mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 15:10:44 +01:00
Handle trade interruption
This commit is contained in:
parent
846cb1869a
commit
fa1fdc3f12
66 changed files with 1660 additions and 1060 deletions
|
@ -56,7 +56,7 @@ public class ArbitrationRepository implements Serializable {
|
|||
|
||||
// Persisted fields
|
||||
private final Map<String, Arbitrator> arbitratorsMap = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
@Inject
|
||||
public ArbitrationRepository(Storage<ArbitrationRepository> storage,
|
||||
|
@ -82,13 +82,13 @@ public class ArbitrationRepository implements Serializable {
|
|||
Arrays.asList(Arbitrator.ID_VERIFICATION.PASSPORT),
|
||||
"https://bitsquare.io",
|
||||
"Bla bla...");
|
||||
|
||||
|
||||
ArbitrationRepository persisted = storage.initAndGetPersisted(this);
|
||||
if (persisted != null) {
|
||||
arbitratorsMap.putAll(persisted.getArbitratorsMap());
|
||||
}
|
||||
arbitratorsMap.put(defaultArbitrator.getId(), defaultArbitrator);
|
||||
|
||||
|
||||
arbitratorsObservableMap.putAll(arbitratorsMap);
|
||||
arbitratorsObservableMap.addListener((MapChangeListener<String, Arbitrator>) change -> storage.queueUpForSave());
|
||||
allArbitratorsSynced = false;
|
||||
|
|
|
@ -59,7 +59,7 @@ public class BitcoinModule extends BitsquareModule {
|
|||
|
||||
@Override
|
||||
protected void doClose(Injector injector) {
|
||||
log.trace("doClose "+getClass().getSimpleName());
|
||||
log.trace("doClose " + getClass().getSimpleName());
|
||||
injector.getInstance(WalletService.class).shutDown();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -398,7 +398,7 @@ public class TradeWalletService {
|
|||
Futures.addCallback(broadcastComplete, callback);
|
||||
}
|
||||
|
||||
// Returns local transaction which has a different state as the serialized publishedDepositTx we get from the offerer
|
||||
// Commits the tx to the wallet and returns that
|
||||
public Transaction commitsDepositTx(Transaction publishedDepositTx) throws VerificationException {
|
||||
log.trace("takerCommitsDepositTx called");
|
||||
log.trace("publishedDepositTx " + publishedDepositTx.toString());
|
||||
|
@ -411,6 +411,14 @@ public class TradeWalletService {
|
|||
return depositTx;
|
||||
}
|
||||
|
||||
// Returns local existing wallet transaction
|
||||
public Transaction getWalletTx(Transaction tx) throws VerificationException {
|
||||
log.trace("getWalleTx called");
|
||||
log.trace("tx " + tx.toString());
|
||||
|
||||
return wallet.getTransaction(tx.getHash());
|
||||
}
|
||||
|
||||
public byte[] offererCreatesAndSignsPayoutTx(Transaction depositTx,
|
||||
Coin offererPayoutAmount,
|
||||
Coin takerPayoutAmount,
|
||||
|
|
|
@ -30,7 +30,7 @@ import org.slf4j.LoggerFactory;
|
|||
public class TaskRunner<T extends Model> {
|
||||
private static final Logger log = LoggerFactory.getLogger(TaskRunner.class);
|
||||
|
||||
private final Queue<Class> tasks = new LinkedBlockingQueue<>();
|
||||
private final Queue<Class<? extends Task>> tasks = new LinkedBlockingQueue<>();
|
||||
protected final T sharedModel;
|
||||
private final ResultHandler resultHandler;
|
||||
private final ErrorMessageHandler errorMessageHandler;
|
||||
|
@ -44,8 +44,8 @@ public class TaskRunner<T extends Model> {
|
|||
this.resultHandler = resultHandler;
|
||||
this.errorMessageHandler = errorMessageHandler;
|
||||
}
|
||||
|
||||
public void addTasks(Class<? extends Task>... items) {
|
||||
|
||||
public final void addTasks(Class<? extends Task>... items) {
|
||||
tasks.addAll(Arrays.asList(items));
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ public class GuiModule extends BitsquareModule {
|
|||
bind(CachingViewLoader.class).in(Singleton.class);
|
||||
|
||||
bind(Navigation.class).in(Singleton.class);
|
||||
|
||||
|
||||
bind(OfferBook.class).in(Singleton.class);
|
||||
bind(OverlayManager.class).in(Singleton.class);
|
||||
bind(BSFormatter.class).in(Singleton.class);
|
||||
|
|
|
@ -143,7 +143,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
|||
acceptedCountriesTextField.setText(model.getAcceptedCountries());
|
||||
acceptedLanguagesTextField.setText(model.getAcceptedLanguages());
|
||||
acceptedArbitratorsTextField.setText(model.getAcceptedArbitratorIds());
|
||||
|
||||
|
||||
showCheckAvailabilityScreen();
|
||||
}
|
||||
|
||||
|
|
|
@ -128,7 +128,6 @@ public class Offer implements Serializable {
|
|||
setState(State.UNKNOWN);
|
||||
}
|
||||
|
||||
// Serialized object does not create our transient objects
|
||||
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
stateProperty = new SimpleObjectProperty<>(state);
|
||||
|
@ -194,7 +193,7 @@ public class Offer implements Serializable {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@NotNull
|
||||
public String getId() {
|
||||
return id;
|
||||
|
@ -282,6 +281,7 @@ public class Offer implements Serializable {
|
|||
", fiatPrice=" + fiatPrice +
|
||||
", amount=" + amount +
|
||||
", minAmount=" + minAmount +
|
||||
", p2pSigPubKey=" + p2pSigPubKey +
|
||||
", fiatAccountType=" + fiatAccountType +
|
||||
", bankAccountCountry=" + bankAccountCountry +
|
||||
", securityDeposit=" + securityDeposit +
|
||||
|
@ -291,7 +291,6 @@ public class Offer implements Serializable {
|
|||
", arbitratorIds=" + arbitratorIds +
|
||||
", offerFeePaymentTxID='" + offerFeePaymentTxID + '\'' +
|
||||
", state=" + state +
|
||||
", stateProperty=" + stateProperty +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,8 +173,13 @@ public class TomP2PAddressService extends TomP2PDHTService implements AddressSer
|
|||
}
|
||||
|
||||
private void removeAddress() {
|
||||
boolean success = removeDataFromMyProtectedDomain(locationKey).awaitUninterruptibly(1000);
|
||||
log.debug("removeDataFromMyProtectedDomain success=" + success);
|
||||
try {
|
||||
boolean success = removeDataFromMyProtectedDomain(locationKey).awaitUninterruptibly(1000);
|
||||
log.debug("removeDataFromMyProtectedDomain success=" + success);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
log.error(t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@ public class TomP2PMessageService extends TomP2PService implements MessageServic
|
|||
|
||||
private void sendMailboxMessage(PublicKey p2pSigPubKey, PublicKey p2pEncryptPubKey, MailboxMessage message, SendMessageListener listener) {
|
||||
Bucket bucket = null;
|
||||
log.info("sendMailboxMessage called");
|
||||
try {
|
||||
bucket = encryptionService.encryptObject(p2pEncryptPubKey, message);
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -273,7 +273,7 @@ public class FileManager<T> {
|
|||
} finally {
|
||||
if (tempFile != null && tempFile.exists()) {
|
||||
log.warn("Temp file still exists after failed save. storageFile=" + storageFile);
|
||||
if (!tempFile.delete())
|
||||
if (!tempFile.delete())
|
||||
log.error("Cannot delete temp file.");
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.security.PublicKey;
|
|||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@Immutable
|
||||
public class Contract implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
|
|
|
@ -20,9 +20,9 @@ package io.bitsquare.trade;
|
|||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.p2p.Peer;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.trade.protocol.trade.TradeProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.ProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.OffererProtocol;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.models.OffererTradeProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.models.OffererProcessModel;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.TransactionConfidence;
|
||||
|
@ -34,6 +34,7 @@ import com.google.common.util.concurrent.Futures;
|
|||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -50,6 +51,7 @@ import org.slf4j.LoggerFactory;
|
|||
public class OffererTrade extends Trade implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
transient private static final Logger log = LoggerFactory.getLogger(OffererTrade.class);
|
||||
|
||||
|
||||
|
@ -78,54 +80,67 @@ public class OffererTrade extends Trade implements Serializable {
|
|||
MESSAGE_SENDING_FAILED,
|
||||
EXCEPTION
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Fields
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Nullable private Coin tradeAmount;
|
||||
@Nullable private Peer tradingPeer;
|
||||
@NotNull private OffererProcessState processState = OffererProcessState.UNDEFINED;
|
||||
@NotNull private OffererLifeCycleState lifeCycleState = OffererLifeCycleState.OFFER_OPEN;
|
||||
@NotNull transient private ObjectProperty<OffererProcessState> processStateProperty = new SimpleObjectProperty<>(processState);
|
||||
@NotNull transient private ObjectProperty<OffererLifeCycleState> lifeCycleStateProperty = new SimpleObjectProperty<>(lifeCycleState);
|
||||
// Transient/Immutable
|
||||
transient private ObjectProperty<OffererProcessState> processStateProperty;
|
||||
transient private ObjectProperty<OffererLifeCycleState> lifeCycleStateProperty;
|
||||
|
||||
// Mutable
|
||||
private Coin tradeAmount;
|
||||
private Peer tradingPeer;
|
||||
private OffererProcessState processState;
|
||||
private OffererLifeCycleState lifeCycleState;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
// Constructor, initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public OffererTrade(@NotNull Offer offer, @NotNull Storage<? extends TradeProcessModel> storage) {
|
||||
public OffererTrade(Offer offer, Storage<? extends TradeList> storage) {
|
||||
super(offer, storage);
|
||||
}
|
||||
log.trace("Created by constructor");
|
||||
|
||||
@Override
|
||||
protected TradeProcessModel createProcessModel() {
|
||||
return new OffererTradeProcessModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createProtocol() {
|
||||
protocol = new OffererProtocol(this);
|
||||
}
|
||||
|
||||
|
||||
// Serialized object does not create our transient objects
|
||||
private void readObject(@NotNull java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
processState = OffererProcessState.UNDEFINED;
|
||||
lifeCycleState = OffererLifeCycleState.OFFER_OPEN;
|
||||
|
||||
processStateProperty = new SimpleObjectProperty<>(processState);
|
||||
lifeCycleStateProperty = new SimpleObjectProperty<>(lifeCycleState);
|
||||
|
||||
tradeAmountProperty = new SimpleObjectProperty<>();
|
||||
tradeVolumeProperty = new SimpleObjectProperty<>();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
log.trace("Created from serialized form.");
|
||||
|
||||
processStateProperty = new SimpleObjectProperty<>(processState);
|
||||
lifeCycleStateProperty = new SimpleObjectProperty<>(lifeCycleState);
|
||||
|
||||
tradeAmountProperty = new SimpleObjectProperty<>();
|
||||
tradeVolumeProperty = new SimpleObjectProperty<>();
|
||||
|
||||
if (tradeAmount != null) {
|
||||
tradeAmountProperty.set(tradeAmount);
|
||||
tradeVolumeProperty.set(getTradeVolume());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProcessModel createProcessModel() {
|
||||
return new OffererProcessModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createProtocol() {
|
||||
protocol = new OffererProtocol(this);
|
||||
}
|
||||
|
||||
public void onFiatPaymentStarted() {
|
||||
assert protocol != null;
|
||||
((OffererProtocol) protocol).onFiatPaymentStarted();
|
||||
|
@ -133,10 +148,29 @@ public class OffererTrade extends Trade implements Serializable {
|
|||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
// Getter only
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setProcessState(@NotNull OffererProcessState processState) {
|
||||
@Override
|
||||
public ReadOnlyObjectProperty<OffererProcessState> processStateProperty() {
|
||||
return processStateProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyObjectProperty<OffererLifeCycleState> lifeCycleStateProperty() {
|
||||
return lifeCycleStateProperty;
|
||||
}
|
||||
|
||||
public OffererProcessModel getProcessModel() {
|
||||
return (OffererProcessModel) processModel;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setter for Mutable objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setProcessState(OffererProcessState processState) {
|
||||
this.processState = processState;
|
||||
processStateProperty.set(processState);
|
||||
|
||||
|
@ -148,7 +182,7 @@ public class OffererTrade extends Trade implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
public void setLifeCycleState(@NotNull OffererLifeCycleState lifeCycleState) {
|
||||
public void setLifeCycleState(OffererLifeCycleState lifeCycleState) {
|
||||
switch (lifeCycleState) {
|
||||
case FAILED:
|
||||
disposeProtocol();
|
||||
|
@ -161,36 +195,24 @@ public class OffererTrade extends Trade implements Serializable {
|
|||
lifeCycleStateProperty.set(lifeCycleState);
|
||||
}
|
||||
|
||||
public void setTradeAmount(@NotNull Coin tradeAmount) {
|
||||
this.tradeAmount = tradeAmount;
|
||||
tradeAmountProperty.set(tradeAmount);
|
||||
tradeVolumeProperty.set(getTradeVolume());
|
||||
}
|
||||
|
||||
public void setTradingPeer(@NotNull Peer tradingPeer) {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter/Setter for Mutable objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setTradingPeer(Peer tradingPeer) {
|
||||
this.tradingPeer = tradingPeer;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@NotNull
|
||||
public OffererTradeProcessModel getProcessModel() {
|
||||
return (OffererTradeProcessModel) processModel;
|
||||
@Nullable
|
||||
public Peer getTradingPeer() {
|
||||
return tradingPeer;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ReadOnlyObjectProperty<OffererProcessState> processStateProperty() {
|
||||
return processStateProperty;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ReadOnlyObjectProperty<OffererLifeCycleState> lifeCycleStateProperty() {
|
||||
return lifeCycleStateProperty;
|
||||
public void setTradeAmount(Coin tradeAmount) {
|
||||
this.tradeAmount = tradeAmount;
|
||||
tradeAmountProperty.set(tradeAmount);
|
||||
tradeVolumeProperty.set(getTradeVolume());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -202,22 +224,19 @@ public class OffererTrade extends Trade implements Serializable {
|
|||
@Nullable
|
||||
@Override
|
||||
public Fiat getTradeVolume() {
|
||||
return offer.getVolumeByAmount(tradeAmount);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Peer getTradingPeer() {
|
||||
return tradingPeer;
|
||||
if (tradeAmount != null)
|
||||
return offer.getVolumeByAmount(tradeAmount);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
// Protected
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void setConfidenceListener() {
|
||||
protected void setupConfidenceListener() {
|
||||
assert depositTx != null;
|
||||
TransactionConfidence transactionConfidence = depositTx.getConfidence();
|
||||
ListenableFuture<TransactionConfidence> future = transactionConfidence.getDepthFuture(1);
|
||||
|
@ -236,4 +255,14 @@ public class OffererTrade extends Trade implements Serializable {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OffererTrade{" +
|
||||
"tradeAmount=" + tradeAmount +
|
||||
", tradingPeer=" + tradingPeer +
|
||||
", processState=" + processState +
|
||||
", lifeCycleState=" + lifeCycleState +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@ package io.bitsquare.trade;
|
|||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.p2p.Peer;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.trade.protocol.trade.TradeProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.ProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.taker.TakerProtocol;
|
||||
import io.bitsquare.trade.protocol.trade.taker.models.TakerTradeProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.taker.models.TakerProcessModel;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.TransactionConfidence;
|
||||
|
@ -48,6 +48,7 @@ import org.slf4j.LoggerFactory;
|
|||
public class TakerTrade extends Trade implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
transient private static final Logger log = LoggerFactory.getLogger(TakerTrade.class);
|
||||
|
||||
|
||||
|
@ -84,33 +85,55 @@ public class TakerTrade extends Trade implements Serializable {
|
|||
// Fields
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@NotNull private final Coin tradeAmount;
|
||||
@NotNull private final Peer tradingPeer;
|
||||
// Transient/Immutable
|
||||
transient private ObjectProperty<TakerProcessState> processStateProperty;
|
||||
transient private ObjectProperty<TakerLifeCycleState> lifeCycleStateProperty;
|
||||
|
||||
@NotNull private TakerProcessState processState = TakerProcessState.UNDEFINED;
|
||||
@NotNull private TakerLifeCycleState lifeCycleState = TakerLifeCycleState.PENDING;
|
||||
// Immutable
|
||||
private final Coin tradeAmount;
|
||||
private final Peer tradingPeer;
|
||||
|
||||
@NotNull transient private ObjectProperty<TakerProcessState> processStateProperty = new SimpleObjectProperty<>(processState);
|
||||
@NotNull transient private ObjectProperty<TakerLifeCycleState> lifeCycleStateProperty = new SimpleObjectProperty<>(lifeCycleState);
|
||||
// Mutable
|
||||
private TakerProcessState processState;
|
||||
private TakerLifeCycleState lifeCycleState;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
// Constructor, initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public TakerTrade(@NotNull Offer offer, @NotNull Coin tradeAmount, @NotNull Peer peer,
|
||||
@NotNull Storage<? extends TradeProcessModel> storage) {
|
||||
public TakerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer,
|
||||
Storage<? extends TradeList> storage) {
|
||||
super(offer, storage);
|
||||
log.trace("Created by constructor");
|
||||
|
||||
this.tradeAmount = tradeAmount;
|
||||
this.tradingPeer = peer;
|
||||
this.tradingPeer = tradingPeer;
|
||||
|
||||
processState = TakerProcessState.UNDEFINED;
|
||||
lifeCycleState = TakerLifeCycleState.PENDING;
|
||||
|
||||
processStateProperty = new SimpleObjectProperty<>(processState);
|
||||
lifeCycleStateProperty = new SimpleObjectProperty<>(lifeCycleState);
|
||||
|
||||
tradeAmountProperty = new SimpleObjectProperty<>(tradeAmount);
|
||||
tradeVolumeProperty = new SimpleObjectProperty<>(getTradeVolume()); // cannot be set before offer is set
|
||||
tradeVolumeProperty = new SimpleObjectProperty<>(getTradeVolume());
|
||||
}
|
||||
|
||||
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
log.trace("Created from serialized form.");
|
||||
|
||||
processStateProperty = new SimpleObjectProperty<>(processState);
|
||||
lifeCycleStateProperty = new SimpleObjectProperty<>(lifeCycleState);
|
||||
|
||||
tradeAmountProperty = new SimpleObjectProperty<>(tradeAmount);
|
||||
tradeVolumeProperty = new SimpleObjectProperty<>(getTradeVolume());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TradeProcessModel createProcessModel() {
|
||||
return new TakerTradeProcessModel();
|
||||
protected ProcessModel createProcessModel() {
|
||||
return new TakerProcessModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -118,21 +141,16 @@ public class TakerTrade extends Trade implements Serializable {
|
|||
protocol = new TakerProtocol(this);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void takeAvailableOffer() {
|
||||
assert processModel != null;
|
||||
((TakerProtocol) protocol).takeAvailableOffer();
|
||||
}
|
||||
|
||||
// Serialized object does not create our transient objects
|
||||
private void readObject(@NotNull java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
|
||||
processStateProperty = new SimpleObjectProperty<>(processState);
|
||||
lifeCycleStateProperty = new SimpleObjectProperty<>(lifeCycleState);
|
||||
tradeAmountProperty = new SimpleObjectProperty<>(tradeAmount);
|
||||
tradeVolumeProperty = new SimpleObjectProperty<>(getTradeVolume());
|
||||
}
|
||||
|
||||
public void onFiatPaymentReceived() {
|
||||
assert protocol != null;
|
||||
((TakerProtocol) protocol).onFiatPaymentReceived();
|
||||
|
@ -140,53 +158,9 @@ public class TakerTrade extends Trade implements Serializable {
|
|||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
// Getter only
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setLifeCycleState(@NotNull TakerLifeCycleState lifeCycleState) {
|
||||
this.lifeCycleState = lifeCycleState;
|
||||
lifeCycleStateProperty.set(lifeCycleState);
|
||||
}
|
||||
|
||||
public void setProcessState(@NotNull TakerProcessState processState) {
|
||||
this.processState = processState;
|
||||
processStateProperty.set(processState);
|
||||
|
||||
if (processState == TakerProcessState.EXCEPTION) {
|
||||
setLifeCycleState(TakerLifeCycleState.FAILED);
|
||||
disposeProtocol();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThrowable(@NotNull Throwable throwable) {
|
||||
super.setThrowable(throwable);
|
||||
setProcessState(TakerTrade.TakerProcessState.EXCEPTION);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@NotNull
|
||||
public TakerTradeProcessModel getProcessModel() {
|
||||
return (TakerTradeProcessModel) processModel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ReadOnlyObjectProperty<TakerProcessState> processStateProperty() {
|
||||
return processStateProperty;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ReadOnlyObjectProperty<TakerLifeCycleState> lifeCycleStateProperty() {
|
||||
return lifeCycleStateProperty;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Coin getTradeAmount() {
|
||||
return tradeAmount;
|
||||
|
@ -197,21 +171,57 @@ public class TakerTrade extends Trade implements Serializable {
|
|||
return offer.getVolumeByAmount(tradeAmount);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Peer getTradingPeer() {
|
||||
return tradingPeer;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Override
|
||||
public ReadOnlyObjectProperty<TakerProcessState> processStateProperty() {
|
||||
return processStateProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setConfidenceListener() {
|
||||
public ReadOnlyObjectProperty<TakerLifeCycleState> lifeCycleStateProperty() {
|
||||
return lifeCycleStateProperty;
|
||||
}
|
||||
|
||||
public TakerProcessModel getProcessModel() {
|
||||
return (TakerProcessModel) processModel;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setter for Mutable objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setLifeCycleState(TakerLifeCycleState lifeCycleState) {
|
||||
this.lifeCycleState = lifeCycleState;
|
||||
lifeCycleStateProperty.set(lifeCycleState);
|
||||
}
|
||||
|
||||
public void setProcessState(TakerProcessState processState) {
|
||||
this.processState = processState;
|
||||
processStateProperty.set(processState);
|
||||
|
||||
if (processState == TakerProcessState.EXCEPTION) {
|
||||
setLifeCycleState(TakerLifeCycleState.FAILED);
|
||||
disposeProtocol();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThrowable(Throwable throwable) {
|
||||
super.setThrowable(throwable);
|
||||
setProcessState(TakerTrade.TakerProcessState.EXCEPTION);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void setupConfidenceListener() {
|
||||
assert depositTx != null;
|
||||
TransactionConfidence transactionConfidence = depositTx.getConfidence();
|
||||
ListenableFuture<TransactionConfidence> future = transactionConfidence.getDepthFuture(1);
|
||||
|
@ -230,4 +240,14 @@ public class TakerTrade extends Trade implements Serializable {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TakerTrade{" +
|
||||
"tradeAmount=" + tradeAmount +
|
||||
", tradingPeer=" + tradingPeer +
|
||||
", processState=" + processState +
|
||||
", lifeCycleState=" + lifeCycleState +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,18 +25,18 @@ import io.bitsquare.common.taskrunner.Model;
|
|||
import io.bitsquare.crypto.SignatureService;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.p2p.MailboxMessage;
|
||||
import io.bitsquare.p2p.MailboxService;
|
||||
import io.bitsquare.p2p.MessageService;
|
||||
import io.bitsquare.p2p.Peer;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.trade.protocol.Protocol;
|
||||
import io.bitsquare.trade.protocol.trade.TradeProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.ProcessModel;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.utils.Fiat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.Date;
|
||||
|
@ -45,9 +45,6 @@ import javax.annotation.Nullable;
|
|||
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -60,7 +57,7 @@ abstract public class Trade extends Model implements Serializable {
|
|||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
transient protected static final Logger log = LoggerFactory.getLogger(Trade.class);
|
||||
private transient static final Logger log = LoggerFactory.getLogger(Trade.class);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -78,53 +75,59 @@ abstract public class Trade extends Model implements Serializable {
|
|||
// Fields
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Transient/Immutable
|
||||
transient private Storage<? extends TradeList> storage;
|
||||
transient protected Protocol protocol;
|
||||
|
||||
// Immutable
|
||||
protected final Offer offer;
|
||||
@NotNull private final Date date;
|
||||
@NotNull protected TradeProcessModel processModel = createProcessModel();
|
||||
private final Date date;
|
||||
protected final ProcessModel processModel;
|
||||
|
||||
protected abstract TradeProcessModel createProcessModel();
|
||||
// Mutable
|
||||
private MailboxMessage mailboxMessage;
|
||||
protected Transaction depositTx;
|
||||
private Contract contract;
|
||||
private String contractAsJson;
|
||||
private String takerContractSignature;
|
||||
private String offererContractSignature;
|
||||
private Transaction payoutTx;
|
||||
|
||||
@NotNull transient protected Protocol protocol;
|
||||
|
||||
@Nullable MailboxMessage mailboxMessage;
|
||||
@Nullable Transaction depositTx;
|
||||
@Nullable private Transaction payoutTx;
|
||||
@Nullable private Contract contract;
|
||||
@Nullable private String contractAsJson;
|
||||
@Nullable private String takerContractSignature;
|
||||
@Nullable private String offererContractSignature;
|
||||
|
||||
@NotNull transient private Storage<? extends TradeProcessModel> storage;
|
||||
|
||||
@Nullable private transient String errorMessage;
|
||||
@Nullable private transient Throwable throwable;
|
||||
@NotNull transient ObjectProperty<Coin> tradeAmountProperty = new SimpleObjectProperty<>();
|
||||
@NotNull transient ObjectProperty<Fiat> tradeVolumeProperty = new SimpleObjectProperty<>();
|
||||
// Transient/Mutable
|
||||
transient private String errorMessage;
|
||||
transient private Throwable throwable;
|
||||
transient protected ObjectProperty<Coin> tradeAmountProperty;
|
||||
transient protected ObjectProperty<Fiat> tradeVolumeProperty;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
// Constructor, initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Trade(Offer offer, @NotNull Storage<? extends TradeProcessModel> storage) {
|
||||
Trade(Offer offer, Storage<? extends TradeList> storage) {
|
||||
log.trace("Created by constructor");
|
||||
this.offer = offer;
|
||||
this.storage = storage;
|
||||
|
||||
date = new Date();
|
||||
processModel = createProcessModel();
|
||||
}
|
||||
|
||||
public void initProcessModel(@NotNull MessageService messageService,
|
||||
@NotNull MailboxService mailboxService,
|
||||
@NotNull WalletService walletService,
|
||||
@NotNull TradeWalletService tradeWalletService,
|
||||
@NotNull BlockChainService blockChainService,
|
||||
@NotNull SignatureService signatureService,
|
||||
@NotNull ArbitrationRepository arbitrationRepository,
|
||||
@NotNull User user) {
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
log.trace("Created from serialized form.");
|
||||
}
|
||||
|
||||
processModel.init(offer,
|
||||
public void init(MessageService messageService,
|
||||
WalletService walletService,
|
||||
TradeWalletService tradeWalletService,
|
||||
BlockChainService blockChainService,
|
||||
SignatureService signatureService,
|
||||
ArbitrationRepository arbitrationRepository,
|
||||
User user) {
|
||||
|
||||
processModel.onAllServicesInitialized(offer,
|
||||
messageService,
|
||||
mailboxService,
|
||||
walletService,
|
||||
tradeWalletService,
|
||||
blockChainService,
|
||||
|
@ -133,25 +136,33 @@ abstract public class Trade extends Model implements Serializable {
|
|||
user);
|
||||
|
||||
createProtocol();
|
||||
|
||||
|
||||
if (mailboxMessage != null)
|
||||
protocol.setMailboxMessage(mailboxMessage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setStorage(Storage<? extends TradeList> storage) {
|
||||
this.storage = storage;
|
||||
}
|
||||
|
||||
abstract protected ProcessModel createProcessModel();
|
||||
|
||||
abstract protected void createProtocol();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// The deserialized tx has not actual confidence data, so we need to get the fresh one from the wallet.
|
||||
public void syncDepositTxWithWallet(@NotNull TradeWalletService tradeWalletService) {
|
||||
public void updateDepositTxFromWallet(TradeWalletService tradeWalletService) {
|
||||
if (depositTx != null)
|
||||
setDepositTx(tradeWalletService.commitsDepositTx(depositTx));
|
||||
setDepositTx(tradeWalletService.getWalletTx(depositTx));
|
||||
}
|
||||
|
||||
public void setDepositTx(@NotNull Transaction tx) {
|
||||
public void setDepositTx(Transaction tx) {
|
||||
this.depositTx = tx;
|
||||
setConfidenceListener();
|
||||
setupConfidenceListener();
|
||||
}
|
||||
|
||||
public void disposeProtocol() {
|
||||
|
@ -161,15 +172,15 @@ abstract public class Trade extends Model implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
public void setMailboxMessage(@NotNull MailboxMessage mailboxMessage) {
|
||||
public void setMailboxMessage(MailboxMessage mailboxMessage) {
|
||||
this.mailboxMessage = mailboxMessage;
|
||||
assert protocol != null;
|
||||
protocol.setMailboxMessage(mailboxMessage);
|
||||
if (protocol != null)
|
||||
protocol.setMailboxMessage(mailboxMessage);
|
||||
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
public void setStorage(@NotNull Storage<? extends TradeProcessModel> storage) {
|
||||
this.storage = storage;
|
||||
}
|
||||
protected abstract void setupConfidenceListener();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -187,72 +198,13 @@ abstract public class Trade extends Model implements Serializable {
|
|||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected abstract void setConfidenceListener();
|
||||
|
||||
public void setTakerContractSignature(@NotNull String takerSignature) {
|
||||
this.takerContractSignature = takerSignature;
|
||||
}
|
||||
|
||||
public void setOffererContractSignature(@NotNull String offererContractSignature) {
|
||||
this.offererContractSignature = offererContractSignature;
|
||||
}
|
||||
|
||||
public void setContractAsJson(@NotNull String contractAsJson) {
|
||||
this.contractAsJson = contractAsJson;
|
||||
}
|
||||
|
||||
public void setContract(@NotNull Contract contract) {
|
||||
this.contract = contract;
|
||||
}
|
||||
|
||||
public void setPayoutTx(@NotNull Transaction tx) {
|
||||
this.payoutTx = tx;
|
||||
}
|
||||
|
||||
public void setErrorMessage(@NotNull String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public void setThrowable(@NotNull Throwable throwable) {
|
||||
this.throwable = throwable;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
// Getter only
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Nullable
|
||||
public String getTakerContractSignature() {
|
||||
return takerContractSignature;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getOffererContractSignature() {
|
||||
return offererContractSignature;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Transaction getDepositTx() {
|
||||
return depositTx;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Transaction getPayoutTx() {
|
||||
return payoutTx;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Contract getContract() {
|
||||
return contract;
|
||||
}
|
||||
|
||||
public Coin getSecurityDeposit() {
|
||||
return offer.getSecurityDeposit();
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
|
@ -263,14 +215,86 @@ abstract public class Trade extends Model implements Serializable {
|
|||
return offer;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Transaction getDepositTx() {
|
||||
return depositTx;
|
||||
}
|
||||
|
||||
public Coin getSecurityDeposit() {
|
||||
return offer.getSecurityDeposit();
|
||||
}
|
||||
|
||||
public ReadOnlyObjectProperty<Coin> tradeAmountProperty() {
|
||||
return tradeAmountProperty;
|
||||
}
|
||||
|
||||
|
||||
public ReadOnlyObjectProperty<Fiat> tradeVolumeProperty() {
|
||||
return tradeVolumeProperty;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
abstract public Coin getTradeAmount();
|
||||
|
||||
@Nullable
|
||||
abstract public Fiat getTradeVolume();
|
||||
|
||||
abstract public ReadOnlyObjectProperty<? extends ProcessState> processStateProperty();
|
||||
|
||||
abstract public ReadOnlyObjectProperty<? extends LifeCycleState> lifeCycleStateProperty();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter/Setter for Mutable objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setTakerContractSignature(String takerSignature) {
|
||||
this.takerContractSignature = takerSignature;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTakerContractSignature() {
|
||||
return takerContractSignature;
|
||||
}
|
||||
|
||||
public void setOffererContractSignature(String offererContractSignature) {
|
||||
this.offererContractSignature = offererContractSignature;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getOffererContractSignature() {
|
||||
return offererContractSignature;
|
||||
}
|
||||
|
||||
public void setContractAsJson(String contractAsJson) {
|
||||
this.contractAsJson = contractAsJson;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getContractAsJson() {
|
||||
return contractAsJson;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Date getDate() {
|
||||
return date;
|
||||
public void setContract(Contract contract) {
|
||||
this.contract = contract;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Contract getContract() {
|
||||
return contract;
|
||||
}
|
||||
|
||||
public void setPayoutTx(Transaction payoutTx) {
|
||||
this.payoutTx = payoutTx;
|
||||
}
|
||||
|
||||
// Not used now, but will be used in some reporting UI
|
||||
public Transaction getPayoutTx() {
|
||||
return payoutTx;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -278,53 +302,30 @@ abstract public class Trade extends Model implements Serializable {
|
|||
return errorMessage;
|
||||
}
|
||||
|
||||
|
||||
public void setThrowable(Throwable throwable) {
|
||||
this.throwable = throwable;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Throwable getThrowable() {
|
||||
return throwable;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ReadOnlyObjectProperty<Coin> tradeAmountProperty() {
|
||||
return tradeAmountProperty;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ReadOnlyObjectProperty<Fiat> tradeVolumeProperty() {
|
||||
return tradeVolumeProperty;
|
||||
}
|
||||
|
||||
abstract void createProtocol();
|
||||
|
||||
@NotNull
|
||||
public abstract ReadOnlyObjectProperty<? extends ProcessState> processStateProperty();
|
||||
|
||||
@NotNull
|
||||
public abstract ReadOnlyObjectProperty<? extends LifeCycleState> lifeCycleStateProperty();
|
||||
|
||||
@org.jetbrains.annotations.Nullable
|
||||
public abstract Coin getTradeAmount();
|
||||
|
||||
@org.jetbrains.annotations.Nullable
|
||||
public abstract Fiat getTradeVolume();
|
||||
|
||||
@org.jetbrains.annotations.Nullable
|
||||
public abstract Peer getTradingPeer();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Trade{" +
|
||||
"protocol=" + protocol +
|
||||
", mailboxMessage=" + mailboxMessage +
|
||||
"throwable=" + throwable +
|
||||
", offer=" + offer +
|
||||
", date=" + date +
|
||||
", mailboxMessage=" + mailboxMessage +
|
||||
", depositTx=" + depositTx +
|
||||
", contract=" + contract +
|
||||
", contractAsJson='" + contractAsJson + '\'' +
|
||||
", takerContractSignature='" + takerContractSignature + '\'' +
|
||||
", offererContractSignature='" + offererContractSignature + '\'' +
|
||||
", depositTx=" + depositTx +
|
||||
", payoutTx=" + payoutTx +
|
||||
", errorMessage='" + errorMessage + '\'' +
|
||||
", processModel=" + processModel +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -19,6 +19,8 @@ package io.bitsquare.trade;
|
|||
|
||||
import io.bitsquare.storage.Storage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -36,6 +38,7 @@ public class TradeList<T> extends ArrayList<T> implements Serializable {
|
|||
transient private static final Logger log = LoggerFactory.getLogger(TradeList.class);
|
||||
|
||||
transient final private Storage<TradeList> storage;
|
||||
// Use getObservableList() also class locally, to be sure that object exists in case we use the object as deserialized form
|
||||
transient private ObservableList<T> observableList;
|
||||
|
||||
// Superclass is ArrayList, which will be persisted
|
||||
|
@ -45,6 +48,7 @@ public class TradeList<T> extends ArrayList<T> implements Serializable {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public TradeList(Storage<TradeList> storage, String fileName) {
|
||||
log.trace("Created by constructor");
|
||||
this.storage = storage;
|
||||
|
||||
TradeList persisted = storage.initAndGetPersisted(this, fileName);
|
||||
|
@ -54,10 +58,15 @@ public class TradeList<T> extends ArrayList<T> implements Serializable {
|
|||
observableList = FXCollections.observableArrayList(this);
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
log.trace("Created from serialized form.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T trade) {
|
||||
boolean result = super.add(trade);
|
||||
observableList.add(trade);
|
||||
getObservableList().add(trade);
|
||||
storage.queueUpForSave();
|
||||
return result;
|
||||
}
|
||||
|
@ -65,12 +74,14 @@ public class TradeList<T> extends ArrayList<T> implements Serializable {
|
|||
@Override
|
||||
public boolean remove(Object trade) {
|
||||
boolean result = super.remove(trade);
|
||||
observableList.remove(trade);
|
||||
getObservableList().remove(trade);
|
||||
storage.queueUpForSave();
|
||||
return result;
|
||||
}
|
||||
|
||||
public ObservableList<T> getObservableList() {
|
||||
if (observableList == null)
|
||||
observableList = FXCollections.observableArrayList(this);
|
||||
return observableList;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ import io.bitsquare.p2p.EncryptedMailboxMessage;
|
|||
import io.bitsquare.p2p.MailboxMessage;
|
||||
import io.bitsquare.p2p.MailboxService;
|
||||
import io.bitsquare.p2p.MessageService;
|
||||
import io.bitsquare.p2p.Peer;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.trade.handlers.TakeOfferResultHandler;
|
||||
import io.bitsquare.trade.handlers.TransactionResultHandler;
|
||||
|
@ -89,8 +88,8 @@ public class TradeManager {
|
|||
private final ArbitrationRepository arbitrationRepository;
|
||||
|
||||
private final Map<String, CheckOfferAvailabilityProtocol> checkOfferAvailabilityProtocolMap = new HashMap<>();
|
||||
private final Storage pendingTradesStorage;
|
||||
private final Storage openOfferTradesStorage;
|
||||
private final Storage<TradeList> pendingTradesStorage;
|
||||
private final Storage<TradeList> openOfferTradesStorage;
|
||||
private final TradeList<OffererTrade> openOfferTrades;
|
||||
private final TradeList<Trade> pendingTrades;
|
||||
private final TradeList<Trade> closedTrades;
|
||||
|
@ -129,12 +128,12 @@ public class TradeManager {
|
|||
this.offerBookService = offerBookService;
|
||||
this.arbitrationRepository = arbitrationRepository;
|
||||
|
||||
openOfferTradesStorage = new Storage(storageDir);
|
||||
pendingTradesStorage = new Storage(storageDir);
|
||||
openOfferTradesStorage = new Storage<>(storageDir);
|
||||
pendingTradesStorage = new Storage<>(storageDir);
|
||||
|
||||
this.openOfferTrades = new TradeList<>(openOfferTradesStorage, "OpenOfferTrades");
|
||||
this.pendingTrades = new TradeList<>(pendingTradesStorage, "PendingTrades");
|
||||
this.closedTrades = new TradeList<>(new Storage(storageDir), "ClosedTrades");
|
||||
this.closedTrades = new TradeList<>(new Storage<>(storageDir), "ClosedTrades");
|
||||
|
||||
|
||||
// In case the app did get killed the shutDown from the modules is not called, so we use a shutdown hook
|
||||
|
@ -144,9 +143,66 @@ public class TradeManager {
|
|||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public API
|
||||
// Lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// When all services are initialized we create the protocols for our open offers and persisted pendingTrades
|
||||
// OffererAsBuyerProtocol listens for take offer requests, so we need to instantiate it early.
|
||||
public void onAllServicesInitialized() {
|
||||
for (OffererTrade offererTrade : openOfferTrades) {
|
||||
Offer offer = offererTrade.getOffer();
|
||||
// We add own offers to offerbook when we go online again
|
||||
offerBookService.addOffer(offer,
|
||||
() -> log.debug("Successful removed open offer from DHT"),
|
||||
(message, throwable) -> log.error("Remove open offer from DHT failed. " + message));
|
||||
offererTrade.setStorage(openOfferTradesStorage);
|
||||
initTrade(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.
|
||||
initTrade(trade);
|
||||
trade.updateDepositTxFromWallet(tradeWalletService);
|
||||
trade.setStorage(pendingTradesStorage);
|
||||
}
|
||||
|
||||
// if there are messages in our mailbox we apply it and remove them from the DHT
|
||||
mailboxService.getAllMessages(user.getP2PSigPubKey(),
|
||||
(encryptedMailboxMessages) -> {
|
||||
setMailboxMessagesToTrades(encryptedMailboxMessages);
|
||||
emptyMailbox();
|
||||
});
|
||||
}
|
||||
|
||||
private void setMailboxMessagesToTrades(List<EncryptedMailboxMessage> encryptedMailboxMessages) {
|
||||
log.trace("applyMailboxMessage encryptedMailboxMessage.size=" + encryptedMailboxMessages.size());
|
||||
for (EncryptedMailboxMessage encrypted : encryptedMailboxMessages) {
|
||||
try {
|
||||
MailboxMessage mailboxMessage = encryptionService.decryptToObject(user.getP2pEncryptPrivateKey(), encrypted.getBucket());
|
||||
|
||||
if (mailboxMessage instanceof TradeMessage) {
|
||||
String tradeId = ((TradeMessage) mailboxMessage).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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void emptyMailbox() {
|
||||
mailboxService.removeAllMessages(user.getP2PSigPubKey(),
|
||||
() -> log.debug("All mailbox entries removed"),
|
||||
(errorMessage, fault) -> {
|
||||
log.error(errorMessage);
|
||||
log.error(fault.getMessage());
|
||||
});
|
||||
}
|
||||
|
||||
public void shutDown() {
|
||||
if (!shutDownRequested) {
|
||||
|
@ -160,50 +216,6 @@ public class TradeManager {
|
|||
}
|
||||
}
|
||||
|
||||
// When all services are initialized we create the protocols for our open offers and persisted not completed pendingTrades
|
||||
// OffererAsBuyerProtocol listens for take offer requests, so we need to instantiate it early.
|
||||
public void onAllServicesInitialized() {
|
||||
|
||||
for (OffererTrade offererTrade : openOfferTrades) {
|
||||
Offer offer = offererTrade.getOffer();
|
||||
// we add own offers to offerbook when we go online again
|
||||
offerBookService.addOffer(offer,
|
||||
() -> log.debug("Successful removed open offer from DHT"),
|
||||
(message, throwable) -> log.error("Remove open offer from DHT failed. " + message));
|
||||
offererTrade.setStorage(openOfferTradesStorage);
|
||||
offererTrade.initProcessModel(messageService,
|
||||
mailboxService,
|
||||
walletService,
|
||||
tradeWalletService,
|
||||
blockChainService,
|
||||
signatureService,
|
||||
arbitrationRepository,
|
||||
user);
|
||||
|
||||
}
|
||||
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.
|
||||
trade.initProcessModel(messageService,
|
||||
mailboxService,
|
||||
walletService,
|
||||
tradeWalletService,
|
||||
blockChainService,
|
||||
signatureService,
|
||||
arbitrationRepository,
|
||||
user);
|
||||
trade.syncDepositTxWithWallet(tradeWalletService);
|
||||
trade.setStorage(pendingTradesStorage);
|
||||
}
|
||||
|
||||
mailboxService.getAllMessages(user.getP2PSigPubKey(),
|
||||
(encryptedMailboxMessages) -> {
|
||||
decryptMailboxMessages(encryptedMailboxMessages);
|
||||
emptyMailbox();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Offer
|
||||
|
@ -217,17 +229,17 @@ public class TradeManager {
|
|||
TransactionResultHandler resultHandler,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
|
||||
FiatAccount currentFiatAccount = user.currentFiatAccountProperty().get();
|
||||
FiatAccount fiatAccount = user.currentFiatAccountProperty().get();
|
||||
Offer offer = new Offer(id,
|
||||
user.getP2PSigPubKey(),
|
||||
direction,
|
||||
price.getValue(),
|
||||
amount,
|
||||
minAmount,
|
||||
currentFiatAccount.type,
|
||||
currentFiatAccount.currencyCode,
|
||||
currentFiatAccount.country,
|
||||
currentFiatAccount.id,
|
||||
fiatAccount.type,
|
||||
fiatAccount.currencyCode,
|
||||
fiatAccount.country,
|
||||
fiatAccount.id,
|
||||
accountSettings.getAcceptedArbitratorIds(),
|
||||
accountSettings.getSecurityDeposit(),
|
||||
accountSettings.getAcceptedCountries(),
|
||||
|
@ -237,42 +249,63 @@ public class TradeManager {
|
|||
|
||||
PlaceOfferProtocol placeOfferProtocol = new PlaceOfferProtocol(
|
||||
model,
|
||||
(transaction) -> {
|
||||
OffererTrade offererTrade = new OffererTrade(offer, openOfferTradesStorage);
|
||||
openOfferTrades.add(offererTrade);
|
||||
offererTrade.initProcessModel(messageService,
|
||||
mailboxService,
|
||||
walletService,
|
||||
tradeWalletService,
|
||||
blockChainService,
|
||||
signatureService,
|
||||
arbitrationRepository,
|
||||
user);
|
||||
|
||||
offererTrade.processStateProperty().addListener((ov, oldValue, newValue) -> {
|
||||
log.debug("offererTrade state = " + newValue);
|
||||
if (newValue == OffererTrade.OffererProcessState.DEPOSIT_PUBLISHED) {
|
||||
removeOpenOffer(offererTrade.getOffer(),
|
||||
() -> log.debug("remove offer was successful"),
|
||||
(message) -> log.error(message),
|
||||
false);
|
||||
pendingTrades.add(offererTrade);
|
||||
offererTrade.setStorage(pendingTradesStorage);
|
||||
}
|
||||
});
|
||||
|
||||
resultHandler.handleResult(transaction);
|
||||
},
|
||||
(message) -> errorMessageHandler.handleErrorMessage(message)
|
||||
transaction -> handlePlaceOfferResult(transaction, offer, resultHandler),
|
||||
errorMessageHandler::handleErrorMessage
|
||||
);
|
||||
|
||||
placeOfferProtocol.placeOffer();
|
||||
}
|
||||
|
||||
private void handlePlaceOfferResult(Transaction transaction, Offer offer, TransactionResultHandler resultHandler) {
|
||||
OffererTrade offererTrade = new OffererTrade(offer, openOfferTradesStorage);
|
||||
openOfferTrades.add(offererTrade);
|
||||
initTrade(offererTrade);
|
||||
|
||||
offererTrade.processStateProperty().addListener((ov, oldValue, newValue) -> {
|
||||
log.debug("offererTrade state = " + newValue);
|
||||
if (newValue == OffererTrade.OffererProcessState.DEPOSIT_PUBLISHED) {
|
||||
removeOpenOffer(offererTrade.getOffer(),
|
||||
() -> log.debug("remove offer was successful"),
|
||||
log::error,
|
||||
false);
|
||||
pendingTrades.add(offererTrade);
|
||||
offererTrade.setStorage(pendingTradesStorage);
|
||||
}
|
||||
});
|
||||
|
||||
resultHandler.handleResult(transaction);
|
||||
}
|
||||
|
||||
public void cancelOpenOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
removeOpenOffer(offer, resultHandler, errorMessageHandler, true);
|
||||
}
|
||||
|
||||
private void removeOpenOffer(Offer offer,
|
||||
ResultHandler resultHandler,
|
||||
ErrorMessageHandler errorMessageHandler,
|
||||
boolean isCancelRequest) {
|
||||
offerBookService.removeOffer(offer,
|
||||
() -> {
|
||||
offer.setState(Offer.State.REMOVED);
|
||||
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) {
|
||||
offererTrade.setLifeCycleState(OffererTrade.OffererLifeCycleState.OFFER_CANCELED);
|
||||
closedTrades.add(offererTrade);
|
||||
offererTrade.disposeProtocol();
|
||||
}
|
||||
}
|
||||
|
||||
disposeCheckOfferAvailabilityRequest(offer);
|
||||
|
||||
resultHandler.handleResult();
|
||||
},
|
||||
(message, throwable) -> errorMessageHandler.handleErrorMessage(message));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Take offer
|
||||
|
@ -305,18 +338,24 @@ public class TradeManager {
|
|||
public void requestTakeOffer(Coin amount, Offer offer, TakeOfferResultHandler takeOfferResultHandler) {
|
||||
CheckOfferAvailabilityModel model = new CheckOfferAvailabilityModel(offer, messageService, addressService);
|
||||
CheckOfferAvailabilityProtocol availabilityProtocol = new CheckOfferAvailabilityProtocol(model,
|
||||
() -> {
|
||||
disposeCheckOfferAvailabilityRequest(offer);
|
||||
if (offer.getState() == Offer.State.AVAILABLE) {
|
||||
TakerTrade trade = takeAvailableOffer(amount, offer, model.getPeer());
|
||||
takeOfferResultHandler.handleResult(trade);
|
||||
}
|
||||
},
|
||||
() -> handleCheckOfferAvailabilityResult(amount, offer, model, takeOfferResultHandler),
|
||||
(errorMessage) -> disposeCheckOfferAvailabilityRequest(offer));
|
||||
checkOfferAvailabilityProtocolMap.put(offer.getId(), availabilityProtocol);
|
||||
availabilityProtocol.checkOfferAvailability();
|
||||
}
|
||||
|
||||
private void handleCheckOfferAvailabilityResult(Coin amount, Offer offer, CheckOfferAvailabilityModel model, TakeOfferResultHandler
|
||||
takeOfferResultHandler) {
|
||||
disposeCheckOfferAvailabilityRequest(offer);
|
||||
if (offer.getState() == Offer.State.AVAILABLE) {
|
||||
TakerTrade takerTrade = new TakerTrade(offer, amount, model.getPeer(), pendingTradesStorage);
|
||||
initTrade(takerTrade);
|
||||
pendingTrades.add(takerTrade);
|
||||
takerTrade.takeAvailableOffer();
|
||||
takeOfferResultHandler.handleResult(takerTrade);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Trade
|
||||
|
@ -328,8 +367,9 @@ public class TradeManager {
|
|||
|
||||
// TODO handle overpaid securityDeposit
|
||||
Coin amountToWithdraw = trade.getSecurityDeposit();
|
||||
assert trade.getTradeAmount() != null;
|
||||
if (trade instanceof OffererTrade)
|
||||
amountToWithdraw = amountToWithdraw.add(((OffererTrade) trade).getTradeAmount());
|
||||
amountToWithdraw = amountToWithdraw.add(trade.getTradeAmount());
|
||||
|
||||
FutureCallback<Transaction> callback = new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
|
@ -392,35 +432,9 @@ public class TradeManager {
|
|||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
// Misc
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void removeOpenOffer(Offer offer,
|
||||
ResultHandler resultHandler,
|
||||
ErrorMessageHandler errorMessageHandler,
|
||||
boolean isCancelRequest) {
|
||||
offerBookService.removeOffer(offer,
|
||||
() -> {
|
||||
offer.setState(Offer.State.REMOVED);
|
||||
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) {
|
||||
offererTrade.setLifeCycleState(OffererTrade.OffererLifeCycleState.OFFER_CANCELED);
|
||||
closedTrades.add(offererTrade);
|
||||
offererTrade.disposeProtocol();
|
||||
}
|
||||
}
|
||||
|
||||
disposeCheckOfferAvailabilityRequest(offer);
|
||||
|
||||
resultHandler.handleResult();
|
||||
},
|
||||
(message, throwable) -> errorMessageHandler.handleErrorMessage(message));
|
||||
}
|
||||
|
||||
private void disposeCheckOfferAvailabilityRequest(Offer offer) {
|
||||
if (checkOfferAvailabilityProtocolMap.containsKey(offer.getId())) {
|
||||
CheckOfferAvailabilityProtocol protocol = checkOfferAvailabilityProtocolMap.get(offer.getId());
|
||||
|
@ -429,57 +443,14 @@ public class TradeManager {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Trade
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private TakerTrade takeAvailableOffer(Coin amount, Offer offer, Peer peer) {
|
||||
TakerTrade takerTrade = new TakerTrade(offer, amount, peer, pendingTradesStorage);
|
||||
takerTrade.initProcessModel(messageService,
|
||||
mailboxService,
|
||||
private void initTrade(Trade trade) {
|
||||
trade.init(messageService,
|
||||
walletService,
|
||||
tradeWalletService,
|
||||
blockChainService,
|
||||
signatureService,
|
||||
arbitrationRepository,
|
||||
user);
|
||||
pendingTrades.add(takerTrade);
|
||||
takerTrade.takeAvailableOffer();
|
||||
return takerTrade;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Mailbox
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void decryptMailboxMessages(List<EncryptedMailboxMessage> encryptedMailboxMessages) {
|
||||
log.trace("applyMailboxMessage encryptedMailboxMessage.size=" + encryptedMailboxMessages.size());
|
||||
for (EncryptedMailboxMessage encrypted : encryptedMailboxMessages) {
|
||||
try {
|
||||
MailboxMessage mailboxMessage = encryptionService.decryptToObject(user.getP2pEncryptPrivateKey(), encrypted.getBucket());
|
||||
|
||||
if (mailboxMessage instanceof TradeMessage) {
|
||||
String tradeId = ((TradeMessage) mailboxMessage).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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void emptyMailbox() {
|
||||
mailboxService.removeAllMessages(user.getP2PSigPubKey(),
|
||||
() -> {
|
||||
log.debug("All mailbox entries removed");
|
||||
},
|
||||
(errorMessage, fault) -> {
|
||||
log.error(errorMessage);
|
||||
log.error(fault.getMessage());
|
||||
});
|
||||
}
|
||||
}
|
|
@ -42,7 +42,6 @@ public class TradeModule extends BitsquareModule {
|
|||
@Override
|
||||
protected void doClose(Injector injector) {
|
||||
log.trace("doClose " + getClass().getSimpleName());
|
||||
// First shut down AddressService to remove address from DHT
|
||||
injector.getInstance(TradeManager.class).shutDown();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +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.handlers;
|
||||
|
||||
import io.bitsquare.offer.Offer;
|
||||
|
||||
|
||||
public interface OfferStateResultHandler {
|
||||
void handleStateResult(Offer.State state);
|
||||
}
|
|
@ -55,7 +55,7 @@ public class CheckOfferAvailabilityProtocol {
|
|||
messageHandler = this::handleMessage;
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
private void cleanup() {
|
||||
model.messageService.removeMessageHandler(messageHandler);
|
||||
}
|
||||
|
||||
|
@ -71,12 +71,8 @@ public class CheckOfferAvailabilityProtocol {
|
|||
model.messageService.addMessageHandler(messageHandler);
|
||||
|
||||
taskRunner = new TaskRunner<>(model,
|
||||
() -> {
|
||||
log.debug("sequence at onCheckOfferAvailability completed");
|
||||
},
|
||||
(errorMessage) -> {
|
||||
log.error(errorMessage);
|
||||
}
|
||||
() -> log.debug("sequence at onCheckOfferAvailability completed"),
|
||||
log::error
|
||||
);
|
||||
taskRunner.addTasks(
|
||||
GetPeerAddress.class,
|
||||
|
@ -96,7 +92,7 @@ public class CheckOfferAvailabilityProtocol {
|
|||
// Incoming message handling
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void handleMessage(Message message, Peer sender) {
|
||||
private void handleMessage(Message message, @SuppressWarnings("UnusedParameters") Peer sender) {
|
||||
if (!isCanceled) {
|
||||
if (message instanceof ReportOfferAvailabilityMessage && model.offer.getId().equals(((ReportOfferAvailabilityMessage) message).offerId))
|
||||
handleReportOfferAvailabilityMessage((ReportOfferAvailabilityMessage) message);
|
||||
|
|
|
@ -33,7 +33,7 @@ public class PlaceOfferModel extends Model {
|
|||
|
||||
public final Offer offer;
|
||||
public final WalletService walletService;
|
||||
public TradeWalletService tradeWalletService;
|
||||
public final TradeWalletService tradeWalletService;
|
||||
public final OfferBookService offerBookService;
|
||||
|
||||
private Transaction transaction;
|
||||
|
|
|
@ -35,11 +35,7 @@ public class AddOfferToRemoteOfferBook extends Task<PlaceOfferModel> {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
model.offerBookService.addOffer(model.offer,
|
||||
() -> {
|
||||
complete();
|
||||
},
|
||||
(message, throwable) -> {
|
||||
failed(throwable);
|
||||
});
|
||||
this::complete,
|
||||
(message, throwable) -> failed(throwable));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,9 +72,7 @@ public class BroadcastCreateOfferFeeTx extends Task<PlaceOfferModel> {
|
|||
// We store now the changed txID to the offer and add that again.
|
||||
model.offer.setOfferFeePaymentTxID(transaction.getHashAsString());
|
||||
model.offerBookService.addOffer(model.offer,
|
||||
() -> {
|
||||
complete();
|
||||
},
|
||||
BroadcastCreateOfferFeeTx.this::complete,
|
||||
(message, throwable) -> {
|
||||
log.error("addOffer failed");
|
||||
addOfferFailed = true;
|
||||
|
@ -108,9 +106,7 @@ public class BroadcastCreateOfferFeeTx extends Task<PlaceOfferModel> {
|
|||
if (!removeOfferFailed && !addOfferFailed) {
|
||||
// If broadcast fails we need to remove offer from offerbook
|
||||
model.offerBookService.removeOffer(model.offer,
|
||||
() -> {
|
||||
log.info("Offer removed from offerbook because broadcast failed.");
|
||||
},
|
||||
() -> log.info("Offer removed from offerbook because broadcast failed."),
|
||||
(message, throwable) -> {
|
||||
log.error("removeOffer failed");
|
||||
failed(throwable);
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import io.bitsquare.arbitration.ArbitrationRepository;
|
||||
import io.bitsquare.btc.BlockChainService;
|
||||
import io.bitsquare.btc.TradeWalletService;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.common.taskrunner.Model;
|
||||
import io.bitsquare.crypto.SignatureService;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.p2p.MailboxMessage;
|
||||
import io.bitsquare.p2p.MessageService;
|
||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ProcessModel extends Model implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ProcessModel.class);
|
||||
|
||||
// Transient/Immutable
|
||||
transient private MessageService messageService;
|
||||
transient private WalletService walletService;
|
||||
transient private TradeWalletService tradeWalletService;
|
||||
transient private BlockChainService blockChainService;
|
||||
transient private SignatureService signatureService;
|
||||
transient private ArbitrationRepository arbitrationRepository;
|
||||
transient private Offer offer;
|
||||
|
||||
// Mutable
|
||||
transient private MailboxMessage mailboxMessage;
|
||||
transient private TradeMessage tradeMessage;
|
||||
|
||||
|
||||
protected ProcessModel() {
|
||||
log.trace("Created by constructor");
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
log.trace("Created from serialized form.");
|
||||
}
|
||||
|
||||
public void onAllServicesInitialized(Offer offer,
|
||||
MessageService messageService,
|
||||
WalletService walletService,
|
||||
TradeWalletService tradeWalletService,
|
||||
BlockChainService blockChainService,
|
||||
SignatureService signatureService,
|
||||
ArbitrationRepository arbitrationRepository,
|
||||
User user) {
|
||||
this.offer = offer;
|
||||
this.messageService = messageService;
|
||||
this.walletService = walletService;
|
||||
this.tradeWalletService = tradeWalletService;
|
||||
this.blockChainService = blockChainService;
|
||||
this.signatureService = signatureService;
|
||||
this.arbitrationRepository = arbitrationRepository;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter only
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public MessageService getMessageService() {
|
||||
return messageService;
|
||||
}
|
||||
|
||||
public WalletService getWalletService() {
|
||||
return walletService;
|
||||
}
|
||||
|
||||
public TradeWalletService getTradeWalletService() {
|
||||
return tradeWalletService;
|
||||
}
|
||||
|
||||
public BlockChainService getBlockChainService() {
|
||||
return blockChainService;
|
||||
}
|
||||
|
||||
public SignatureService getSignatureService() {
|
||||
return signatureService;
|
||||
}
|
||||
|
||||
public byte[] getArbitratorPubKey() {
|
||||
return arbitrationRepository.getDefaultArbitrator().getPubKey();
|
||||
}
|
||||
|
||||
public Offer getOffer() {
|
||||
return offer;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return offer.getId();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter/Setter for Mutable objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setTradeMessage(TradeMessage tradeMessage) {
|
||||
this.tradeMessage = tradeMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TradeMessage getTradeMessage() {
|
||||
return tradeMessage;
|
||||
}
|
||||
|
||||
public void setMailboxMessage(MailboxMessage mailboxMessage) {
|
||||
this.mailboxMessage = mailboxMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MailboxMessage getMailboxMessage() {
|
||||
return mailboxMessage;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ProcessModel{" +
|
||||
"offer=" + offer +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -1,106 +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;
|
||||
|
||||
import io.bitsquare.arbitration.ArbitrationRepository;
|
||||
import io.bitsquare.btc.BlockChainService;
|
||||
import io.bitsquare.btc.TradeWalletService;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.common.taskrunner.Model;
|
||||
import io.bitsquare.crypto.SignatureService;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.p2p.MailboxMessage;
|
||||
import io.bitsquare.p2p.MailboxService;
|
||||
import io.bitsquare.p2p.MessageService;
|
||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TradeProcessModel extends Model implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected static final Logger log = LoggerFactory.getLogger(TradeProcessModel.class);
|
||||
|
||||
// those fields are re-assigned in case of deserialized object after backend is ready.
|
||||
// Therefore they are not final but annotated with @NotNull
|
||||
@NotNull transient public MessageService messageService;
|
||||
@NotNull transient public MailboxService mailboxService;
|
||||
@NotNull transient public WalletService walletService;
|
||||
@NotNull transient public TradeWalletService tradeWalletService;
|
||||
@NotNull transient public BlockChainService blockChainService;
|
||||
@NotNull transient public SignatureService signatureService;
|
||||
|
||||
@NotNull public Offer offer;
|
||||
@NotNull public String id;
|
||||
@NotNull public byte[] arbitratorPubKey;
|
||||
|
||||
@Nullable private transient MailboxMessage mailboxMessage;
|
||||
@Nullable transient private TradeMessage tradeMessage;
|
||||
|
||||
protected TradeProcessModel() {
|
||||
}
|
||||
|
||||
public void init(@NotNull Offer offer,
|
||||
@NotNull MessageService messageService,
|
||||
@NotNull MailboxService mailboxService,
|
||||
@NotNull WalletService walletService,
|
||||
@NotNull TradeWalletService tradeWalletService,
|
||||
@NotNull BlockChainService blockChainService,
|
||||
@NotNull SignatureService signatureService,
|
||||
@NotNull ArbitrationRepository arbitrationRepository,
|
||||
@NotNull User user) {
|
||||
this.offer = offer;
|
||||
this.messageService = messageService;
|
||||
this.mailboxService = mailboxService;
|
||||
this.walletService = walletService;
|
||||
this.tradeWalletService = tradeWalletService;
|
||||
this.blockChainService = blockChainService;
|
||||
this.signatureService = signatureService;
|
||||
|
||||
id = offer.getId();
|
||||
arbitratorPubKey = arbitrationRepository.getDefaultArbitrator().getPubKey();
|
||||
assert arbitratorPubKey != null;
|
||||
}
|
||||
|
||||
public void setTradeMessage(@NotNull TradeMessage tradeMessage) {
|
||||
this.tradeMessage = tradeMessage;
|
||||
}
|
||||
|
||||
public void setMailboxMessage(@NotNull MailboxMessage mailboxMessage) {
|
||||
this.mailboxMessage = mailboxMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TradeMessage getTradeMessage() {
|
||||
return tradeMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MailboxMessage getMailboxMessage() {
|
||||
return mailboxMessage;
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ public abstract class OfferMessage implements Message, Serializable {
|
|||
|
||||
public final String offerId;
|
||||
|
||||
public OfferMessage(String offerId) {
|
||||
protected OfferMessage(String offerId) {
|
||||
this.offerId = offerId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ public class RequestOffererPublishDepositTxMessage extends TradeMessage implemen
|
|||
public final String takerPayoutAddressString;
|
||||
public final Transaction takersPreparedDepositTx;
|
||||
public final List<TransactionOutput> takerConnectedOutputsForAllInputs;
|
||||
public final List<TransactionOutput> takerOutputs;
|
||||
|
||||
public RequestOffererPublishDepositTxMessage(String tradeId,
|
||||
FiatAccount takerFiatAccount,
|
||||
|
@ -55,8 +54,7 @@ public class RequestOffererPublishDepositTxMessage extends TradeMessage implemen
|
|||
String takerContractSignature,
|
||||
String takerPayoutAddressString,
|
||||
Transaction takersPreparedDepositTx,
|
||||
List<TransactionOutput> takerConnectedOutputsForAllInputs,
|
||||
List<TransactionOutput> takerOutputs) {
|
||||
List<TransactionOutput> takerConnectedOutputsForAllInputs) {
|
||||
super(tradeId);
|
||||
this.takerFiatAccount = takerFiatAccount;
|
||||
this.takerAccountId = takerAccountId;
|
||||
|
@ -67,6 +65,5 @@ public class RequestOffererPublishDepositTxMessage extends TradeMessage implemen
|
|||
this.takerPayoutAddressString = takerPayoutAddressString;
|
||||
this.takersPreparedDepositTx = takersPreparedDepositTx;
|
||||
this.takerConnectedOutputsForAllInputs = takerConnectedOutputsForAllInputs;
|
||||
this.takerOutputs = takerOutputs;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public abstract class TradeMessage implements Message, Serializable {
|
|||
|
||||
public final String tradeId;
|
||||
|
||||
public TradeMessage(String tradeId) {
|
||||
protected TradeMessage(String tradeId) {
|
||||
this.tradeId = tradeId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ import io.bitsquare.trade.protocol.trade.messages.PayoutTxPublishedMessage;
|
|||
import io.bitsquare.trade.protocol.trade.messages.RequestDepositTxInputsMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestOffererPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.models.OffererTradeProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.models.OffererProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.tasks.CreateAndSignPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.tasks.CreateOffererDepositTxInputs;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.tasks.ProcessPayoutTxPublishedMessage;
|
||||
|
@ -55,7 +55,7 @@ public class OffererProtocol implements Protocol {
|
|||
|
||||
private final MessageHandler messageHandler;
|
||||
private final OffererTrade offererTrade;
|
||||
private final OffererTradeProcessModel offererTradeProcessModel;
|
||||
private final OffererProcessModel offererTradeProcessModel;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
|
@ -67,7 +67,7 @@ public class OffererProtocol implements Protocol {
|
|||
offererTradeProcessModel = offererTrade.getProcessModel();
|
||||
messageHandler = this::handleMessage;
|
||||
|
||||
offererTradeProcessModel.messageService.addMessageHandler(messageHandler);
|
||||
offererTradeProcessModel.getMessageService().addMessageHandler(messageHandler);
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,7 +89,7 @@ public class OffererProtocol implements Protocol {
|
|||
public void cleanup() {
|
||||
log.debug("cleanup " + this);
|
||||
|
||||
offererTradeProcessModel.messageService.removeMessageHandler(messageHandler);
|
||||
offererTradeProcessModel.getMessageService().removeMessageHandler(messageHandler);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -99,15 +99,15 @@ public class OffererProtocol implements Protocol {
|
|||
// OpenOffer requests
|
||||
private void handleRequestIsOfferAvailableMessage(RequestIsOfferAvailableMessage tradeMessage, Peer sender) {
|
||||
try {
|
||||
checkTradeId(offererTradeProcessModel.id, tradeMessage);
|
||||
checkTradeId(offererTradeProcessModel.getId(), tradeMessage);
|
||||
|
||||
// We don't store anything in the offererTradeProcessModel as we might be in a trade process and receive that request from another peer who wants
|
||||
// to take the
|
||||
// offer
|
||||
// at the same time
|
||||
boolean isOfferOpen = offererTrade.lifeCycleStateProperty().get() == OffererTrade.OffererLifeCycleState.OFFER_OPEN;
|
||||
ReportOfferAvailabilityMessage reportOfferAvailabilityMessage = new ReportOfferAvailabilityMessage(offererTradeProcessModel.id, isOfferOpen);
|
||||
offererTradeProcessModel.messageService.sendMessage(sender, reportOfferAvailabilityMessage, new SendMessageListener() {
|
||||
ReportOfferAvailabilityMessage reportOfferAvailabilityMessage = new ReportOfferAvailabilityMessage(offererTradeProcessModel.getId(), isOfferOpen);
|
||||
offererTradeProcessModel.getMessageService().sendMessage(sender, reportOfferAvailabilityMessage, new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
// Offerer does not do anything at that moment. Peer might only watch the offer and does not start a trade.
|
||||
|
@ -128,14 +128,14 @@ public class OffererProtocol implements Protocol {
|
|||
|
||||
// Trade started. We reserve the offer for that taker. If anything goes wrong we reset the offer as open.
|
||||
private void handleRequestDepositTxInputsMessage(RequestDepositTxInputsMessage tradeMessage, Peer taker) {
|
||||
checkTradeId(offererTradeProcessModel.id, tradeMessage);
|
||||
checkTradeId(offererTradeProcessModel.getId(), tradeMessage);
|
||||
offererTradeProcessModel.setTradeMessage(tradeMessage);
|
||||
offererTrade.setTradingPeer(taker);
|
||||
offererTrade.setLifeCycleState(OffererTrade.OffererLifeCycleState.OFFER_RESERVED);
|
||||
|
||||
TaskRunner<OffererTrade> taskRunner = new TaskRunner<>(offererTrade,
|
||||
() -> log.debug("taskRunner at handleTakeOfferFeePayedMessage completed"),
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
this::handleTaskRunnerFault);
|
||||
taskRunner.addTasks(
|
||||
ProcessRequestDepositTxInputsMessage.class,
|
||||
CreateOffererDepositTxInputs.class,
|
||||
|
@ -149,7 +149,7 @@ public class OffererProtocol implements Protocol {
|
|||
|
||||
TaskRunner<OffererTrade> taskRunner = new TaskRunner<>(offererTrade,
|
||||
() -> log.debug("taskRunner at handleRequestOffererPublishDepositTxMessage completed"),
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
this::handleTaskRunnerFault);
|
||||
taskRunner.addTasks(
|
||||
ProcessRequestOffererPublishDepositTxMessage.class,
|
||||
VerifyTakerAccount.class,
|
||||
|
@ -169,7 +169,7 @@ public class OffererProtocol implements Protocol {
|
|||
public void onFiatPaymentStarted() {
|
||||
TaskRunner<OffererTrade> taskRunner = new TaskRunner<>(offererTrade,
|
||||
() -> log.debug("taskRunner at handleBankTransferStartedUIEvent completed"),
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
this::handleTaskRunnerFault);
|
||||
taskRunner.addTasks(
|
||||
CreateAndSignPayoutTx.class,
|
||||
VerifyTakeOfferFeePayment.class,
|
||||
|
@ -192,7 +192,7 @@ public class OffererProtocol implements Protocol {
|
|||
// we are done!
|
||||
offererTradeProcessModel.onComplete();
|
||||
},
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(ProcessPayoutTxPublishedMessage.class);
|
||||
taskRunner.run();
|
||||
|
@ -230,6 +230,7 @@ public class OffererProtocol implements Protocol {
|
|||
}
|
||||
|
||||
private void handleTaskRunnerFault(String errorMessage) {
|
||||
log.error(errorMessage);
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,34 +18,158 @@
|
|||
package io.bitsquare.trade.protocol.trade.offerer.models;
|
||||
|
||||
import io.bitsquare.btc.AddressEntry;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.fiat.FiatAccount;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
import org.bitcoinj.crypto.DeterministicKey;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Offerer implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public FiatAccount fiatAccount;
|
||||
public String accountId;
|
||||
public PublicKey p2pSigPubKey;
|
||||
public PublicKey p2pEncryptPubKey;
|
||||
public byte[] registrationPubKey;
|
||||
transient public DeterministicKey registrationKeyPair;
|
||||
public AddressEntry addressEntry;
|
||||
public byte[] tradeWalletPubKey;
|
||||
transient private static final Logger log = LoggerFactory.getLogger(Offerer.class);
|
||||
|
||||
// written by tasks
|
||||
public byte[] payoutTxSignature;
|
||||
public Coin payoutAmount;
|
||||
public List<TransactionOutput> connectedOutputsForAllInputs;
|
||||
public List<TransactionOutput> outputs; // used to verify amounts with change outputs
|
||||
// Transient/Immutable
|
||||
private transient Offer offer;
|
||||
private transient WalletService walletService;
|
||||
private transient User user;
|
||||
|
||||
// Mutable
|
||||
private byte[] payoutTxSignature;
|
||||
private Coin payoutAmount;
|
||||
private List<TransactionOutput> connectedOutputsForAllInputs;
|
||||
private List<TransactionOutput> outputs; // used to verify amounts with change outputs
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Offerer() {
|
||||
log.trace("Created by constructor");
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
log.trace("Created from serialized form.");
|
||||
}
|
||||
|
||||
// We need to wait until backend services are ready to set the required dependencies
|
||||
public void onAllServicesInitialized(Offer offer,
|
||||
WalletService walletService,
|
||||
User user) {
|
||||
log.trace("onBackendReady");
|
||||
this.offer = offer;
|
||||
this.walletService = walletService;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter only
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public FiatAccount getFiatAccount() {
|
||||
return user.getFiatAccount(offer.getBankAccountId());
|
||||
}
|
||||
|
||||
public String getAccountId() {
|
||||
return user.getAccountId();
|
||||
}
|
||||
|
||||
public PublicKey getP2pSigPubKey() {
|
||||
return user.getP2PSigPubKey();
|
||||
}
|
||||
|
||||
public PublicKey getP2pEncryptPubKey() {
|
||||
return user.getP2PEncryptPubKey();
|
||||
}
|
||||
|
||||
public byte[] getRegistrationPubKey() {
|
||||
return walletService.getRegistrationAddressEntry().getPubKey();
|
||||
}
|
||||
|
||||
public DeterministicKey getRegistrationKeyPair() {
|
||||
return walletService.getRegistrationAddressEntry().getKeyPair();
|
||||
}
|
||||
|
||||
public AddressEntry getAddressEntry() {
|
||||
return walletService.getAddressEntry(offer.getId());
|
||||
}
|
||||
|
||||
public byte[] getTradeWalletPubKey() {
|
||||
return getAddressEntry().getPubKey();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter/Setter for Mutable objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Nullable
|
||||
public List<TransactionOutput> getOutputs() {
|
||||
return outputs;
|
||||
}
|
||||
|
||||
public void setOutputs(List<TransactionOutput> outputs) {
|
||||
this.outputs = outputs;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public byte[] getPayoutTxSignature() {
|
||||
return payoutTxSignature;
|
||||
}
|
||||
|
||||
public void setPayoutTxSignature(byte[] payoutTxSignature) {
|
||||
this.payoutTxSignature = payoutTxSignature;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Coin getPayoutAmount() {
|
||||
return payoutAmount;
|
||||
}
|
||||
|
||||
public void setPayoutAmount(Coin payoutAmount) {
|
||||
this.payoutAmount = payoutAmount;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<TransactionOutput> getConnectedOutputsForAllInputs() {
|
||||
return connectedOutputsForAllInputs;
|
||||
}
|
||||
|
||||
public void setConnectedOutputsForAllInputs(List<TransactionOutput> connectedOutputsForAllInputs) {
|
||||
this.connectedOutputsForAllInputs = connectedOutputsForAllInputs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Offerer{" +
|
||||
"offer=" + offer +
|
||||
", walletService=" + walletService +
|
||||
", user=" + user +
|
||||
", payoutTxSignature=" + Arrays.toString(payoutTxSignature) +
|
||||
", payoutAmount=" + payoutAmount +
|
||||
", connectedOutputsForAllInputs=" + connectedOutputsForAllInputs +
|
||||
", outputs=" + outputs +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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.models;
|
||||
|
||||
import io.bitsquare.arbitration.ArbitrationRepository;
|
||||
import io.bitsquare.btc.BlockChainService;
|
||||
import io.bitsquare.btc.TradeWalletService;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.crypto.SignatureService;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.p2p.MessageService;
|
||||
import io.bitsquare.trade.protocol.trade.ProcessModel;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class OffererProcessModel extends ProcessModel implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
transient private static final Logger log = LoggerFactory.getLogger(OffererProcessModel.class);
|
||||
|
||||
// Immutable
|
||||
public final Taker taker;
|
||||
public final Offerer offerer;
|
||||
|
||||
// Mutable
|
||||
private String takeOfferFeeTxId;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public OffererProcessModel() {
|
||||
log.trace("Created by constructor");
|
||||
taker = new Taker();
|
||||
offerer = new Offerer();
|
||||
}
|
||||
|
||||
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
log.trace("Created from serialized form.");
|
||||
}
|
||||
|
||||
public void onAllServicesInitialized(Offer offer,
|
||||
MessageService messageService,
|
||||
WalletService walletService,
|
||||
TradeWalletService tradeWalletService,
|
||||
BlockChainService blockChainService,
|
||||
SignatureService signatureService,
|
||||
ArbitrationRepository arbitrationRepository,
|
||||
User user) {
|
||||
log.trace("onAllServicesInitialized");
|
||||
super.onAllServicesInitialized(offer,
|
||||
messageService,
|
||||
walletService,
|
||||
tradeWalletService,
|
||||
blockChainService,
|
||||
signatureService,
|
||||
arbitrationRepository,
|
||||
user);
|
||||
|
||||
offerer.onAllServicesInitialized(offer, walletService, user);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter/Setter for Mutable objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Nullable
|
||||
public String getTakeOfferFeeTxId() {
|
||||
return takeOfferFeeTxId;
|
||||
}
|
||||
|
||||
public void setTakeOfferFeeTxId(String takeOfferFeeTxId) {
|
||||
this.takeOfferFeeTxId = takeOfferFeeTxId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OffererProcessModel{" +
|
||||
"taker=" + taker +
|
||||
", offerer=" + offerer +
|
||||
", takeOfferFeeTxId='" + takeOfferFeeTxId + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -1,90 +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.models;
|
||||
|
||||
import io.bitsquare.arbitration.ArbitrationRepository;
|
||||
import io.bitsquare.btc.BlockChainService;
|
||||
import io.bitsquare.btc.TradeWalletService;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.crypto.SignatureService;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.p2p.MailboxService;
|
||||
import io.bitsquare.p2p.MessageService;
|
||||
import io.bitsquare.trade.protocol.trade.TradeProcessModel;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class OffererTradeProcessModel extends TradeProcessModel implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
transient private static final Logger log = LoggerFactory.getLogger(OffererTradeProcessModel.class);
|
||||
|
||||
public final Taker taker = new Taker();
|
||||
public final Offerer offerer = new Offerer();
|
||||
|
||||
// written by tasks
|
||||
private String takeOfferFeeTxId;
|
||||
|
||||
public OffererTradeProcessModel() {
|
||||
}
|
||||
|
||||
public void init(@NotNull Offer offer,
|
||||
@NotNull MessageService messageService,
|
||||
@NotNull MailboxService mailboxService,
|
||||
@NotNull WalletService walletService,
|
||||
@NotNull TradeWalletService tradeWalletService,
|
||||
@NotNull BlockChainService blockChainService,
|
||||
@NotNull SignatureService signatureService,
|
||||
@NotNull ArbitrationRepository arbitrationRepository,
|
||||
@NotNull User user) {
|
||||
super.init(offer,
|
||||
messageService,
|
||||
mailboxService,
|
||||
walletService,
|
||||
tradeWalletService,
|
||||
blockChainService,
|
||||
signatureService,
|
||||
arbitrationRepository,
|
||||
user);
|
||||
|
||||
offerer.registrationPubKey = walletService.getRegistrationAddressEntry().getPubKey();
|
||||
offerer.registrationKeyPair = walletService.getRegistrationAddressEntry().getKeyPair();
|
||||
offerer.addressEntry = walletService.getAddressEntry(id);
|
||||
offerer.fiatAccount = user.getFiatAccount(offer.getBankAccountId());
|
||||
offerer.accountId = user.getAccountId();
|
||||
offerer.p2pSigPubKey = user.getP2PSigPubKey();
|
||||
offerer.p2pEncryptPubKey = user.getP2PEncryptPubKey();
|
||||
offerer.tradeWalletPubKey = offerer.addressEntry.getPubKey();
|
||||
log.debug("BuyerAsOffererModel addressEntry " + offerer.addressEntry);
|
||||
}
|
||||
|
||||
public String getTakeOfferFeeTxId() {
|
||||
return takeOfferFeeTxId;
|
||||
}
|
||||
|
||||
public void setTakeOfferFeeTxId(String takeOfferFeeTxId) {
|
||||
this.takeOfferFeeTxId = takeOfferFeeTxId;
|
||||
}
|
||||
}
|
|
@ -23,26 +23,159 @@ import org.bitcoinj.core.Coin;
|
|||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Taker implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// written by tasks
|
||||
public String accountId;
|
||||
public FiatAccount fiatAccount;
|
||||
public PublicKey p2pSigPublicKey;
|
||||
public PublicKey p2pEncryptPubKey;
|
||||
public String contractAsJson;//TODO only write access now, missing impl.
|
||||
public String contractSignature;
|
||||
public Coin payoutAmount;
|
||||
public Transaction preparedDepositTx;
|
||||
public List<TransactionOutput> connectedOutputsForAllInputs;
|
||||
public String payoutAddressString;
|
||||
public byte[] tradeWalletPubKey;
|
||||
transient private static final Logger log = LoggerFactory.getLogger(Taker.class);
|
||||
|
||||
// Mutable
|
||||
private String accountId;
|
||||
private FiatAccount fiatAccount;
|
||||
private PublicKey p2pSigPublicKey;
|
||||
private PublicKey p2pEncryptPubKey;
|
||||
private String contractAsJson;
|
||||
private String contractSignature;
|
||||
private Coin payoutAmount;
|
||||
private Transaction preparedDepositTx;
|
||||
private List<TransactionOutput> connectedOutputsForAllInputs;
|
||||
private String payoutAddressString;
|
||||
private byte[] tradeWalletPubKey;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Taker() {
|
||||
log.trace("Created by constructor");
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
log.trace("Created from serialized form.");
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter/Setter for Mutable objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(String accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public FiatAccount getFiatAccount() {
|
||||
return fiatAccount;
|
||||
}
|
||||
|
||||
public void setFiatAccount(FiatAccount fiatAccount) {
|
||||
this.fiatAccount = fiatAccount;
|
||||
}
|
||||
|
||||
public PublicKey getP2pSigPublicKey() {
|
||||
return p2pSigPublicKey;
|
||||
}
|
||||
|
||||
public void setP2pSigPublicKey(PublicKey p2pSigPublicKey) {
|
||||
this.p2pSigPublicKey = p2pSigPublicKey;
|
||||
}
|
||||
|
||||
public PublicKey getP2pEncryptPubKey() {
|
||||
return p2pEncryptPubKey;
|
||||
}
|
||||
|
||||
public void setP2pEncryptPubKey(PublicKey p2pEncryptPubKey) {
|
||||
this.p2pEncryptPubKey = p2pEncryptPubKey;
|
||||
}
|
||||
|
||||
public String getContractAsJson() {
|
||||
return contractAsJson;
|
||||
}
|
||||
|
||||
public void setContractAsJson(String contractAsJson) {
|
||||
this.contractAsJson = contractAsJson;
|
||||
}
|
||||
|
||||
public String getContractSignature() {
|
||||
return contractSignature;
|
||||
}
|
||||
|
||||
public void setContractSignature(String contractSignature) {
|
||||
this.contractSignature = contractSignature;
|
||||
}
|
||||
|
||||
public Coin getPayoutAmount() {
|
||||
return payoutAmount;
|
||||
}
|
||||
|
||||
public void setPayoutAmount(Coin payoutAmount) {
|
||||
this.payoutAmount = payoutAmount;
|
||||
}
|
||||
|
||||
public Transaction getPreparedDepositTx() {
|
||||
return preparedDepositTx;
|
||||
}
|
||||
|
||||
public void setPreparedDepositTx(Transaction preparedDepositTx) {
|
||||
this.preparedDepositTx = preparedDepositTx;
|
||||
}
|
||||
|
||||
public List<TransactionOutput> getConnectedOutputsForAllInputs() {
|
||||
return connectedOutputsForAllInputs;
|
||||
}
|
||||
|
||||
public void setConnectedOutputsForAllInputs(List<TransactionOutput> connectedOutputsForAllInputs) {
|
||||
this.connectedOutputsForAllInputs = connectedOutputsForAllInputs;
|
||||
}
|
||||
|
||||
public String getPayoutAddressString() {
|
||||
return payoutAddressString;
|
||||
}
|
||||
|
||||
public void setPayoutAddressString(String payoutAddressString) {
|
||||
this.payoutAddressString = payoutAddressString;
|
||||
}
|
||||
|
||||
public byte[] getTradeWalletPubKey() {
|
||||
return tradeWalletPubKey;
|
||||
}
|
||||
|
||||
public void setTradeWalletPubKey(byte[] tradeWalletPubKey) {
|
||||
this.tradeWalletPubKey = tradeWalletPubKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Taker{" +
|
||||
"accountId='" + accountId + '\'' +
|
||||
", fiatAccount=" + fiatAccount +
|
||||
", p2pSigPublicKey=" + p2pSigPublicKey +
|
||||
", p2pEncryptPubKey=" + p2pEncryptPubKey +
|
||||
", contractAsJson='" + contractAsJson + '\'' +
|
||||
", contractSignature='" + contractSignature + '\'' +
|
||||
", payoutAmount=" + payoutAmount +
|
||||
", preparedDepositTx=" + preparedDepositTx +
|
||||
", connectedOutputsForAllInputs=" + connectedOutputsForAllInputs +
|
||||
", payoutAddressString='" + payoutAddressString + '\'' +
|
||||
", tradeWalletPubKey=" + Arrays.toString(tradeWalletPubKey) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,23 +35,24 @@ public class CreateAndSignPayoutTx extends OffererTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
assert offererTrade.getTradeAmount() != null;
|
||||
Coin securityDeposit = offererTrade.getSecurityDeposit();
|
||||
Coin offererPayoutAmount = offererTrade.getTradeAmount().add(securityDeposit);
|
||||
@SuppressWarnings("UnnecessaryLocalVariable") Coin takerPayoutAmount = securityDeposit;
|
||||
|
||||
byte[] offererPayoutTxSignature = offererTradeProcessModel.tradeWalletService.offererCreatesAndSignsPayoutTx(
|
||||
byte[] offererPayoutTxSignature = offererTradeProcessModel.getTradeWalletService().offererCreatesAndSignsPayoutTx(
|
||||
offererTrade.getDepositTx(),
|
||||
offererPayoutAmount,
|
||||
takerPayoutAmount,
|
||||
offererTradeProcessModel.offerer.addressEntry,
|
||||
offererTradeProcessModel.taker.payoutAddressString,
|
||||
offererTradeProcessModel.offerer.tradeWalletPubKey,
|
||||
offererTradeProcessModel.taker.tradeWalletPubKey,
|
||||
offererTradeProcessModel.arbitratorPubKey);
|
||||
offererTradeProcessModel.offerer.getAddressEntry(),
|
||||
offererTradeProcessModel.taker.getPayoutAddressString(),
|
||||
offererTradeProcessModel.offerer.getTradeWalletPubKey(),
|
||||
offererTradeProcessModel.taker.getTradeWalletPubKey(),
|
||||
offererTradeProcessModel.getArbitratorPubKey());
|
||||
|
||||
offererTradeProcessModel.offerer.payoutTxSignature = offererPayoutTxSignature;
|
||||
offererTradeProcessModel.offerer.payoutAmount = offererPayoutAmount;
|
||||
offererTradeProcessModel.taker.payoutAmount = takerPayoutAmount;
|
||||
offererTradeProcessModel.offerer.setPayoutTxSignature(offererPayoutTxSignature);
|
||||
offererTradeProcessModel.offerer.setPayoutAmount(offererPayoutAmount);
|
||||
offererTradeProcessModel.taker.setPayoutAmount(takerPayoutAmount);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -39,11 +39,11 @@ public class CreateOffererDepositTxInputs extends OffererTradeTask {
|
|||
try {
|
||||
log.debug("offererTrade.id" + offererTrade.getId());
|
||||
Coin offererInputAmount = offererTrade.getSecurityDeposit().add(FeePolicy.TX_FEE);
|
||||
TradeWalletService.Result result = offererTradeProcessModel.tradeWalletService.createOffererDepositTxInputs(offererInputAmount,
|
||||
offererTradeProcessModel.offerer.addressEntry);
|
||||
TradeWalletService.Result result = offererTradeProcessModel.getTradeWalletService().createOffererDepositTxInputs(offererInputAmount,
|
||||
offererTradeProcessModel.offerer.getAddressEntry());
|
||||
|
||||
offererTradeProcessModel.offerer.connectedOutputsForAllInputs = result.getConnectedOutputsForAllInputs();
|
||||
offererTradeProcessModel.offerer.outputs = result.getOutputs();
|
||||
offererTradeProcessModel.offerer.setConnectedOutputsForAllInputs(result.getConnectedOutputsForAllInputs());
|
||||
offererTradeProcessModel.offerer.setOutputs(result.getOutputs());
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -23,17 +23,17 @@ import io.bitsquare.btc.exceptions.WalletException;
|
|||
import io.bitsquare.common.taskrunner.Task;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.OffererTrade;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.models.OffererTradeProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.models.OffererProcessModel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class OffererTradeTask extends Task<OffererTrade> {
|
||||
class OffererTradeTask extends Task<OffererTrade> {
|
||||
private static final Logger log = LoggerFactory.getLogger(OffererTradeTask.class);
|
||||
protected final OffererTradeProcessModel offererTradeProcessModel;
|
||||
protected final OffererProcessModel offererTradeProcessModel;
|
||||
protected final OffererTrade offererTrade;
|
||||
|
||||
public OffererTradeTask(TaskRunner taskHandler, OffererTrade model) {
|
||||
OffererTradeTask(TaskRunner taskHandler, OffererTrade model) {
|
||||
super(taskHandler, model);
|
||||
|
||||
offererTrade = model;
|
||||
|
|
|
@ -37,9 +37,11 @@ public class ProcessPayoutTxPublishedMessage extends OffererTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
checkTradeId(offererTradeProcessModel.id, offererTradeProcessModel.getTradeMessage());
|
||||
PayoutTxPublishedMessage message = (PayoutTxPublishedMessage) offererTradeProcessModel.getTradeMessage();
|
||||
checkTradeId(offererTradeProcessModel.getId(), message);
|
||||
checkNotNull(message);
|
||||
|
||||
offererTrade.setPayoutTx(checkNotNull(((PayoutTxPublishedMessage) offererTradeProcessModel.getTradeMessage()).payoutTx));
|
||||
offererTrade.setPayoutTx(checkNotNull(message.payoutTx));
|
||||
|
||||
offererTrade.setProcessState(OffererTrade.OffererProcessState.PAYOUT_PUBLISHED);
|
||||
|
||||
|
|
|
@ -37,12 +37,13 @@ public class ProcessRequestDepositTxInputsMessage extends OffererTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
checkTradeId(offererTradeProcessModel.id, offererTradeProcessModel.getTradeMessage());
|
||||
RequestDepositTxInputsMessage requestDepositTxInputsMessage = (RequestDepositTxInputsMessage) offererTradeProcessModel.getTradeMessage();
|
||||
RequestDepositTxInputsMessage message = (RequestDepositTxInputsMessage) offererTradeProcessModel.getTradeMessage();
|
||||
checkTradeId(offererTradeProcessModel.getId(), message);
|
||||
checkNotNull(message);
|
||||
|
||||
offererTrade.setTradeAmount(positiveCoinOf(nonZeroCoinOf(requestDepositTxInputsMessage.tradeAmount)));
|
||||
offererTradeProcessModel.setTakeOfferFeeTxId(nonEmptyStringOf(requestDepositTxInputsMessage.takeOfferFeeTxId));
|
||||
offererTradeProcessModel.taker.tradeWalletPubKey = checkNotNull(requestDepositTxInputsMessage.takerTradeWalletPubKey);
|
||||
offererTrade.setTradeAmount(positiveCoinOf(nonZeroCoinOf(message.tradeAmount)));
|
||||
offererTradeProcessModel.setTakeOfferFeeTxId(nonEmptyStringOf(message.takeOfferFeeTxId));
|
||||
offererTradeProcessModel.taker.setTradeWalletPubKey(checkNotNull(message.takerTradeWalletPubKey));
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -37,18 +37,19 @@ public class ProcessRequestOffererPublishDepositTxMessage extends OffererTradeTa
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
checkTradeId(offererTradeProcessModel.id, offererTradeProcessModel.getTradeMessage());
|
||||
RequestOffererPublishDepositTxMessage message = (RequestOffererPublishDepositTxMessage) offererTradeProcessModel.getTradeMessage();
|
||||
checkTradeId(offererTradeProcessModel.getId(), message);
|
||||
checkNotNull(message);
|
||||
|
||||
offererTradeProcessModel.taker.fiatAccount = checkNotNull(message.takerFiatAccount);
|
||||
offererTradeProcessModel.taker.accountId = nonEmptyStringOf(message.takerAccountId);
|
||||
offererTradeProcessModel.taker.p2pSigPublicKey = checkNotNull(message.takerP2PSigPublicKey);
|
||||
offererTradeProcessModel.taker.p2pEncryptPubKey = checkNotNull(message.takerP2PEncryptPublicKey);
|
||||
offererTradeProcessModel.taker.contractAsJson = nonEmptyStringOf(message.takerContractAsJson);
|
||||
offererTradeProcessModel.taker.contractSignature = nonEmptyStringOf(message.takerContractSignature);
|
||||
offererTradeProcessModel.taker.payoutAddressString = nonEmptyStringOf(message.takerPayoutAddressString);
|
||||
offererTradeProcessModel.taker.preparedDepositTx = checkNotNull(message.takersPreparedDepositTx);
|
||||
offererTradeProcessModel.taker.connectedOutputsForAllInputs = checkNotNull(message.takerConnectedOutputsForAllInputs);
|
||||
offererTradeProcessModel.taker.setFiatAccount(checkNotNull(message.takerFiatAccount));
|
||||
offererTradeProcessModel.taker.setAccountId(nonEmptyStringOf(message.takerAccountId));
|
||||
offererTradeProcessModel.taker.setP2pSigPublicKey(checkNotNull(message.takerP2PSigPublicKey));
|
||||
offererTradeProcessModel.taker.setP2pEncryptPubKey(checkNotNull(message.takerP2PEncryptPublicKey));
|
||||
offererTradeProcessModel.taker.setContractAsJson(nonEmptyStringOf(message.takerContractAsJson));
|
||||
offererTradeProcessModel.taker.setContractSignature(nonEmptyStringOf(message.takerContractSignature));
|
||||
offererTradeProcessModel.taker.setPayoutAddressString(nonEmptyStringOf(message.takerPayoutAddressString));
|
||||
offererTradeProcessModel.taker.setPreparedDepositTx(checkNotNull(message.takersPreparedDepositTx));
|
||||
offererTradeProcessModel.taker.setConnectedOutputsForAllInputs(checkNotNull(message.takerConnectedOutputsForAllInputs));
|
||||
checkArgument(message.takerConnectedOutputsForAllInputs.size() > 0);
|
||||
|
||||
complete();
|
||||
|
|
|
@ -36,16 +36,16 @@ public class RequestTakerDepositPayment extends OffererTradeTask {
|
|||
protected void doRun() {
|
||||
try {
|
||||
RequestTakerDepositPaymentMessage tradeMessage = new RequestTakerDepositPaymentMessage(
|
||||
offererTradeProcessModel.id,
|
||||
offererTradeProcessModel.offerer.connectedOutputsForAllInputs,
|
||||
offererTradeProcessModel.offerer.outputs,
|
||||
offererTradeProcessModel.offerer.tradeWalletPubKey,
|
||||
offererTradeProcessModel.offerer.p2pSigPubKey,
|
||||
offererTradeProcessModel.offerer.p2pEncryptPubKey,
|
||||
offererTradeProcessModel.offerer.fiatAccount,
|
||||
offererTradeProcessModel.offerer.accountId);
|
||||
offererTradeProcessModel.getId(),
|
||||
offererTradeProcessModel.offerer.getConnectedOutputsForAllInputs(),
|
||||
offererTradeProcessModel.offerer.getOutputs(),
|
||||
offererTradeProcessModel.offerer.getTradeWalletPubKey(),
|
||||
offererTradeProcessModel.offerer.getP2pSigPubKey(),
|
||||
offererTradeProcessModel.offerer.getP2pEncryptPubKey(),
|
||||
offererTradeProcessModel.offerer.getFiatAccount(),
|
||||
offererTradeProcessModel.offerer.getAccountId());
|
||||
|
||||
offererTradeProcessModel.messageService.sendMessage(offererTrade.getTradingPeer(), tradeMessage, new SendMessageListener() {
|
||||
offererTradeProcessModel.getMessageService().sendMessage(offererTrade.getTradingPeer(), tradeMessage, new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
log.trace("RequestTakerDepositPaymentMessage successfully arrived at peer");
|
||||
|
|
|
@ -35,15 +35,15 @@ public class SendBankTransferStartedMessage extends OffererTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
FiatTransferStartedMessage tradeMessage = new FiatTransferStartedMessage(offererTradeProcessModel.id,
|
||||
offererTradeProcessModel.offerer.payoutTxSignature,
|
||||
offererTradeProcessModel.offerer.payoutAmount,
|
||||
offererTradeProcessModel.taker.payoutAmount,
|
||||
offererTradeProcessModel.offerer.addressEntry.getAddressString());
|
||||
FiatTransferStartedMessage tradeMessage = new FiatTransferStartedMessage(offererTradeProcessModel.getId(),
|
||||
offererTradeProcessModel.offerer.getPayoutTxSignature(),
|
||||
offererTradeProcessModel.offerer.getPayoutAmount(),
|
||||
offererTradeProcessModel.taker.getPayoutAmount(),
|
||||
offererTradeProcessModel.offerer.getAddressEntry().getAddressString());
|
||||
|
||||
offererTradeProcessModel.messageService.sendMessage(offererTrade.getTradingPeer(), tradeMessage,
|
||||
offererTradeProcessModel.taker.p2pSigPublicKey,
|
||||
offererTradeProcessModel.taker.p2pEncryptPubKey,
|
||||
offererTradeProcessModel.getMessageService().sendMessage(offererTrade.getTradingPeer(), tradeMessage,
|
||||
offererTradeProcessModel.taker.getP2pSigPublicKey(),
|
||||
offererTradeProcessModel.taker.getP2pEncryptPubKey(),
|
||||
new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
|
|
|
@ -35,9 +35,9 @@ public class SendDepositTxToTaker extends OffererTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
DepositTxPublishedMessage tradeMessage = new DepositTxPublishedMessage(offererTradeProcessModel.id, offererTrade.getDepositTx());
|
||||
DepositTxPublishedMessage tradeMessage = new DepositTxPublishedMessage(offererTradeProcessModel.getId(), offererTrade.getDepositTx());
|
||||
|
||||
offererTradeProcessModel.messageService.sendMessage(offererTrade.getTradingPeer(), tradeMessage, new SendMessageListener() {
|
||||
offererTradeProcessModel.getMessageService().sendMessage(offererTrade.getTradingPeer(), tradeMessage, new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
log.trace("DepositTxPublishedMessage successfully arrived at peer");
|
||||
|
|
|
@ -42,15 +42,15 @@ public class SignAndPublishDepositTx extends OffererTradeTask {
|
|||
protected void doRun() {
|
||||
try {
|
||||
Coin offererInputAmount = offererTrade.getSecurityDeposit().add(FeePolicy.TX_FEE);
|
||||
offererTradeProcessModel.tradeWalletService.offererSignsAndPublishDepositTx(
|
||||
offererTradeProcessModel.taker.preparedDepositTx,
|
||||
offererTradeProcessModel.offerer.connectedOutputsForAllInputs,
|
||||
offererTradeProcessModel.taker.connectedOutputsForAllInputs,
|
||||
offererTradeProcessModel.offerer.outputs,
|
||||
offererTradeProcessModel.getTradeWalletService().offererSignsAndPublishDepositTx(
|
||||
offererTradeProcessModel.taker.getPreparedDepositTx(),
|
||||
offererTradeProcessModel.offerer.getConnectedOutputsForAllInputs(),
|
||||
offererTradeProcessModel.taker.getConnectedOutputsForAllInputs(),
|
||||
offererTradeProcessModel.offerer.getOutputs(),
|
||||
offererInputAmount,
|
||||
offererTradeProcessModel.offerer.tradeWalletPubKey,
|
||||
offererTradeProcessModel.taker.tradeWalletPubKey,
|
||||
offererTradeProcessModel.arbitratorPubKey,
|
||||
offererTradeProcessModel.offerer.getTradeWalletPubKey(),
|
||||
offererTradeProcessModel.taker.getTradeWalletPubKey(),
|
||||
offererTradeProcessModel.getArbitratorPubKey(),
|
||||
new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
|
|
|
@ -36,22 +36,23 @@ public class VerifyAndSignContract extends OffererTradeTask {
|
|||
protected void doRun() {
|
||||
try {
|
||||
Contract contract = new Contract(
|
||||
offererTradeProcessModel.offer,
|
||||
offererTradeProcessModel.getOffer(),
|
||||
offererTrade.getTradeAmount(),
|
||||
offererTradeProcessModel.getTakeOfferFeeTxId(),
|
||||
offererTradeProcessModel.offerer.accountId,
|
||||
offererTradeProcessModel.taker.accountId,
|
||||
offererTradeProcessModel.offerer.fiatAccount,
|
||||
offererTradeProcessModel.taker.fiatAccount,
|
||||
offererTradeProcessModel.offerer.p2pSigPubKey,
|
||||
offererTradeProcessModel.taker.p2pSigPublicKey);
|
||||
offererTradeProcessModel.offerer.getAccountId(),
|
||||
offererTradeProcessModel.taker.getAccountId(),
|
||||
offererTradeProcessModel.offerer.getFiatAccount(),
|
||||
offererTradeProcessModel.taker.getFiatAccount(),
|
||||
offererTradeProcessModel.offerer.getP2pSigPubKey(),
|
||||
offererTradeProcessModel.taker.getP2pSigPublicKey());
|
||||
String contractAsJson = Utilities.objectToJson(contract);
|
||||
String signature = offererTradeProcessModel.signatureService.signMessage(offererTradeProcessModel.offerer.registrationKeyPair, contractAsJson);
|
||||
String signature = offererTradeProcessModel.getSignatureService().signMessage(offererTradeProcessModel.offerer.getRegistrationKeyPair(),
|
||||
contractAsJson);
|
||||
|
||||
offererTrade.setContract(contract);
|
||||
offererTrade.setContractAsJson(contractAsJson);
|
||||
offererTrade.setOffererContractSignature(signature);
|
||||
offererTrade.setTakerContractSignature(offererTradeProcessModel.taker.contractSignature);
|
||||
offererTrade.setTakerContractSignature(offererTradeProcessModel.taker.getContractSignature());
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -34,7 +34,7 @@ public class VerifyTakeOfferFeePayment extends OffererTradeTask {
|
|||
protected void doRun() {
|
||||
try {
|
||||
//TODO mocked yet, need a confidence listeners
|
||||
int numOfPeersSeenTx = offererTradeProcessModel.walletService.getNumOfPeersSeenTx(offererTradeProcessModel.getTakeOfferFeeTxId());
|
||||
int numOfPeersSeenTx = offererTradeProcessModel.getWalletService().getNumOfPeersSeenTx(offererTradeProcessModel.getTakeOfferFeeTxId());
|
||||
/* if (numOfPeersSeenTx > 2) {
|
||||
resultHandler.handleResult();
|
||||
}*/
|
||||
|
|
|
@ -34,9 +34,10 @@ public class VerifyTakerAccount extends OffererTradeTask {
|
|||
protected void doRun() {
|
||||
try {
|
||||
//TODO mocked yet
|
||||
if (offererTradeProcessModel.blockChainService.verifyAccountRegistration()) {
|
||||
if (offererTradeProcessModel.blockChainService.isAccountBlackListed(offererTradeProcessModel.taker.accountId, offererTradeProcessModel.taker
|
||||
.fiatAccount)) {
|
||||
if (offererTradeProcessModel.getBlockChainService().verifyAccountRegistration()) {
|
||||
if (offererTradeProcessModel.getBlockChainService().isAccountBlackListed(offererTradeProcessModel.taker.getAccountId(), offererTradeProcessModel
|
||||
.taker
|
||||
.getFiatAccount())) {
|
||||
log.error("Taker is blacklisted");
|
||||
failed("Taker is blacklisted");
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
|
|||
import io.bitsquare.trade.protocol.trade.messages.FiatTransferStartedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestTakerDepositPaymentMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||
import io.bitsquare.trade.protocol.trade.taker.models.TakerTradeProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.taker.models.TakerProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.taker.tasks.BroadcastTakeOfferFeeTx;
|
||||
import io.bitsquare.trade.protocol.trade.taker.tasks.CreateAndSignContract;
|
||||
import io.bitsquare.trade.protocol.trade.taker.tasks.CreateTakeOfferFeeTx;
|
||||
|
@ -53,7 +53,7 @@ public class TakerProtocol implements Protocol {
|
|||
private static final Logger log = LoggerFactory.getLogger(TakerProtocol.class);
|
||||
|
||||
private final TakerTrade takerTrade;
|
||||
private final TakerTradeProcessModel takerTradeProcessModel;
|
||||
private final TakerProcessModel takerTradeProcessModel;
|
||||
private final MessageHandler messageHandler;
|
||||
|
||||
|
||||
|
@ -65,9 +65,9 @@ public class TakerProtocol implements Protocol {
|
|||
log.debug("New SellerAsTakerProtocol " + this);
|
||||
this.takerTrade = takerTrade;
|
||||
takerTradeProcessModel = takerTrade.getProcessModel();
|
||||
|
||||
|
||||
messageHandler = this::handleMessage;
|
||||
takerTradeProcessModel.messageService.addMessageHandler(messageHandler);
|
||||
takerTradeProcessModel.getMessageService().addMessageHandler(messageHandler);
|
||||
}
|
||||
|
||||
|
||||
|
@ -77,7 +77,7 @@ public class TakerProtocol implements Protocol {
|
|||
|
||||
public void cleanup() {
|
||||
log.debug("cleanup " + this);
|
||||
takerTradeProcessModel.messageService.removeMessageHandler(messageHandler);
|
||||
takerTradeProcessModel.getMessageService().removeMessageHandler(messageHandler);
|
||||
}
|
||||
|
||||
public void setMailboxMessage(MailboxMessage mailboxMessage) {
|
||||
|
@ -96,10 +96,8 @@ public class TakerProtocol implements Protocol {
|
|||
|
||||
public void takeAvailableOffer() {
|
||||
TaskRunner<TakerTrade> taskRunner = new TaskRunner<>(takerTrade,
|
||||
() -> {
|
||||
log.debug("taskRunner at takeAvailableOffer completed");
|
||||
},
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
() -> log.debug("taskRunner at takeAvailableOffer completed"),
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(
|
||||
CreateTakeOfferFeeTx.class,
|
||||
|
@ -118,10 +116,8 @@ public class TakerProtocol implements Protocol {
|
|||
takerTradeProcessModel.setTradeMessage(tradeMessage);
|
||||
|
||||
TaskRunner<TakerTrade> taskRunner = new TaskRunner<>(takerTrade,
|
||||
() -> {
|
||||
log.debug("taskRunner at handleTakerDepositPaymentRequestMessage completed");
|
||||
},
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
() -> log.debug("taskRunner at handleTakerDepositPaymentRequestMessage completed"),
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(
|
||||
ProcessRequestTakerDepositPaymentMessage.class,
|
||||
|
@ -137,10 +133,8 @@ public class TakerProtocol implements Protocol {
|
|||
takerTradeProcessModel.setTradeMessage(tradeMessage);
|
||||
|
||||
TaskRunner<TakerTrade> taskRunner = new TaskRunner<>(takerTrade,
|
||||
() -> {
|
||||
log.debug("taskRunner at handleDepositTxPublishedMessage completed");
|
||||
},
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
() -> log.debug("taskRunner at handleDepositTxPublishedMessage completed"),
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(
|
||||
ProcessDepositTxPublishedMessage.class,
|
||||
|
@ -153,10 +147,8 @@ public class TakerProtocol implements Protocol {
|
|||
takerTradeProcessModel.setTradeMessage(tradeMessage);
|
||||
|
||||
TaskRunner<TakerTrade> taskRunner = new TaskRunner<>(takerTrade,
|
||||
() -> {
|
||||
log.debug("taskRunner at handleFiatTransferStartedMessage completed");
|
||||
},
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
() -> log.debug("taskRunner at handleFiatTransferStartedMessage completed"),
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(ProcessFiatTransferStartedMessage.class);
|
||||
taskRunner.run();
|
||||
|
@ -178,7 +170,7 @@ public class TakerProtocol implements Protocol {
|
|||
// we are done!
|
||||
takerTradeProcessModel.onComplete();
|
||||
},
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(
|
||||
SignAndPublishPayoutTx.class,
|
||||
|
@ -198,7 +190,7 @@ public class TakerProtocol implements Protocol {
|
|||
TradeMessage tradeMessage = (TradeMessage) message;
|
||||
nonEmptyStringOf(tradeMessage.tradeId);
|
||||
|
||||
if (tradeMessage.tradeId.equals(takerTradeProcessModel.id)) {
|
||||
if (tradeMessage.tradeId.equals(takerTradeProcessModel.getId())) {
|
||||
if (tradeMessage instanceof RequestTakerDepositPaymentMessage) {
|
||||
handleRequestTakerDepositPaymentMessage((RequestTakerDepositPaymentMessage) tradeMessage);
|
||||
}
|
||||
|
@ -216,6 +208,7 @@ public class TakerProtocol implements Protocol {
|
|||
}
|
||||
|
||||
private void handleTaskRunnerFault(String errorMessage) {
|
||||
log.error(errorMessage);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,29 +22,164 @@ import io.bitsquare.fiat.FiatAccount;
|
|||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Fully serializable, no transient fields
|
||||
*/
|
||||
public class Offerer implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
transient private static final Logger log = LoggerFactory.getLogger(Offerer.class);
|
||||
|
||||
// Mutable
|
||||
private byte[] tradeWalletPubKey;
|
||||
private Coin payoutAmount;
|
||||
private String payoutAddressString;
|
||||
private List<TransactionOutput> connectedOutputsForAllInputs;
|
||||
private List<TransactionOutput> outputs;
|
||||
private byte[] signature;
|
||||
private FiatAccount fiatAccount;
|
||||
private String accountId;
|
||||
private PublicKey p2pSigPublicKey;
|
||||
private PublicKey p2pEncryptPubKey;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Offerer() {
|
||||
log.trace("Created by constructor");
|
||||
}
|
||||
|
||||
// written by tasks
|
||||
public byte[] tradeWalletPubKey;
|
||||
public Coin payoutAmount;
|
||||
public String payoutAddressString;
|
||||
public List<TransactionOutput> connectedOutputsForAllInputs;
|
||||
public List<TransactionOutput> outputs;
|
||||
public byte[] signature;
|
||||
public FiatAccount fiatAccount;
|
||||
public String accountId;
|
||||
public PublicKey p2pSigPublicKey;
|
||||
public PublicKey p2pEncryptPubKey;
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
log.trace("Created from serialized form.");
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter/Setter for Mutable objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Nullable
|
||||
public byte[] getTradeWalletPubKey() {
|
||||
return tradeWalletPubKey;
|
||||
}
|
||||
|
||||
public void setTradeWalletPubKey(byte[] tradeWalletPubKey) {
|
||||
this.tradeWalletPubKey = tradeWalletPubKey;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Coin getPayoutAmount() {
|
||||
return payoutAmount;
|
||||
}
|
||||
|
||||
public void setPayoutAmount(Coin payoutAmount) {
|
||||
this.payoutAmount = payoutAmount;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getPayoutAddressString() {
|
||||
return payoutAddressString;
|
||||
}
|
||||
|
||||
public void setPayoutAddressString(String payoutAddressString) {
|
||||
this.payoutAddressString = payoutAddressString;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<TransactionOutput> getConnectedOutputsForAllInputs() {
|
||||
return connectedOutputsForAllInputs;
|
||||
}
|
||||
|
||||
public void setConnectedOutputsForAllInputs(List<TransactionOutput> connectedOutputsForAllInputs) {
|
||||
this.connectedOutputsForAllInputs = connectedOutputsForAllInputs;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<TransactionOutput> getOutputs() {
|
||||
return outputs;
|
||||
}
|
||||
|
||||
public void setOutputs(List<TransactionOutput> outputs) {
|
||||
this.outputs = outputs;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public byte[] getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(byte[] signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FiatAccount getFiatAccount() {
|
||||
return fiatAccount;
|
||||
}
|
||||
|
||||
public void setFiatAccount(FiatAccount fiatAccount) {
|
||||
this.fiatAccount = fiatAccount;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(String accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PublicKey getP2pSigPublicKey() {
|
||||
return p2pSigPublicKey;
|
||||
}
|
||||
|
||||
public void setP2pSigPublicKey(PublicKey p2pSigPublicKey) {
|
||||
this.p2pSigPublicKey = p2pSigPublicKey;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PublicKey getP2pEncryptPubKey() {
|
||||
return p2pEncryptPubKey;
|
||||
}
|
||||
|
||||
public void setP2pEncryptPubKey(PublicKey p2pEncryptPubKey) {
|
||||
this.p2pEncryptPubKey = p2pEncryptPubKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Offerer{" +
|
||||
"tradeWalletPubKey=" + Arrays.toString(tradeWalletPubKey) +
|
||||
", payoutAmount=" + payoutAmount +
|
||||
", payoutAddressString='" + payoutAddressString + '\'' +
|
||||
", connectedOutputsForAllInputs=" + connectedOutputsForAllInputs +
|
||||
", outputs=" + outputs +
|
||||
", signature=" + Arrays.toString(signature) +
|
||||
", fiatAccount=" + fiatAccount +
|
||||
", accountId='" + accountId + '\'' +
|
||||
", p2pSigPublicKey=" + p2pSigPublicKey +
|
||||
", p2pEncryptPubKey=" + p2pEncryptPubKey +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,39 +18,147 @@
|
|||
package io.bitsquare.trade.protocol.trade.taker.models;
|
||||
|
||||
import io.bitsquare.btc.AddressEntry;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.fiat.FiatAccount;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
import org.bitcoinj.crypto.DeterministicKey;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class Taker implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
transient private static final Logger log = LoggerFactory.getLogger(Taker.class);
|
||||
|
||||
// Transient/Immutable
|
||||
transient private Offer offer;
|
||||
transient private WalletService walletService;
|
||||
transient private User user;
|
||||
|
||||
// Mutable
|
||||
private List<TransactionOutput> connectedOutputsForAllInputs;
|
||||
private Coin payoutAmount;
|
||||
private Transaction preparedDepositTx;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Taker() {
|
||||
log.trace("Created by constructor");
|
||||
}
|
||||
|
||||
public FiatAccount fiatAccount;
|
||||
public String accountId;
|
||||
public PublicKey p2pSigPubKey;
|
||||
public PublicKey p2pEncryptPublicKey;
|
||||
public byte[] registrationPubKey; // TODO not read yet, missing impl.
|
||||
transient public DeterministicKey registrationKeyPair;
|
||||
public AddressEntry addressEntry;
|
||||
public byte[] tradeWalletPubKey;
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
log.trace("Created from serialized form.");
|
||||
}
|
||||
|
||||
// written by tasks
|
||||
public List<TransactionOutput> connectedOutputsForAllInputs;
|
||||
public List<TransactionOutput> outputs;
|
||||
public Coin payoutAmount;
|
||||
public Transaction preparedDepositTx;
|
||||
// We need to wait until backend services are ready to set the required dependencies
|
||||
public void onAllServicesInitialized(Offer offer,
|
||||
WalletService walletService,
|
||||
User user) {
|
||||
log.trace("onBackendReady");
|
||||
this.offer = offer;
|
||||
this.walletService = walletService;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter only
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public FiatAccount getFiatAccount() {
|
||||
return user.getFiatAccount(offer.getBankAccountId());
|
||||
}
|
||||
|
||||
public DeterministicKey getRegistrationKeyPair() {
|
||||
return walletService.getRegistrationAddressEntry().getKeyPair();
|
||||
}
|
||||
|
||||
public String getAccountId() {
|
||||
return user.getAccountId();
|
||||
}
|
||||
|
||||
public PublicKey getP2pSigPubKey() {
|
||||
return user.getP2PSigPubKey();
|
||||
}
|
||||
|
||||
public PublicKey getP2pEncryptPublicKey() {
|
||||
return user.getP2PEncryptPubKey();
|
||||
}
|
||||
|
||||
public byte[] getRegistrationPubKey() {
|
||||
return walletService.getRegistrationAddressEntry().getPubKey();
|
||||
}
|
||||
|
||||
public AddressEntry getAddressEntry() {
|
||||
return walletService.getAddressEntry(offer.getId());
|
||||
}
|
||||
|
||||
public byte[] getTradeWalletPubKey() {
|
||||
return getAddressEntry().getPubKey();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter/Setter for Mutable objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Nullable
|
||||
public List<TransactionOutput> getConnectedOutputsForAllInputs() {
|
||||
return connectedOutputsForAllInputs;
|
||||
}
|
||||
|
||||
public void setConnectedOutputsForAllInputs(List<TransactionOutput> connectedOutputsForAllInputs) {
|
||||
this.connectedOutputsForAllInputs = connectedOutputsForAllInputs;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Coin getPayoutAmount() {
|
||||
return payoutAmount;
|
||||
}
|
||||
|
||||
public void setPayoutAmount(Coin payoutAmount) {
|
||||
this.payoutAmount = payoutAmount;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Transaction getPreparedDepositTx() {
|
||||
return preparedDepositTx;
|
||||
}
|
||||
|
||||
public void setPreparedDepositTx(Transaction preparedDepositTx) {
|
||||
this.preparedDepositTx = preparedDepositTx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Taker{" +
|
||||
"offer=" + offer +
|
||||
", walletService=" + walletService +
|
||||
", user=" + user +
|
||||
", connectedOutputsForAllInputs=" + connectedOutputsForAllInputs +
|
||||
", payoutAmount=" + payoutAmount +
|
||||
", preparedDepositTx=" + preparedDepositTx +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* 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.models;
|
||||
|
||||
import io.bitsquare.arbitration.ArbitrationRepository;
|
||||
import io.bitsquare.btc.BlockChainService;
|
||||
import io.bitsquare.btc.TradeWalletService;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.crypto.SignatureService;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.p2p.MessageService;
|
||||
import io.bitsquare.trade.protocol.trade.ProcessModel;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Fully serializable, no transient fields
|
||||
* <p/>
|
||||
* Holds all data which are needed between tasks. All relevant data for the trade itself are stored in Trade.
|
||||
*/
|
||||
public class TakerProcessModel extends ProcessModel implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
transient private static final Logger log = LoggerFactory.getLogger(TakerProcessModel.class);
|
||||
|
||||
// Immutable
|
||||
public final Taker taker;
|
||||
public final Offerer offerer;
|
||||
|
||||
// Mutable
|
||||
private Transaction takeOfferFeeTx;
|
||||
private Transaction payoutTx;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public TakerProcessModel() {
|
||||
log.trace("Created by constructor");
|
||||
taker = new Taker();
|
||||
offerer = new Offerer();
|
||||
}
|
||||
|
||||
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
log.trace("Created from serialized form.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllServicesInitialized(Offer offer,
|
||||
MessageService messageService,
|
||||
WalletService walletService,
|
||||
TradeWalletService tradeWalletService,
|
||||
BlockChainService blockChainService,
|
||||
SignatureService signatureService,
|
||||
ArbitrationRepository arbitrationRepository,
|
||||
User user) {
|
||||
log.trace("onAllServicesInitialized");
|
||||
super.onAllServicesInitialized(offer,
|
||||
messageService,
|
||||
walletService,
|
||||
tradeWalletService,
|
||||
blockChainService,
|
||||
signatureService,
|
||||
arbitrationRepository,
|
||||
user);
|
||||
|
||||
taker.onAllServicesInitialized(offer, walletService, user);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter/Setter for Mutable objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Nullable
|
||||
public Transaction getPayoutTx() {
|
||||
return payoutTx;
|
||||
}
|
||||
|
||||
public void setPayoutTx(Transaction payoutTx) {
|
||||
this.payoutTx = payoutTx;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Transaction getTakeOfferFeeTx() {
|
||||
return takeOfferFeeTx;
|
||||
}
|
||||
|
||||
public void setTakeOfferFeeTx(Transaction takeOfferFeeTx) {
|
||||
this.takeOfferFeeTx = takeOfferFeeTx;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TakerProcessModel{" +
|
||||
"taker=" + taker +
|
||||
", offerer=" + offerer +
|
||||
", takeOfferFeeTx=" + takeOfferFeeTx +
|
||||
", payoutTx=" + payoutTx +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -1,109 +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.models;
|
||||
|
||||
import io.bitsquare.arbitration.ArbitrationRepository;
|
||||
import io.bitsquare.btc.BlockChainService;
|
||||
import io.bitsquare.btc.TradeWalletService;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.crypto.SignatureService;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.p2p.MailboxService;
|
||||
import io.bitsquare.p2p.MessageService;
|
||||
import io.bitsquare.trade.protocol.trade.TradeProcessModel;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Holds all data which are needed between tasks. All relevant data for the trade itself are stored in Trade.
|
||||
*/
|
||||
public class TakerTradeProcessModel extends TradeProcessModel implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
transient private static final Logger log = LoggerFactory.getLogger(TakerTradeProcessModel.class);
|
||||
|
||||
public final Taker taker = new Taker();
|
||||
public final Offerer offerer = new Offerer();
|
||||
|
||||
// written by tasks
|
||||
@Nullable private Transaction takeOfferFeeTx;
|
||||
@Nullable private Transaction payoutTx;
|
||||
|
||||
public TakerTradeProcessModel(){
|
||||
}
|
||||
|
||||
public void init(@NotNull Offer offer,
|
||||
@NotNull MessageService messageService,
|
||||
@NotNull MailboxService mailboxService,
|
||||
@NotNull WalletService walletService,
|
||||
@NotNull TradeWalletService tradeWalletService,
|
||||
@NotNull BlockChainService blockChainService,
|
||||
@NotNull SignatureService signatureService,
|
||||
@NotNull ArbitrationRepository arbitrationRepository,
|
||||
@NotNull User user) {
|
||||
|
||||
super.init(offer,
|
||||
messageService,
|
||||
mailboxService,
|
||||
walletService,
|
||||
tradeWalletService,
|
||||
blockChainService,
|
||||
signatureService,
|
||||
arbitrationRepository,
|
||||
user);
|
||||
|
||||
taker.registrationPubKey = walletService.getRegistrationAddressEntry().getPubKey();
|
||||
taker.registrationKeyPair = walletService.getRegistrationAddressEntry().getKeyPair();
|
||||
taker.addressEntry = walletService.getAddressEntry(id);
|
||||
taker.fiatAccount = user.getFiatAccount(offer.getBankAccountId());
|
||||
taker.accountId = user.getAccountId();
|
||||
taker.p2pSigPubKey = user.getP2PSigPubKey();
|
||||
taker.p2pEncryptPublicKey = user.getP2PEncryptPubKey();
|
||||
taker.tradeWalletPubKey = taker.addressEntry.getPubKey();
|
||||
}
|
||||
|
||||
public void setPayoutTx(@NotNull Transaction payoutTx) {
|
||||
this.payoutTx = payoutTx;
|
||||
}
|
||||
|
||||
public void setTakeOfferFeeTx(@NotNull Transaction takeOfferFeeTx) {
|
||||
this.takeOfferFeeTx = takeOfferFeeTx;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Transaction getTakeOfferFeeTx() {
|
||||
return takeOfferFeeTx;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Transaction getPayoutTx() {
|
||||
return payoutTx;
|
||||
}
|
||||
|
||||
}
|
|
@ -39,7 +39,7 @@ public class BroadcastTakeOfferFeeTx extends TakerTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
takerTradeProcessModel.tradeWalletService.broadcastTakeOfferFeeTx(takerTradeProcessModel.getTakeOfferFeeTx(),
|
||||
takerTradeProcessModel.getTradeWalletService().broadcastTakeOfferFeeTx(takerTradeProcessModel.getTakeOfferFeeTx(),
|
||||
new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
|
|
|
@ -35,18 +35,19 @@ public class CreateAndSignContract extends TakerTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
assert takerTradeProcessModel.getTakeOfferFeeTx() != null;
|
||||
Contract contract = new Contract(
|
||||
takerTradeProcessModel.offer,
|
||||
takerTradeProcessModel.getOffer(),
|
||||
model.getTradeAmount(),
|
||||
takerTradeProcessModel.getTakeOfferFeeTx().getHashAsString(),
|
||||
takerTradeProcessModel.offerer.accountId,
|
||||
takerTradeProcessModel.taker.accountId,
|
||||
takerTradeProcessModel.offerer.fiatAccount,
|
||||
takerTradeProcessModel.taker.fiatAccount,
|
||||
takerTradeProcessModel.offer.getP2PSigPubKey(),
|
||||
takerTradeProcessModel.taker.p2pSigPubKey);
|
||||
takerTradeProcessModel.offerer.getAccountId(),
|
||||
takerTradeProcessModel.taker.getAccountId(),
|
||||
takerTradeProcessModel.offerer.getFiatAccount(),
|
||||
takerTradeProcessModel.taker.getFiatAccount(),
|
||||
takerTradeProcessModel.getOffer().getP2PSigPubKey(),
|
||||
takerTradeProcessModel.taker.getP2pSigPubKey());
|
||||
String contractAsJson = Utilities.objectToJson(contract);
|
||||
String signature = takerTradeProcessModel.signatureService.signMessage(takerTradeProcessModel.taker.registrationKeyPair, contractAsJson);
|
||||
String signature = takerTradeProcessModel.getSignatureService().signMessage(takerTradeProcessModel.taker.getRegistrationKeyPair(), contractAsJson);
|
||||
|
||||
model.setContract(contract);
|
||||
model.setContractAsJson(contractAsJson);
|
||||
|
|
|
@ -35,7 +35,8 @@ public class CreateTakeOfferFeeTx extends TakerTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
Transaction createTakeOfferFeeTx = takerTradeProcessModel.tradeWalletService.createTakeOfferFeeTx(takerTradeProcessModel.taker.addressEntry);
|
||||
Transaction createTakeOfferFeeTx = takerTradeProcessModel.getTradeWalletService().createTakeOfferFeeTx(takerTradeProcessModel.taker
|
||||
.getAddressEntry());
|
||||
|
||||
takerTradeProcessModel.setTakeOfferFeeTx(createTakeOfferFeeTx);
|
||||
takerTrade.setProcessState(TakerTrade.TakerProcessState.TAKE_OFFER_FEE_TX_CREATED);
|
||||
|
|
|
@ -37,9 +37,10 @@ public class ProcessDepositTxPublishedMessage extends TakerTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
checkTradeId(takerTradeProcessModel.id, takerTradeProcessModel.getTradeMessage());
|
||||
|
||||
DepositTxPublishedMessage message = (DepositTxPublishedMessage) takerTradeProcessModel.getTradeMessage();
|
||||
checkTradeId(takerTradeProcessModel.getId(), message);
|
||||
checkNotNull(message);
|
||||
|
||||
takerTrade.setDepositTx(checkNotNull(message.depositTx));
|
||||
takerTrade.setProcessState(TakerTrade.TakerProcessState.DEPOSIT_PUBLISHED);
|
||||
|
||||
|
|
|
@ -37,13 +37,14 @@ public class ProcessFiatTransferStartedMessage extends TakerTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
checkTradeId(takerTradeProcessModel.id, takerTradeProcessModel.getTradeMessage());
|
||||
FiatTransferStartedMessage message = (FiatTransferStartedMessage) takerTradeProcessModel.getTradeMessage();
|
||||
checkTradeId(takerTradeProcessModel.getId(), message);
|
||||
checkNotNull(message);
|
||||
|
||||
takerTradeProcessModel.offerer.signature = checkNotNull(message.offererSignature);
|
||||
takerTradeProcessModel.offerer.payoutAmount = positiveCoinOf(nonZeroCoinOf(message.offererPayoutAmount));
|
||||
takerTradeProcessModel.taker.payoutAmount = positiveCoinOf(nonZeroCoinOf(message.takerPayoutAmount));
|
||||
takerTradeProcessModel.offerer.payoutAddressString = nonEmptyStringOf(message.offererPayoutAddress);
|
||||
takerTradeProcessModel.offerer.setSignature(checkNotNull(message.offererSignature));
|
||||
takerTradeProcessModel.offerer.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.offererPayoutAmount)));
|
||||
takerTradeProcessModel.taker.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.takerPayoutAmount)));
|
||||
takerTradeProcessModel.offerer.setPayoutAddressString(nonEmptyStringOf(message.offererPayoutAddress));
|
||||
takerTrade.setProcessState(TakerTrade.TakerProcessState.FIAT_PAYMENT_STARTED);
|
||||
|
||||
complete();
|
||||
|
|
|
@ -37,17 +37,18 @@ public class ProcessRequestTakerDepositPaymentMessage extends TakerTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
checkTradeId(takerTradeProcessModel.id, takerTradeProcessModel.getTradeMessage());
|
||||
RequestTakerDepositPaymentMessage message = (RequestTakerDepositPaymentMessage) takerTradeProcessModel.getTradeMessage();
|
||||
checkTradeId(takerTradeProcessModel.getId(), message);
|
||||
checkNotNull(message);
|
||||
|
||||
takerTradeProcessModel.offerer.connectedOutputsForAllInputs = checkNotNull(message.offererConnectedOutputsForAllInputs);
|
||||
takerTradeProcessModel.offerer.setConnectedOutputsForAllInputs(checkNotNull(message.offererConnectedOutputsForAllInputs));
|
||||
checkArgument(message.offererConnectedOutputsForAllInputs.size() > 0);
|
||||
takerTradeProcessModel.offerer.outputs = checkNotNull(message.offererOutputs);
|
||||
takerTradeProcessModel.offerer.tradeWalletPubKey = checkNotNull(message.offererTradeWalletPubKey);
|
||||
takerTradeProcessModel.offerer.p2pSigPublicKey = checkNotNull(message.offererP2PSigPublicKey);
|
||||
takerTradeProcessModel.offerer.p2pEncryptPubKey = checkNotNull(message.offererP2PEncryptPublicKey);
|
||||
takerTradeProcessModel.offerer.fiatAccount = checkNotNull(message.offererFiatAccount);
|
||||
takerTradeProcessModel.offerer.accountId = nonEmptyStringOf(message.offererAccountId);
|
||||
takerTradeProcessModel.offerer.setOutputs(checkNotNull(message.offererOutputs));
|
||||
takerTradeProcessModel.offerer.setTradeWalletPubKey(checkNotNull(message.offererTradeWalletPubKey));
|
||||
takerTradeProcessModel.offerer.setP2pSigPublicKey(checkNotNull(message.offererP2PSigPublicKey));
|
||||
takerTradeProcessModel.offerer.setP2pEncryptPubKey(checkNotNull(message.offererP2PEncryptPublicKey));
|
||||
takerTradeProcessModel.offerer.setFiatAccount(checkNotNull(message.offererFiatAccount));
|
||||
takerTradeProcessModel.offerer.setAccountId(nonEmptyStringOf(message.offererAccountId));
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -35,11 +35,11 @@ public class SendPayoutTxToOfferer extends TakerTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(takerTradeProcessModel.id, takerTradeProcessModel.getPayoutTx());
|
||||
takerTradeProcessModel.messageService.sendMessage(takerTrade.getTradingPeer(),
|
||||
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(takerTradeProcessModel.getId(), takerTradeProcessModel.getPayoutTx());
|
||||
takerTradeProcessModel.getMessageService().sendMessage(takerTrade.getTradingPeer(),
|
||||
tradeMessage,
|
||||
takerTradeProcessModel.offerer.p2pSigPublicKey,
|
||||
takerTradeProcessModel.offerer.p2pEncryptPubKey,
|
||||
takerTradeProcessModel.offerer.getP2pSigPublicKey(),
|
||||
takerTradeProcessModel.offerer.getP2pEncryptPubKey(),
|
||||
new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
|
|
|
@ -39,13 +39,14 @@ public class SendRequestDepositTxInputsMessage extends TakerTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
assert takerTradeProcessModel.getTakeOfferFeeTx() != null;
|
||||
RequestDepositTxInputsMessage msg = new RequestDepositTxInputsMessage(
|
||||
takerTradeProcessModel.id,
|
||||
takerTradeProcessModel.getId(),
|
||||
takerTradeProcessModel.getTakeOfferFeeTx().getHashAsString(),
|
||||
takerTrade.getTradeAmount(),
|
||||
takerTradeProcessModel.taker.tradeWalletPubKey);
|
||||
takerTradeProcessModel.taker.getTradeWalletPubKey());
|
||||
|
||||
takerTradeProcessModel.messageService.sendMessage(takerTrade.getTradingPeer(), msg, new SendMessageListener() {
|
||||
takerTradeProcessModel.getMessageService().sendMessage(takerTrade.getTradingPeer(), msg, new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
log.trace("Sending TakeOfferFeePayedMessage succeeded.");
|
||||
|
|
|
@ -36,20 +36,19 @@ public class SendSignedTakerDepositTx extends TakerTradeTask {
|
|||
protected void doRun() {
|
||||
try {
|
||||
RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(
|
||||
takerTradeProcessModel.id,
|
||||
takerTradeProcessModel.taker.fiatAccount,
|
||||
takerTradeProcessModel.taker.accountId,
|
||||
takerTradeProcessModel.taker.p2pSigPubKey,
|
||||
takerTradeProcessModel.taker.p2pEncryptPublicKey,
|
||||
takerTradeProcessModel.getId(),
|
||||
takerTradeProcessModel.taker.getFiatAccount(),
|
||||
takerTradeProcessModel.taker.getAccountId(),
|
||||
takerTradeProcessModel.taker.getP2pSigPubKey(),
|
||||
takerTradeProcessModel.taker.getP2pEncryptPublicKey(),
|
||||
takerTrade.getContractAsJson(),
|
||||
takerTrade.getTakerContractSignature(),
|
||||
takerTradeProcessModel.taker.addressEntry.getAddressString(),
|
||||
takerTradeProcessModel.taker.preparedDepositTx,
|
||||
takerTradeProcessModel.taker.connectedOutputsForAllInputs,
|
||||
takerTradeProcessModel.taker.outputs
|
||||
takerTradeProcessModel.taker.getAddressEntry().getAddressString(),
|
||||
takerTradeProcessModel.taker.getPreparedDepositTx(),
|
||||
takerTradeProcessModel.taker.getConnectedOutputsForAllInputs()
|
||||
);
|
||||
|
||||
takerTradeProcessModel.messageService.sendMessage(takerTrade.getTradingPeer(), tradeMessage, new SendMessageListener() {
|
||||
takerTradeProcessModel.getMessageService().sendMessage(takerTrade.getTradingPeer(), tradeMessage, new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
complete();
|
||||
|
|
|
@ -39,16 +39,16 @@ public class SignAndPublishPayoutTx extends TakerTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
takerTradeProcessModel.tradeWalletService.takerSignsAndPublishPayoutTx(
|
||||
takerTradeProcessModel.getTradeWalletService().takerSignsAndPublishPayoutTx(
|
||||
takerTrade.getDepositTx(),
|
||||
takerTradeProcessModel.offerer.signature,
|
||||
takerTradeProcessModel.offerer.payoutAmount,
|
||||
takerTradeProcessModel.taker.payoutAmount,
|
||||
takerTradeProcessModel.offerer.payoutAddressString,
|
||||
takerTradeProcessModel.taker.addressEntry,
|
||||
takerTradeProcessModel.offerer.tradeWalletPubKey,
|
||||
takerTradeProcessModel.taker.tradeWalletPubKey,
|
||||
takerTradeProcessModel.arbitratorPubKey,
|
||||
takerTradeProcessModel.offerer.getSignature(),
|
||||
takerTradeProcessModel.offerer.getPayoutAmount(),
|
||||
takerTradeProcessModel.taker.getPayoutAmount(),
|
||||
takerTradeProcessModel.offerer.getPayoutAddressString(),
|
||||
takerTradeProcessModel.taker.getAddressEntry(),
|
||||
takerTradeProcessModel.offerer.getTradeWalletPubKey(),
|
||||
takerTradeProcessModel.taker.getTradeWalletPubKey(),
|
||||
takerTradeProcessModel.getArbitratorPubKey(),
|
||||
new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
|
|
|
@ -36,7 +36,7 @@ public class TakerCommitDepositTx extends TakerTradeTask {
|
|||
protected void doRun() {
|
||||
try {
|
||||
// To access tx confidence we need to add that tx into our wallet.
|
||||
Transaction depositTx = takerTradeProcessModel.tradeWalletService.commitsDepositTx(takerTrade.getDepositTx());
|
||||
Transaction depositTx = takerTradeProcessModel.getTradeWalletService().commitsDepositTx(takerTrade.getDepositTx());
|
||||
|
||||
takerTrade.setDepositTx(depositTx);
|
||||
|
||||
|
|
|
@ -37,23 +37,23 @@ public class TakerCreatesAndSignsDepositTx extends TakerTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
assert takerTrade.getTradeAmount() != null;
|
||||
Coin takerInputAmount = takerTrade.getTradeAmount().add(takerTrade.getSecurityDeposit()).add(FeePolicy.TX_FEE);
|
||||
Coin msOutputAmount = takerInputAmount.add(takerTrade.getSecurityDeposit());
|
||||
|
||||
TradeWalletService.Result result = takerTradeProcessModel.tradeWalletService.takerCreatesAndSignsDepositTx(
|
||||
TradeWalletService.Result result = takerTradeProcessModel.getTradeWalletService().takerCreatesAndSignsDepositTx(
|
||||
takerInputAmount,
|
||||
msOutputAmount,
|
||||
takerTradeProcessModel.offerer.connectedOutputsForAllInputs,
|
||||
takerTradeProcessModel.offerer.outputs,
|
||||
takerTradeProcessModel.taker.addressEntry,
|
||||
takerTradeProcessModel.offerer.tradeWalletPubKey,
|
||||
takerTradeProcessModel.taker.tradeWalletPubKey,
|
||||
takerTradeProcessModel.arbitratorPubKey);
|
||||
takerTradeProcessModel.offerer.getConnectedOutputsForAllInputs(),
|
||||
takerTradeProcessModel.offerer.getOutputs(),
|
||||
takerTradeProcessModel.taker.getAddressEntry(),
|
||||
takerTradeProcessModel.offerer.getTradeWalletPubKey(),
|
||||
takerTradeProcessModel.taker.getTradeWalletPubKey(),
|
||||
takerTradeProcessModel.getArbitratorPubKey());
|
||||
|
||||
|
||||
takerTradeProcessModel.taker.connectedOutputsForAllInputs = result.getConnectedOutputsForAllInputs();
|
||||
takerTradeProcessModel.taker.outputs = result.getOutputs();
|
||||
takerTradeProcessModel.taker.preparedDepositTx = result.getDepositTx();
|
||||
takerTradeProcessModel.taker.setConnectedOutputsForAllInputs(result.getConnectedOutputsForAllInputs());
|
||||
takerTradeProcessModel.taker.setPreparedDepositTx(result.getDepositTx());
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -23,17 +23,17 @@ import io.bitsquare.btc.exceptions.WalletException;
|
|||
import io.bitsquare.common.taskrunner.Task;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.TakerTrade;
|
||||
import io.bitsquare.trade.protocol.trade.taker.models.TakerTradeProcessModel;
|
||||
import io.bitsquare.trade.protocol.trade.taker.models.TakerProcessModel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TakerTradeTask extends Task<TakerTrade> {
|
||||
class TakerTradeTask extends Task<TakerTrade> {
|
||||
private static final Logger log = LoggerFactory.getLogger(TakerTradeTask.class);
|
||||
protected final TakerTradeProcessModel takerTradeProcessModel;
|
||||
protected final TakerProcessModel takerTradeProcessModel;
|
||||
protected final TakerTrade takerTrade;
|
||||
|
||||
public TakerTradeTask(TaskRunner taskHandler, TakerTrade model) {
|
||||
TakerTradeTask(TaskRunner taskHandler, TakerTrade model) {
|
||||
super(taskHandler, model);
|
||||
|
||||
takerTrade = model;
|
||||
|
|
|
@ -34,7 +34,7 @@ public class VerifyOfferFeePayment extends TakerTradeTask {
|
|||
protected void doRun() {
|
||||
try {
|
||||
//TODO impl. missing
|
||||
int numOfPeersSeenTx = takerTradeProcessModel.walletService.getNumOfPeersSeenTx(takerTradeProcessModel.getTakeOfferFeeTx().getHashAsString());
|
||||
int numOfPeersSeenTx = takerTradeProcessModel.getWalletService().getNumOfPeersSeenTx(takerTradeProcessModel.getTakeOfferFeeTx().getHashAsString());
|
||||
/* if (numOfPeersSeenTx > 2) {
|
||||
resultHandler.handleResult();
|
||||
}*/
|
||||
|
|
|
@ -33,9 +33,10 @@ public class VerifyOffererAccount extends TakerTradeTask {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
if (takerTradeProcessModel.blockChainService.verifyAccountRegistration()) {
|
||||
if (takerTradeProcessModel.blockChainService.isAccountBlackListed(takerTradeProcessModel.offerer.accountId, takerTradeProcessModel.offerer
|
||||
.fiatAccount)) {
|
||||
if (takerTradeProcessModel.getBlockChainService().verifyAccountRegistration()) {
|
||||
if (takerTradeProcessModel.getBlockChainService().isAccountBlackListed(takerTradeProcessModel.offerer.getAccountId(), takerTradeProcessModel
|
||||
.offerer
|
||||
.getFiatAccount())) {
|
||||
failed("Taker is blacklisted.");
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -54,6 +54,4 @@ public class Validator {
|
|||
public static void checkTradeId(String tradeId, TradeMessage tradeMessage) {
|
||||
checkArgument(tradeId.equals(tradeMessage.tradeId));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue