Remove listeners/unbind at views. Add more error handling

This commit is contained in:
Manfred Karrer 2015-04-22 18:38:53 +02:00
parent 919e31f0d5
commit 3f6f8dd160
90 changed files with 1940 additions and 1610 deletions

View file

@ -23,8 +23,7 @@ import org.slf4j.LoggerFactory;
public abstract class Task<T extends Model> {
private static final Logger log = LoggerFactory.getLogger(Task.class);
public static Class<? extends Task> taskToInterceptBeforeRun;
public static Class<? extends Task> taskToInterceptAfterRun;
public static Class<? extends Task> taskToIntercept;
private final TaskRunner taskHandler;
protected final T model;
@ -35,26 +34,11 @@ public abstract class Task<T extends Model> {
this.model = model;
}
protected void run() {
try {
interceptBeforeRun();
doRun();
} catch (Throwable t) {
appendExceptionToErrorMessage(t);
failed();
}
}
abstract protected void run();
abstract protected void doRun();
private void interceptBeforeRun() {
if (getClass() == taskToInterceptBeforeRun)
throw new InterceptTaskException("Task intercepted before run got executed. Task = " + getClass().getSimpleName());
}
private void interceptBeforeComplete() {
if (getClass() == taskToInterceptAfterRun)
throw new InterceptTaskException("Task intercepted before complete was called. Task = " + getClass().getSimpleName());
protected void runInterceptHook() {
if (getClass() == taskToIntercept)
throw new InterceptTaskException("Task intercepted for testing purpose. Task = " + getClass().getSimpleName());
}
protected void appendToErrorMessage(String message) {
@ -69,12 +53,6 @@ public abstract class Task<T extends Model> {
}
protected void complete() {
try {
interceptBeforeComplete();
} catch (Throwable t) {
appendExceptionToErrorMessage(t);
failed();
}
taskHandler.handleComplete();
}
@ -84,6 +62,7 @@ public abstract class Task<T extends Model> {
}
protected void failed(Throwable t) {
t.printStackTrace();
appendExceptionToErrorMessage(t);
failed();
}

View file

@ -21,8 +21,6 @@ import com.google.common.base.Throwables;
import java.io.File;
import java.io.IOException;
import java.io.InvalidClassException;
import java.io.InvalidObjectException;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
@ -131,7 +129,7 @@ public class Storage<T extends Serializable> {
log.info("Backup {} completed in {}msec", serializable.getClass().getSimpleName(), System.currentTimeMillis() - now);
return persistedObject;
} catch (InvalidClassException | InvalidObjectException | ClassCastException | ClassNotFoundException e) {
} catch (ClassCastException | ClassNotFoundException | IOException e) {
e.printStackTrace();
log.error("Version of persisted class has changed. We cannot read the persisted data anymore. We make a backup and remove the inconsistent " +
"file.");

View file

@ -33,6 +33,8 @@ import io.bitsquare.storage.Storage;
import io.bitsquare.trade.offer.Offer;
import io.bitsquare.trade.protocol.trade.ProcessModel;
import io.bitsquare.trade.protocol.trade.TradeProtocol;
import io.bitsquare.trade.states.BuyerTradeState;
import io.bitsquare.trade.states.SellerTradeState;
import io.bitsquare.trade.states.TradeState;
import io.bitsquare.user.User;
@ -245,6 +247,13 @@ abstract public class Trade implements Tradable, Model, Serializable {
storage.queueUpForSave();
}
public void setFaultState() {
if (this instanceof SellerTrade)
setProcessState(SellerTradeState.ProcessState.FAULT);
else if (this instanceof BuyerTrade)
setProcessState(BuyerTradeState.ProcessState.FAULT);
}
public void setLifeCycleState(Trade.LifeCycleState lifeCycleState) {
this.lifeCycleState = lifeCycleState;
lifeCycleStateProperty.set(lifeCycleState);

View file

@ -59,7 +59,10 @@ public class Offer implements Serializable {
AVAILABLE,
NOT_AVAILABLE,
REMOVED,
OFFERER_OFFLINE
OFFERER_OFFLINE,
TIMEOUT,
FAULT
}

View file

@ -23,7 +23,7 @@ import io.bitsquare.p2p.DHTService;
import java.util.List;
import javafx.beans.property.LongProperty;
import javafx.beans.property.ReadOnlyLongProperty;
public interface OfferBookService extends DHTService {
@ -39,7 +39,7 @@ public interface OfferBookService extends DHTService {
void removeListener(Listener listener);
LongProperty invalidationTimestampProperty();
ReadOnlyLongProperty invalidationTimestampProperty();
void requestInvalidationTimeStampFromDHT(String fiatCode);

View file

@ -21,14 +21,12 @@ import io.bitsquare.app.Version;
import io.bitsquare.storage.Storage;
import io.bitsquare.trade.Tradable;
import io.bitsquare.trade.TradableList;
import org.bitcoinj.utils.Threading;
import io.bitsquare.util.Utilities;
import java.io.Serializable;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -95,26 +93,16 @@ public class OpenOffer implements Tradable, Serializable {
private void startTimeout() {
log.trace("startTimeout");
stopTimeout();
timeoutTimer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
Threading.USER_THREAD.execute(() -> {
log.debug("Timeout reached");
if (state == State.RESERVED)
setState(State.AVAILABLE);
});
}
};
timeoutTimer.schedule(task, TIMEOUT);
timeoutTimer = Utilities.setTimeout(TIMEOUT, () -> {
log.debug("Timeout reached");
if (state == State.RESERVED)
setState(State.AVAILABLE);
});
}
protected void stopTimeout() {
log.trace("stopTimeout");
if (timeoutTimer != null) {
timeoutTimer.cancel();
timeoutTimer = null;

View file

@ -34,6 +34,7 @@ import java.util.Map;
import javax.inject.Inject;
import javafx.beans.property.LongProperty;
import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.SimpleLongProperty;
import net.tomp2p.dht.FutureGet;
@ -220,7 +221,7 @@ public class TomP2POfferBookService extends TomP2PDHTService implements OfferBoo
if (offerDataObject instanceof Offer) {
offers.add((Offer) offerDataObject);
}
} catch (ClassNotFoundException | IOException e) {
} catch (ClassCastException | ClassNotFoundException | IOException e) {
e.printStackTrace();
log.warn(e.getMessage());
}
@ -293,7 +294,7 @@ public class TomP2POfferBookService extends TomP2PDHTService implements OfferBoo
}
}
public LongProperty invalidationTimestampProperty() {
public ReadOnlyLongProperty invalidationTimestampProperty() {
return invalidationTimestamp;
}

View file

@ -30,11 +30,9 @@ import io.bitsquare.trade.protocol.availability.messages.OfferMessage;
import io.bitsquare.trade.protocol.availability.tasks.GetPeerAddress;
import io.bitsquare.trade.protocol.availability.tasks.ProcessOfferAvailabilityResponse;
import io.bitsquare.trade.protocol.availability.tasks.SendOfferAvailabilityRequest;
import org.bitcoinj.utils.Threading;
import io.bitsquare.util.Utilities;
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -52,7 +50,6 @@ public class OfferAvailabilityProtocol {
private final DecryptedMessageHandler decryptedMessageHandler;
private Timer timeoutTimer;
private boolean isCanceled;
private TaskRunner<OfferAvailabilityModel> taskRunner;
@ -84,8 +81,14 @@ public class OfferAvailabilityProtocol {
model.messageService.addDecryptedMessageHandler(decryptedMessageHandler);
taskRunner = new TaskRunner<>(model,
() -> log.debug("sequence at onCheckOfferAvailability completed"),
log::error
() -> {
log.debug("sequence at onCheckOfferAvailability completed");
stopTimeout();
},
(errorMessage) -> {
log.error(errorMessage);
stopTimeout();
}
);
taskRunner.addTasks(
GetPeerAddress.class,
@ -96,7 +99,6 @@ public class OfferAvailabilityProtocol {
}
public void cancel() {
isCanceled = true;
taskRunner.cancel();
cleanup();
}
@ -119,15 +121,18 @@ public class OfferAvailabilityProtocol {
private void handle(OfferAvailabilityResponse message) {
stopTimeout();
startTimeout();
model.setMessage(message);
taskRunner = new TaskRunner<>(model,
() -> {
log.debug("sequence at handleReportOfferAvailabilityMessage completed");
log.debug("sequence at handle OfferAvailabilityResponse completed");
stopTimeout();
resultHandler.handleResult();
},
(errorMessage) -> {
log.error(errorMessage);
stopTimeout();
errorMessageHandler.handleErrorMessage(errorMessage);
}
);
@ -136,26 +141,16 @@ public class OfferAvailabilityProtocol {
}
protected void startTimeout() {
log.debug("startTimeout");
stopTimeout();
timeoutTimer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
Threading.USER_THREAD.execute(() -> {
log.debug("Timeout reached");
errorMessageHandler.handleErrorMessage("Timeout reached: Peer has not responded.");
model.offer.setState(Offer.State.OFFERER_OFFLINE);
});
}
};
timeoutTimer.schedule(task, TIMEOUT);
timeoutTimer = Utilities.setTimeout(TIMEOUT, () -> {
log.warn("Timeout reached");
errorMessageHandler.handleErrorMessage("Timeout reached: Peer has not responded.");
model.offer.setState(Offer.State.TIMEOUT);
});
}
protected void stopTimeout() {
log.debug("stopTimeout");
if (timeoutTimer != null) {
timeoutTimer.cancel();
timeoutTimer = null;

View file

@ -37,13 +37,13 @@ public class GetPeerAddress extends Task<OfferAvailabilityModel> {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
model.addressService.findPeerAddress(model.offer.getPubKeyRing(), new GetPeerAddressListener() {
@Override
public void onResult(Peer peer) {
model.setPeer(peer);
complete();
}
@ -55,6 +55,7 @@ public class GetPeerAddress extends Task<OfferAvailabilityModel> {
}
});
} catch (Throwable t) {
model.offer.setState(Offer.State.FAULT);
failed(t);
}
}

View file

@ -34,8 +34,9 @@ public class ProcessOfferAvailabilityResponse extends Task<OfferAvailabilityMode
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
OfferAvailabilityResponse offerAvailabilityResponse = (OfferAvailabilityResponse) model.getMessage();
if (model.offer.getState() != Offer.State.REMOVED) {
@ -47,6 +48,7 @@ public class ProcessOfferAvailabilityResponse extends Task<OfferAvailabilityMode
complete();
} catch (Throwable t) {
model.offer.setState(Offer.State.FAULT);
failed(t);
}
}

View file

@ -35,8 +35,9 @@ public class SendOfferAvailabilityRequest extends Task<OfferAvailabilityModel> {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
OfferAvailabilityRequest message = new OfferAvailabilityRequest(model.offer.getId(), model.getPubKeyRing());
model.messageService.sendEncryptedMessage(model.getPeer(),
model.offer.getPubKeyRing(),
@ -55,6 +56,7 @@ public class SendOfferAvailabilityRequest extends Task<OfferAvailabilityModel> {
}
});
} catch (Throwable t) {
model.offer.setState(Offer.State.FAULT);
failed(t);
}
}

View file

@ -35,7 +35,7 @@ public class PlaceOfferModel implements Model {
public final WalletService walletService;
public final TradeWalletService tradeWalletService;
public final OfferBookService offerBookService;
public boolean offerAddedToOfferBook;
private Transaction transaction;
public PlaceOfferModel(Offer offer,

View file

@ -61,6 +61,15 @@ public class PlaceOfferProtocol {
},
(errorMessage) -> {
log.error(errorMessage);
if (model.offerAddedToOfferBook) {
model.offerBookService.removeOffer(model.offer,
() -> {
model.offerAddedToOfferBook = false;
log.debug("Offer removed from offer book.");
},
(message, throwable) -> log.error(message));
}
errorMessageHandler.handleErrorMessage(errorMessage);
}
);

View file

@ -33,9 +33,17 @@ public class AddOfferToRemoteOfferBook extends Task<PlaceOfferModel> {
}
@Override
protected void doRun() {
model.offerBookService.addOffer(model.offer,
this::complete,
(message, throwable) -> failed(throwable));
protected void run() {
try {
runInterceptHook();
model.offerBookService.addOffer(model.offer,
() -> {
model.offerAddedToOfferBook = true;
complete();
},
(message, throwable) -> failed(throwable));
} catch (Throwable t) {
failed(t);
}
}
}

View file

@ -47,58 +47,61 @@ public class BroadcastCreateOfferFeeTx extends Task<PlaceOfferModel> {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
Coin totalsNeeded = model.offer.getSecurityDeposit().add(FeePolicy.CREATE_OFFER_FEE).add(FeePolicy.TX_FEE);
AddressEntry addressEntry = model.walletService.getAddressEntry(model.offer.getId());
Coin balance = model.walletService.getBalanceForAddress(addressEntry.getAddress());
if (balance.compareTo(totalsNeeded) >= 0) {
model.tradeWalletService.broadcastTx(model.getTransaction(), new FutureCallback<Transaction>() {
@Override
public void onSuccess(Transaction transaction) {
log.info("Broadcast of offer fee payment succeeded: transaction = " + transaction.toString());
Coin totalsNeeded = model.offer.getSecurityDeposit().add(FeePolicy.CREATE_OFFER_FEE).add(FeePolicy.TX_FEE);
AddressEntry addressEntry = model.walletService.getAddressEntry(model.offer.getId());
Coin balance = model.walletService.getBalanceForAddress(addressEntry.getAddress());
if (balance.compareTo(totalsNeeded) >= 0) {
model.tradeWalletService.broadcastTx(model.getTransaction(), new FutureCallback<Transaction>() {
@Override
public void onSuccess(Transaction transaction) {
log.info("Broadcast of offer fee payment succeeded: transaction = " + transaction.toString());
if (model.getTransaction().getHashAsString().equals(transaction.getHashAsString())) {
// No tx malleability happened after broadcast (still not in blockchain)
complete();
if (model.getTransaction().getHashAsString().equals(transaction.getHashAsString())) {
// No tx malleability happened after broadcast (still not in blockchain)
complete();
}
else {
log.warn("Tx malleability happened after broadcast. We publish the changed offer to the DHT again.");
// Tx malleability happened after broadcast. We publish the changed offer to the DHT again.
model.offerBookService.removeOffer(model.offer,
() -> {
log.info("We store now the changed txID to the offer and add that again.");
// We store now the changed txID to the offer and add that again.
model.offer.setOfferFeePaymentTxID(transaction.getHashAsString());
model.offerBookService.addOffer(model.offer,
BroadcastCreateOfferFeeTx.this::complete,
(message, throwable) -> {
log.error("addOffer failed");
addOfferFailed = true;
failed(throwable);
updateStateOnFault();
});
},
(message, throwable) -> {
log.error("removeOffer failed");
removeOfferFailed = true;
failed(throwable);
updateStateOnFault();
});
}
}
else {
log.warn("Tx malleability happened after broadcast. We publish the changed offer to the DHT again.");
// Tx malleability happened after broadcast. We publish the changed offer to the DHT again.
model.offerBookService.removeOffer(model.offer,
() -> {
log.info("We store now the changed txID to the offer and add that again.");
// We store now the changed txID to the offer and add that again.
model.offer.setOfferFeePaymentTxID(transaction.getHashAsString());
model.offerBookService.addOffer(model.offer,
BroadcastCreateOfferFeeTx.this::complete,
(message, throwable) -> {
log.error("addOffer failed");
addOfferFailed = true;
failed(throwable);
updateStateOnFault();
});
},
(message, throwable) -> {
log.error("removeOffer failed");
removeOfferFailed = true;
failed(throwable);
updateStateOnFault();
});
}
}
@Override
public void onFailure(@NotNull Throwable t) {
failed(t);
updateStateOnFault();
}
});
}
else {
failed("Not enough balance for placing the offer.");
updateStateOnFault();
@Override
public void onFailure(@NotNull Throwable t) {
failed(t);
updateStateOnFault();
}
});
}
else {
failed("Not enough balance for placing the offer.");
updateStateOnFault();
}
} catch (Throwable t) {
failed(t);
}
}

View file

@ -34,8 +34,9 @@ public class CreateOfferFeeTx extends Task<PlaceOfferModel> {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
Transaction transaction = model.tradeWalletService.createOfferFeeTx(
model.walletService.getAddressEntry(model.offer.getId()));

View file

@ -32,8 +32,9 @@ public class ValidateOffer extends Task<PlaceOfferModel> {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
model.offer.validate();
complete();

View file

@ -102,8 +102,8 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
CreateDepositTxInputs.class,
SendPayDepositRequest.class
);
taskRunner.run();
startTimeout();
taskRunner.run();
}
@Override

View file

@ -116,8 +116,8 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
CreateDepositTxInputs.class,
SendPayDepositRequest.class
);
taskRunner.run();
startTimeout();
taskRunner.run();
}

View file

@ -100,8 +100,8 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
CreateAndSignDepositTx.class,
SendPublishDepositTxRequest.class
);
taskRunner.run();
startTimeout();
taskRunner.run();
}
@Override

View file

@ -128,8 +128,8 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
BroadcastTakeOfferFeeTx.class,
SendDepositTxInputsRequest.class
);
taskRunner.run();
startTimeout();
taskRunner.run();
}
@ -153,8 +153,8 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
CreateAndSignDepositTx.class,
SendPublishDepositTxRequest.class
);
taskRunner.run();
startTimeout();
taskRunner.run();
}
private void handle(DepositTxPublishedMessage tradeMessage) {

View file

@ -32,11 +32,9 @@ import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
import io.bitsquare.trade.states.BuyerTradeState;
import io.bitsquare.trade.states.SellerTradeState;
import org.bitcoinj.utils.Threading;
import io.bitsquare.util.Utilities;
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -141,28 +139,18 @@ public abstract class TradeProtocol {
}
protected void startTimeout() {
log.debug("startTimeout");
stopTimeout();
timeoutTimer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
Threading.USER_THREAD.execute(() -> {
log.debug("Timeout reached");
/* if (trade instanceof SellerTrade)
trade.setProcessState(SellerTradeState.ProcessState.TIMEOUT);
else if (trade instanceof BuyerTrade)
trade.setProcessState(BuyerTradeState.ProcessState.TIMEOUT);*/
});
}
};
timeoutTimer.schedule(task, TIMEOUT);
timeoutTimer = Utilities.setTimeout(TIMEOUT, () -> {
log.debug("Timeout reached");
if (trade instanceof SellerTrade)
trade.setProcessState(SellerTradeState.ProcessState.TIMEOUT);
else if (trade instanceof BuyerTrade)
trade.setProcessState(BuyerTradeState.ProcessState.TIMEOUT);
});
}
protected void stopTimeout() {
log.debug("stopTimeout");
if (timeoutTimer != null) {
timeoutTimer.cancel();
timeoutTimer = null;

View file

@ -38,6 +38,16 @@ public class TradeTask extends Task<Trade> {
}
@Override
protected void doRun() {
protected void run() {
}
@Override
protected void failed(Throwable t) {
t.printStackTrace();
appendExceptionToErrorMessage(t);
trade.setThrowable(t);
trade.setErrorMessage(errorMessage);
trade.setFaultState();
failed();
}
}

View file

@ -37,8 +37,9 @@ public class CreateDepositTxInputs extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
log.debug("trade.id" + trade.getId());
Coin inputAmount = trade.getSecurityDeposit().add(FeePolicy.TX_FEE);
TradeWalletService.Result result = processModel.getTradeWalletService().createDepositTxInputs(inputAmount,

View file

@ -37,8 +37,9 @@ public class ProcessDepositTxInputsRequest extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
DepositTxInputsRequest message = (DepositTxInputsRequest) processModel.getTradeMessage();
checkTradeId(processModel.getId(), message);
checkNotNull(message);

View file

@ -38,8 +38,9 @@ public class ProcessFinalizePayoutTxRequest extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
FinalizePayoutTxRequest message = (FinalizePayoutTxRequest) processModel.getTradeMessage();
checkTradeId(processModel.getId(), message);
checkNotNull(message);

View file

@ -37,8 +37,9 @@ public class ProcessPublishDepositTxRequest extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
PublishDepositTxRequest message = (PublishDepositTxRequest) processModel.getTradeMessage();
checkTradeId(processModel.getId(), message);
checkNotNull(message);

View file

@ -36,8 +36,9 @@ public class SendDepositTxPublishedMessage extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
DepositTxPublishedMessage tradeMessage = new DepositTxPublishedMessage(processModel.getId(), trade.getDepositTx());
processModel.getMessageService().sendEncryptedMessage(

View file

@ -36,8 +36,9 @@ public class SendFiatTransferStartedMessage extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
FiatTransferStartedMessage tradeMessage = new FiatTransferStartedMessage(processModel.getId(),
processModel.getAddressEntry().getAddressString()
);

View file

@ -36,8 +36,9 @@ public class SendPayDepositRequest extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
boolean isInitialRequest = trade instanceof BuyerAsTakerTrade;
PayDepositRequest tradeMessage = new PayDepositRequest(
processModel.getId(),

View file

@ -36,8 +36,9 @@ public class SendPayoutTxFinalizedMessage extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
PayoutTxFinalizedMessage tradeMessage = new PayoutTxFinalizedMessage(processModel.getId(), trade.getPayoutTx());
processModel.getMessageService().sendEncryptedMessage(
trade.getTradingPeer(),

View file

@ -35,8 +35,9 @@ public class SignAndFinalizePayoutTx extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
assert trade.getTradeAmount() != null;
assert trade.getSecurityDeposit() != null;
Coin sellerPayoutAmount = trade.getSecurityDeposit();

View file

@ -44,8 +44,9 @@ public class SignAndPublishDepositTx extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
Coin inputAmount = trade.getSecurityDeposit().add(FeePolicy.TX_FEE);
processModel.getTradeWalletService().signAndPublishDepositTx(

View file

@ -35,8 +35,9 @@ public class VerifyAndSignContract extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
Contract contract = new Contract(
processModel.getOffer(),
trade.getTradeAmount(),

View file

@ -32,8 +32,9 @@ public class VerifyTakeOfferFeePayment extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
//TODO mocked yet, need a confidence listeners
int numOfPeersSeenTx = processModel.getWalletService().getNumOfPeersSeenTx(processModel.getTakeOfferFeeTxId());
/* if (numOfPeersSeenTx > 2) {

View file

@ -33,8 +33,9 @@ public class VerifyTakerAccount extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
//TODO mocked yet
if (processModel.getBlockChainService().verifyAccountRegistration()) {
if (processModel.getBlockChainService().isAccountBlackListed(processModel.tradingPeer.getAccountId(),

View file

@ -34,8 +34,9 @@ public class CommitDepositTx extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
// To access tx confidence we need to add that tx into our wallet.
Transaction depositTx = processModel.getTradeWalletService().commitTx(trade.getDepositTx());

View file

@ -34,8 +34,9 @@ public class CreateAndSignContract extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
assert processModel.getTakeOfferFeeTxId() != null;
Contract contract = new Contract(
processModel.getOffer(),

View file

@ -36,8 +36,9 @@ public class CreateAndSignDepositTx extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
assert trade.getTradeAmount() != null;
Coin inputAmount = trade.getSecurityDeposit().add(FeePolicy.TX_FEE).add(trade.getTradeAmount());
Coin msOutputAmount = inputAmount.add(trade.getSecurityDeposit());

View file

@ -37,8 +37,9 @@ public class ProcessDepositTxPublishedMessage extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
DepositTxPublishedMessage message = (DepositTxPublishedMessage) processModel.getTradeMessage();
checkTradeId(processModel.getId(), message);
checkNotNull(message);

View file

@ -37,8 +37,9 @@ public class ProcessFiatTransferStartedMessage extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
FiatTransferStartedMessage message = (FiatTransferStartedMessage) processModel.getTradeMessage();
checkTradeId(processModel.getId(), message);
checkNotNull(message);

View file

@ -36,8 +36,9 @@ public class ProcessPayDepositRequest extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
PayDepositRequest message = (PayDepositRequest) processModel.getTradeMessage();
checkTradeId(processModel.getId(), message);
checkNotNull(message);

View file

@ -37,8 +37,9 @@ public class ProcessPayoutTxFinalizedMessage extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
PayoutTxFinalizedMessage message = (PayoutTxFinalizedMessage) processModel.getTradeMessage();
checkTradeId(processModel.getId(), message);
checkNotNull(message);

View file

@ -39,8 +39,9 @@ public class SendDepositTxInputsRequest extends TradeTask {
private int retryCounter = 0;
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
assert processModel.getTakeOfferFeeTx() != null;
DepositTxInputsRequest message = new DepositTxInputsRequest(
processModel.getId(),
@ -67,7 +68,7 @@ public class SendDepositTxInputsRequest extends TradeTask {
// We try to repeat once and if that fails as well we persist the state for a later retry.
if (retryCounter == 0) {
retryCounter++;
Threading.USER_THREAD.execute(SendDepositTxInputsRequest.this::doRun);
Threading.USER_THREAD.execute(SendDepositTxInputsRequest.this::run);
}
else {
appendToErrorMessage("Sending TakeOfferFeePayedMessage to offerer failed. Maybe the network connection was " +

View file

@ -36,8 +36,9 @@ public class SendFinalizePayoutTxRequest extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
FinalizePayoutTxRequest message = new FinalizePayoutTxRequest(
processModel.getId(),
processModel.getPayoutTxSignature(),

View file

@ -35,8 +35,9 @@ public class SendPublishDepositTxRequest extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
PublishDepositTxRequest tradeMessage = new PublishDepositTxRequest(
processModel.getId(),
processModel.getFiatAccount(),

View file

@ -34,8 +34,9 @@ public class SignPayoutTx extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
assert trade.getTradeAmount() != null;
assert trade.getSecurityDeposit() != null;
Coin sellerPayoutAmount = trade.getSecurityDeposit();

View file

@ -38,8 +38,9 @@ public class CommitPayoutTx extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
Transaction transaction = processModel.getTradeWalletService().commitTx(trade.getPayoutTx());
trade.setPayoutTx(transaction);

View file

@ -47,8 +47,9 @@ public class SetupPayoutTxLockTimeReachedListener extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
log.debug("ChainHeight/LockTime: {} / {}", processModel.getTradeWalletService().getBestChainHeight(), trade.getLockTime());
if (processModel.getTradeWalletService().getBestChainHeight() >= trade.getLockTime()) {
broadcastTx();

View file

@ -38,35 +38,25 @@ public class BroadcastTakeOfferFeeTx extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
processModel.getTradeWalletService().broadcastTx(processModel.getTakeOfferFeeTx(),
new FutureCallback<Transaction>() {
@Override
public void onSuccess(Transaction transaction) {
log.debug("Take offer fee published successfully. Transaction ID = " + transaction.getHashAsString());
/* if (trade instanceof SellerTrade)
trade.setProcessState(TakerTradeState.ProcessState.TAKE_OFFER_FEE_PUBLISHED);*/
complete();
}
@Override
public void onFailure(@NotNull Throwable t) {
t.printStackTrace();
appendToErrorMessage("Take offer fee payment failed. Maybe your network connection was lost. Please try again.");
trade.setErrorMessage(errorMessage);
/* if (trade instanceof SellerTrade)
trade.setProcessState(TakerTradeState.ProcessState.TAKE_OFFER_FEE_PUBLISH_FAILED);*/
failed(t);
}
});
} catch (Throwable t) {
t.printStackTrace();
trade.setThrowable(t);
failed(t);
}
}

View file

@ -34,20 +34,16 @@ public class CreateTakeOfferFeeTx extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
Transaction createTakeOfferFeeTx = processModel.getTradeWalletService().createTakeOfferFeeTx(processModel.getAddressEntry());
processModel.setTakeOfferFeeTx(createTakeOfferFeeTx);
processModel.setTakeOfferFeeTxId(createTakeOfferFeeTx.getHashAsString());
/*if (trade instanceof SellerTrade)
trade.setProcessState(TakerTradeState.ProcessState.TAKE_OFFER_FEE_TX_CREATED);*/
complete();
} catch (Throwable t) {
t.printStackTrace();
trade.setThrowable(t);
failed(t);
}
}

View file

@ -32,8 +32,9 @@ public class VerifyOfferFeePayment extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
//TODO impl. missing
int numOfPeersSeenTx = processModel.getWalletService().getNumOfPeersSeenTx(processModel.getTakeOfferFeeTx().getHashAsString());
/* if (numOfPeersSeenTx > 2) {

View file

@ -32,8 +32,9 @@ public class VerifyOffererAccount extends TradeTask {
}
@Override
protected void doRun() {
protected void run() {
try {
runInterceptHook();
if (processModel.getBlockChainService().verifyAccountRegistration()) {
if (processModel.getBlockChainService().isAccountBlackListed(processModel.tradingPeer.getAccountId(),
processModel.tradingPeer.getFiatAccount())) {

View file

@ -38,6 +38,9 @@ public class BuyerTradeState {
PAYOUT_TX_COMMITTED,
PAYOUT_TX_SENT,
PAYOUT_BROAD_CASTED
PAYOUT_BROAD_CASTED,
TIMEOUT,
FAULT
}
}

View file

@ -37,6 +37,9 @@ public class SellerTradeState {
PAYOUT_TX_RECEIVED,
PAYOUT_TX_COMMITTED,
PAYOUT_BROAD_CASTED
PAYOUT_BROAD_CASTED,
TIMEOUT,
FAULT
}
}

View file

@ -0,0 +1,26 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade.states;
public enum TradePhase {
PREPARATION, // No damage
TAKE_OFFER__FEE_PAID, // Offer fee can be lost
DEPOSIT_BROAD_CASTED, // Need arbitrator
PAYOUT_BROAD_CASTED // Only charge back risk open
}

View file

@ -54,9 +54,9 @@ public class Preferences implements Serializable {
// Persisted fields
private String btcDenomination = MonetaryFormat.CODE_BTC;
private Boolean useAnimations = true;
private Boolean useEffects = true;
private Boolean displaySecurityDepositInfo = true;
private boolean useAnimations = true;
private boolean useEffects = true;
private boolean displaySecurityDepositInfo = true;
// Observable wrappers
transient private final StringProperty btcDenominationProperty = new SimpleStringProperty(btcDenomination);
@ -111,7 +111,7 @@ public class Preferences implements Serializable {
this.useEffectsProperty.set(useEffectsProperty);
}
public void setDisplaySecurityDepositInfo(Boolean displaySecurityDepositInfo) {
public void setDisplaySecurityDepositInfo(boolean displaySecurityDepositInfo) {
this.displaySecurityDepositInfo = displaySecurityDepositInfo;
storage.queueUpForSave();
}
@ -133,7 +133,7 @@ public class Preferences implements Serializable {
return useAnimationsProperty.get();
}
public Boolean getDisplaySecurityDepositInfo() {
public boolean getDisplaySecurityDepositInfo() {
return displaySecurityDepositInfo;
}

View file

@ -17,6 +17,10 @@
package io.bitsquare.util;
import io.bitsquare.common.handlers.ResultHandler;
import org.bitcoinj.utils.Threading;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@ -36,6 +40,9 @@ import java.io.Serializable;
import java.net.URI;
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -47,6 +54,31 @@ public class Utilities {
private static final Logger log = LoggerFactory.getLogger(Utilities.class);
private static long lastTimeStamp = System.currentTimeMillis();
public static Timer setTimeout(long delay, ResultHandler handler) {
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
Threading.USER_THREAD.execute(() -> handler.handleResult());
}
};
timer.schedule(task, delay);
return timer;
}
public static Timer setInterval(long delay, ResultHandler handler) {
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
Threading.USER_THREAD.execute(() -> handler.handleResult());
}
};
timer.scheduleAtFixedRate(task, delay, delay);
return timer;
}
public static String objectToJson(Object object) {
Gson gson =
new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).setPrettyPrinting().create();