Merge branch 'master' into Development

# Conflicts:
#	provider/src/main/java/io/bisq/provider/price/providers/PoloniexProvider.java
This commit is contained in:
Manfred Karrer 2017-12-19 20:52:27 +01:00
commit e3488184a5
No known key found for this signature in database
GPG Key ID: 401250966A6B2C46
13 changed files with 19 additions and 245 deletions

View File

@ -19,8 +19,7 @@ package io.bisq.core.offer.placeoffer;
import io.bisq.common.handlers.ErrorMessageHandler;
import io.bisq.common.taskrunner.TaskRunner;
import io.bisq.core.offer.placeoffer.tasks.AddOfferToRemoteOfferBook;
import io.bisq.core.offer.placeoffer.tasks.BroadcastMakerFeeTx;
import io.bisq.core.offer.placeoffer.tasks.AddOfferOfferBook;
import io.bisq.core.offer.placeoffer.tasks.CreateMakerFeeTx;
import io.bisq.core.offer.placeoffer.tasks.ValidateOffer;
import io.bisq.core.trade.handlers.TransactionResultHandler;
@ -76,8 +75,7 @@ public class PlaceOfferProtocol {
taskRunner.addTasks(
ValidateOffer.class,
CreateMakerFeeTx.class,
AddOfferToRemoteOfferBook.class,
BroadcastMakerFeeTx.class
AddOfferOfferBook.class
);
taskRunner.run();

View File

@ -23,12 +23,12 @@ import io.bisq.core.offer.placeoffer.PlaceOfferModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AddOfferToRemoteOfferBook extends Task<PlaceOfferModel> {
public class AddOfferOfferBook extends Task<PlaceOfferModel> {
@SuppressWarnings("unused")
private static final Logger log = LoggerFactory.getLogger(AddOfferToRemoteOfferBook.class);
private static final Logger log = LoggerFactory.getLogger(AddOfferOfferBook.class);
@SuppressWarnings({"WeakerAccess", "unused"})
public AddOfferToRemoteOfferBook(TaskRunner taskHandler, PlaceOfferModel model) {
public AddOfferOfferBook(TaskRunner taskHandler, PlaceOfferModel model) {
super(taskHandler, model);
}

View File

@ -1,137 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq 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.
*
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bisq.core.offer.placeoffer.tasks;
import com.google.common.util.concurrent.FutureCallback;
import io.bisq.common.Timer;
import io.bisq.common.UserThread;
import io.bisq.common.taskrunner.Task;
import io.bisq.common.taskrunner.TaskRunner;
import io.bisq.core.offer.Offer;
import io.bisq.core.offer.placeoffer.PlaceOfferModel;
import org.bitcoinj.core.Transaction;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BroadcastMakerFeeTx extends Task<PlaceOfferModel> {
private static final Logger log = LoggerFactory.getLogger(BroadcastMakerFeeTx.class);
private boolean removeOfferFailed;
private boolean addOfferFailed;
@SuppressWarnings({"WeakerAccess", "unused"})
public BroadcastMakerFeeTx(TaskRunner taskHandler, PlaceOfferModel model) {
super(taskHandler, model);
}
@Override
protected void run() {
try {
runInterceptHook();
final Transaction transaction = model.getTransaction();
// TODO Try to republish tx?
Timer timeoutTimer = UserThread.runAfter(() -> {
log.warn("Broadcast not completed after 5 sec. We go on with the trade protocol.");
model.getOffer().setState(Offer.State.OFFER_FEE_PAID);
complete();
}, 20);
model.getTradeWalletService().broadcastTx(model.getTransaction(),
new FutureCallback<Transaction>() {
@Override
public void onSuccess(Transaction tx) {
timeoutTimer.stop();
if (!completed) {
log.debug("Broadcast of offer fee payment succeeded: transaction = " + tx.toString());
if (transaction.getHashAsString().equals(tx.getHashAsString())) {
model.getOffer().setState(Offer.State.OFFER_FEE_PAID);
// 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 P2P network again.");
// Tx malleability happened after broadcast. We first remove the malleable offer.
// Then we publish the changed offer to the P2P network again after setting the new TxId.
// Normally we use a delay for broadcasting to the peers, but at shut down we want to get it fast out
model.getOfferBookService().removeOffer(model.getOffer().getOfferPayload(),
() -> {
log.debug("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(tx.getHashAsString());
model.setTransaction(tx);
model.getOfferBookService().addOffer(model.getOffer(),
BroadcastMakerFeeTx.this::complete,
errorMessage -> {
log.error("addOffer failed");
addOfferFailed = true;
updateStateOnFault();
model.getOffer().setErrorMessage("An error occurred when adding the offer to the P2P network.\n" +
"Error message:\n"
+ errorMessage);
failed(errorMessage);
});
},
errorMessage -> {
log.error("removeOffer failed");
removeOfferFailed = true;
updateStateOnFault();
model.getOffer().setErrorMessage("An error occurred when removing the offer from the P2P network.\n" +
"Error message:\n"
+ errorMessage);
failed(errorMessage);
});
}
} else {
log.warn("We got the onSuccess callback called after the timeout has been triggered a complete().");
}
}
@Override
public void onFailure(@NotNull Throwable t) {
if (!completed) {
timeoutTimer.stop();
updateStateOnFault();
model.getOffer().setErrorMessage("An error occurred.\n" +
"Error message:\n"
+ t.getMessage());
failed(t);
} else {
log.warn("We got the onFailure callback called after the timeout has been triggered a complete().");
}
}
});
} catch (Throwable t) {
model.getOffer().setErrorMessage("An error occurred.\n" +
"Error message:\n"
+ t.getMessage());
failed(t);
}
}
private void updateStateOnFault() {
if (!removeOfferFailed && !addOfferFailed) {
// If broadcast fails we need to remove offer from offerbook
model.getOfferBookService().removeOffer(model.getOffer().getOfferPayload(),
() -> log.debug("OfferPayload removed from offerbook because broadcast failed."),
errorMessage -> log.error("removeOffer failed. " + errorMessage));
}
}
}

View File

@ -39,7 +39,6 @@ import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
public class CreateMakerFeeTx extends Task<PlaceOfferModel> {
@ -92,12 +91,12 @@ public class CreateMakerFeeTx extends Task<PlaceOfferModel> {
// returned (tradeFeeTx would be null in that case)
UserThread.execute(() -> {
if (!completed) {
if (tradeFeeTx != null && !tradeFeeTx.getHashAsString().equals(transaction.getHashAsString()))
log.warn("The trade fee tx received from the network had another tx ID than the one we publish");
offer.setOfferFeePaymentTxId(transaction.getHashAsString());
model.setTransaction(transaction);
walletService.swapTradeEntryToAvailableEntry(id, AddressEntry.Context.OFFER_FUNDING);
model.getOffer().setState(Offer.State.OFFER_FEE_PAID);
complete();
} else {
log.warn("We got the onSuccess callback called after the timeout has been triggered a complete().");
@ -138,14 +137,15 @@ public class CreateMakerFeeTx extends Task<PlaceOfferModel> {
@Override
public void onSuccess(@Nullable Transaction transaction) {
if (transaction != null) {
checkArgument(transaction.equals(signedTx));
offer.setOfferFeePaymentTxId(transaction.getHashAsString());
model.setTransaction(transaction);
log.debug("onSuccess, offerId={}, OFFER_FUNDING", id);
walletService.swapTradeEntryToAvailableEntry(id, AddressEntry.Context.OFFER_FUNDING);
complete();
log.debug("Successfully sent tx with id " + transaction.getHashAsString());
model.getOffer().setState(Offer.State.OFFER_FEE_PAID);
complete();
}
}

View File

@ -100,7 +100,6 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
TakerVerifyMakerAccount.class,
TakerVerifyMakerFeePayment.class,
CreateTakerFeeTx.class,
TakerPublishTakerFeeTx.class,
BuyerAsTakerCreatesDepositTxInputs.class,
TakerSendPayDepositRequest.class
);

View File

@ -91,7 +91,6 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
TakerSelectArbitrator.class,
TakerSelectMediator.class,
CreateTakerFeeTx.class,
TakerPublishTakerFeeTx.class,
SellerAsTakerCreatesDepositTxInputs.class,
TakerSendPayDepositRequest.class
);

View File

@ -38,7 +38,6 @@ import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
@ -91,12 +90,10 @@ public class CreateTakerFeeTx extends TradeTask {
// returned (tradeFeeTx would be null in that case)
UserThread.execute(() -> {
if (!completed) {
if (tradeFeeTx != null && !tradeFeeTx.getHashAsString().equals(transaction.getHashAsString()))
log.warn("The trade fee tx received from the network had another tx ID than the one we publish");
processModel.setTakeOfferFeeTx(tradeFeeTx);
trade.setTakerFeeTxId(tradeFeeTx.getHashAsString());
walletService.swapTradeEntryToAvailableEntry(id, AddressEntry.Context.OFFER_FUNDING);
trade.setState(Trade.State.TAKER_PUBLISHED_TAKER_FEE_TX);
complete();
} else {
@ -140,10 +137,10 @@ public class CreateTakerFeeTx extends TradeTask {
if (!completed) {
if (transaction != null) {
log.debug("Successfully sent tx with id " + transaction.getHashAsString());
checkArgument(transaction.equals(signedTx));
trade.setTakerFeeTxId(transaction.getHashAsString());
processModel.setTakeOfferFeeTx(transaction);
walletService.swapTradeEntryToAvailableEntry(id, AddressEntry.Context.OFFER_FUNDING);
trade.setState(Trade.State.TAKER_PUBLISHED_TAKER_FEE_TX);
complete();
}

View File

@ -1,77 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq 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.
*
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bisq.core.trade.protocol.tasks.taker;
import com.google.common.util.concurrent.FutureCallback;
import io.bisq.common.Timer;
import io.bisq.common.UserThread;
import io.bisq.common.taskrunner.TaskRunner;
import io.bisq.core.trade.Trade;
import io.bisq.core.trade.protocol.tasks.TradeTask;
import lombok.extern.slf4j.Slf4j;
import org.bitcoinj.core.Transaction;
import org.jetbrains.annotations.NotNull;
@Slf4j
public class TakerPublishTakerFeeTx extends TradeTask {
@SuppressWarnings({"WeakerAccess", "unused"})
public TakerPublishTakerFeeTx(TaskRunner taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
Timer timeoutTimer = UserThread.runAfter(() -> {
log.warn("Broadcast not completed after 5 sec. We go on with the trade protocol.");
trade.setState(Trade.State.TAKER_PUBLISHED_TAKER_FEE_TX);
complete();
}, 5);
processModel.getTradeWalletService().broadcastTx(processModel.resolveTakeOfferFeeTx(trade),
new FutureCallback<Transaction>() {
@Override
public void onSuccess(Transaction transaction) {
if (!completed) {
timeoutTimer.stop();
log.debug("Trading fee published successfully. Transaction ID = " + transaction.getHashAsString());
trade.setState(Trade.State.TAKER_PUBLISHED_TAKER_FEE_TX);
complete();
} else {
log.warn("We got the onSuccess callback called after the timeout has been triggered a complete().");
}
}
@Override
public void onFailure(@NotNull Throwable t) {
if (!completed) {
timeoutTimer.stop();
appendToErrorMessage("Trading fee payment failed. Maybe your network connection was lost. Please try again.");
failed(t);
} else {
log.warn("We got the onFailure callback called after the timeout has been triggered a complete().");
}
}
});
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -223,7 +223,7 @@ bg color of non edit textFields: fafafa
}
.dao-tx-type-unverified-icon,
.dao-tx-type-unverified-icon,
.dao-tx-type-unverified-icon:hover {
-fx-text-fill: -bs-yellow;
-fx-cursor: hand;
@ -1155,4 +1155,4 @@ textfield */
-fx-border-insets: 0 0 0 -2;
-fx-background-insets: 0 0 0 -2;
-fx-background-radius: 0 4 4 0;
}
}

View File

@ -32,7 +32,6 @@ import com.sun.javafx.scene.control.skin.BehaviorSkinBase;
import io.bisq.gui.components.indicator.TxConfidenceIndicator;
import io.bisq.gui.components.indicator.behavior.StaticProgressIndicatorBehavior;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;

View File

@ -20,8 +20,7 @@ package io.bisq.gui.main.debug;
import io.bisq.common.taskrunner.Task;
import io.bisq.core.offer.availability.tasks.ProcessOfferAvailabilityResponse;
import io.bisq.core.offer.availability.tasks.SendOfferAvailabilityRequest;
import io.bisq.core.offer.placeoffer.tasks.AddOfferToRemoteOfferBook;
import io.bisq.core.offer.placeoffer.tasks.BroadcastMakerFeeTx;
import io.bisq.core.offer.placeoffer.tasks.AddOfferOfferBook;
import io.bisq.core.offer.placeoffer.tasks.CreateMakerFeeTx;
import io.bisq.core.offer.placeoffer.tasks.ValidateOffer;
import io.bisq.core.trade.protocol.tasks.CheckIfPeerIsBanned;
@ -79,8 +78,7 @@ public class DebugView extends InitializableView<GridPane, Void> {
FXCollections.observableArrayList(Arrays.asList(
ValidateOffer.class,
CreateMakerFeeTx.class,
AddOfferToRemoteOfferBook.class,
BroadcastMakerFeeTx.class)
AddOfferOfferBook.class)
));
addGroup("BuyerAsMakerProtocol: ",
@ -115,7 +113,6 @@ public class DebugView extends InitializableView<GridPane, Void> {
TakerSelectArbitrator.class,
TakerSelectMediator.class,
CreateTakerFeeTx.class,
TakerPublishTakerFeeTx.class,
SellerAsTakerCreatesDepositTxInputs.class,
TakerSendPayDepositRequest.class,
@ -145,7 +142,6 @@ public class DebugView extends InitializableView<GridPane, Void> {
TakerVerifyMakerAccount.class,
TakerVerifyMakerFeePayment.class,
CreateTakerFeeTx.class,
TakerPublishTakerFeeTx.class,
BuyerAsTakerCreatesDepositTxInputs.class,
TakerSendPayDepositRequest.class,

View File

@ -19,7 +19,6 @@ package io.bisq.provider.price;
import lombok.Value;
@SuppressWarnings("FieldCanBeLocal")
@Value
public class PriceData {
private final String currencyCode;

View File

@ -54,7 +54,8 @@ public class PoloniexProvider {
marketPriceMap.put(altcoinCurrency,
new PriceData(altcoinCurrency,
parseDouble((String) data.get("last")),
ts, PriceRequestService.POLO_PROVIDER)
ts,
PriceRequestService.POLO_PROVIDER)
);
}
}