Handle create offer error cases

This commit is contained in:
Manfred Karrer 2015-03-13 23:22:56 +01:00
parent a198e4fcbb
commit 16100e2f8b
6 changed files with 56 additions and 50 deletions

View file

@ -33,7 +33,7 @@ public class FeePolicy {
// TODO: Change REGISTRATION_FEE to 0.00001 (See https://github.com/bitsquare/bitsquare/issues/228) // TODO: Change REGISTRATION_FEE to 0.00001 (See https://github.com/bitsquare/bitsquare/issues/228)
public static final Coin REGISTRATION_FEE = TX_FEE.add(TX_FEE); public static final Coin REGISTRATION_FEE = TX_FEE.add(TX_FEE);
public static final Coin CREATE_OFFER_FEE = Coin.valueOf(20000); // 0.0002 BTC public static final Coin CREATE_OFFER_FEE = Coin.valueOf(10000000); // 0.1 BTC
public static final Coin TAKE_OFFER_FEE = CREATE_OFFER_FEE; public static final Coin TAKE_OFFER_FEE = CREATE_OFFER_FEE;
private final BitcoinNetwork bitcoinNetwork; private final BitcoinNetwork bitcoinNetwork;

View file

@ -142,7 +142,6 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
dataModel.requestPlaceOfferErrorMessage.set(null); dataModel.requestPlaceOfferErrorMessage.set(null);
dataModel.requestPlaceOfferSuccess.set(false); dataModel.requestPlaceOfferSuccess.set(false);
isPlaceOfferButtonDisabled.set(true);
isPlaceOfferSpinnerVisible.set(true); isPlaceOfferSpinnerVisible.set(true);
dataModel.placeOffer(); dataModel.placeOffer();
@ -291,9 +290,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
updateButtonDisableState(); updateButtonDisableState();
}); });
dataModel.isWalletFunded.addListener((ov, oldValue, newValue) -> { dataModel.isWalletFunded.addListener((ov, oldValue, newValue) -> {
if (newValue) { updateButtonDisableState();
updateButtonDisableState();
}
}); });
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding // Binding with Bindings.createObjectBinding does not work because of bi-directional binding
@ -304,7 +301,6 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
dataModel.requestPlaceOfferErrorMessage.addListener((ov, oldValue, newValue) -> { dataModel.requestPlaceOfferErrorMessage.addListener((ov, oldValue, newValue) -> {
if (newValue != null) { if (newValue != null) {
isPlaceOfferButtonDisabled.set(false);
isPlaceOfferSpinnerVisible.set(false); isPlaceOfferSpinnerVisible.set(false);
} }
}); });

View file

@ -268,9 +268,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
}); });
dataModel.isWalletFunded.addListener((ov, oldValue, newValue) -> { dataModel.isWalletFunded.addListener((ov, oldValue, newValue) -> {
if (newValue) { updateButtonDisableState();
updateButtonDisableState();
}
}); });
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding // Binding with Bindings.createObjectBinding does not work because of bi-directional binding

View file

@ -49,6 +49,7 @@ import static com.google.common.base.Preconditions.checkArgument;
public class OfferBook { public class OfferBook {
private static final Logger log = LoggerFactory.getLogger(OfferBook.class); private static final Logger log = LoggerFactory.getLogger(OfferBook.class);
private static final int POLLING_INTERVAL = 1000;
private final OfferBookService offerBookService; private final OfferBookService offerBookService;
private final User user; private final User user;
@ -180,7 +181,7 @@ public class OfferBook {
private void startPolling() { private void startPolling() {
addListeners(); addListeners();
setBankAccount(user.getCurrentBankAccount().get()); setBankAccount(user.getCurrentBankAccount().get());
pollingTimer = Utilities.setInterval(3000, (animationTimer) -> { pollingTimer = Utilities.setInterval(POLLING_INTERVAL, (animationTimer) -> {
offerBookService.requestInvalidationTimeStampFromDHT(fiatCode); offerBookService.requestInvalidationTimeStampFromDHT(fiatCode);
return null; return null;
}); });

View file

@ -17,10 +17,13 @@
package io.bitsquare.trade.protocol.placeoffer.tasks; package io.bitsquare.trade.protocol.placeoffer.tasks;
import io.bitsquare.btc.AddressEntry;
import io.bitsquare.btc.FeePolicy;
import io.bitsquare.trade.protocol.placeoffer.PlaceOfferModel; import io.bitsquare.trade.protocol.placeoffer.PlaceOfferModel;
import io.bitsquare.util.taskrunner.Task; import io.bitsquare.util.taskrunner.Task;
import io.bitsquare.util.taskrunner.TaskRunner; import io.bitsquare.util.taskrunner.TaskRunner;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Transaction;
import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureCallback;
@ -43,53 +46,61 @@ public class BroadcastCreateOfferFeeTx extends Task<PlaceOfferModel> {
@Override @Override
protected void doRun() { protected void doRun() {
model.getWalletService().broadcastCreateOfferFeeTx(model.getTransaction(), new FutureCallback<Transaction>() {
Coin totalsNeeded = model.getOffer().getSecurityDeposit().add(FeePolicy.CREATE_OFFER_FEE).add(FeePolicy.TX_FEE);
AddressEntry addressEntry = model.getWalletService().getAddressInfoByTradeID(model.getOffer().getId());
Coin balance = model.getWalletService().getBalanceForAddress(addressEntry.getAddress());
if (balance.compareTo(totalsNeeded) >= 0) {
@Override model.getWalletService().broadcastCreateOfferFeeTx(model.getTransaction(), new FutureCallback<Transaction>() {
public void onSuccess(Transaction transaction) { @Override
log.info("Broadcast of offer fee payment succeeded: transaction = " + transaction.toString()); public void onSuccess(Transaction transaction) {
if (transaction != null) { log.info("Broadcast of offer fee payment succeeded: transaction = " + transaction.toString());
if (transaction != null) {
if (model.getTransaction().getHashAsString() == transaction.getHashAsString()) { if (model.getTransaction().getHashAsString() == transaction.getHashAsString()) {
// No tx malleability happened after broadcast (still not in blockchain) // No tx malleability happened after broadcast (still not in blockchain)
complete(); 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.getOfferBookService().removeOffer(model.getOffer(),
() -> {
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.getOffer().setOfferFeePaymentTxID(transaction.getHashAsString());
model.getOfferBookService().addOffer(model.getOffer(),
() -> {
complete();
},
(message, throwable) -> {
log.error("addOffer failed");
addOfferFailed = true;
failed(throwable);
});
},
(message, throwable) -> {
log.error("removeOffer failed");
removeOfferFailed = true;
failed(throwable);
});
}
} }
else { else {
log.warn("Tx malleability happened after broadcast. We publish the changed offer to the DHT again."); failed("Fault reason: Transaction = null.");
// Tx malleability happened after broadcast. We publish the changed offer to the DHT again.
model.getOfferBookService().removeOffer(model.getOffer(),
() -> {
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.getOffer().setOfferFeePaymentTxID(transaction.getHashAsString());
model.getOfferBookService().addOffer(model.getOffer(),
() -> {
complete();
},
(message, throwable) -> {
log.error("addOffer failed");
addOfferFailed = true;
failed(throwable);
});
},
(message, throwable) -> {
log.error("removeOffer failed");
removeOfferFailed = true;
failed(throwable);
});
} }
} }
else {
failed("Fault reason: Transaction = null.");
}
}
@Override @Override
public void onFailure(Throwable t) { public void onFailure(Throwable t) {
failed(t); failed(t);
} }
}); });
}
else {
failed("Not enough balance for placing the offer.");
}
} }
protected void applyErrorState() { protected void applyErrorState() {

View file

@ -65,7 +65,7 @@ public abstract class Task<T extends SharedModel> {
} }
protected void appendExceptionToErrorMessage(Throwable t) { protected void appendExceptionToErrorMessage(Throwable t) {
errorMessage += "\n Exception message: " + t.getMessage(); errorMessage += "\nException message: " + t.getMessage();
} }
protected void complete() { protected void complete() {