mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-20 10:22:18 +01:00
Add timeout to broadcast callbacks in tasks to avoid timeout errors.
Add minValue to BtcValidator. Fix LTC fees. Log all onStoredInMailbox and onArrived handler calls. Fix translations.
This commit is contained in:
parent
67e8a1c74d
commit
4bd299427c
@ -27,7 +27,7 @@ import java.util.stream.Collectors;
|
||||
public class CurrencyUtil {
|
||||
private static String baseCurrencyCode = "BTC";
|
||||
|
||||
public static void setBaseCurrencyNetwork(String baseCurrencyCode) {
|
||||
public static void setBaseCurrencyCode(String baseCurrencyCode) {
|
||||
CurrencyUtil.baseCurrencyCode = baseCurrencyCode;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ public abstract class Task<T extends Model> {
|
||||
private final TaskRunner taskHandler;
|
||||
protected final T model;
|
||||
protected String errorMessage = "An error occurred at task: " + getClass().getSimpleName();
|
||||
protected boolean completed;
|
||||
|
||||
public Task(TaskRunner taskHandler, T model) {
|
||||
this.taskHandler = taskHandler;
|
||||
@ -53,6 +54,7 @@ public abstract class Task<T extends Model> {
|
||||
}
|
||||
|
||||
protected void complete() {
|
||||
completed = true;
|
||||
taskHandler.handleComplete();
|
||||
}
|
||||
|
||||
|
@ -358,7 +358,11 @@ createOffer.fixed=Fixed
|
||||
createOffer.percentage=Percentage
|
||||
createOffer.timeoutAtPublishing=A timeout occurred at publishing the offer.
|
||||
createOffer.errorInfo=\n\nThe maker fee is already paid. In the worst case you have lost that fee. We are sorry about that but keep in mind it is a very small amount.\nPlease try to restart you application and check your network connection to see if you can resolve the issue.
|
||||
createOffer.tooLowSecDeposit.warning=You have set the security deposit to a lower value than the recommended default value of {0}.\nAre you sure you want to use a lower security deposit?\nIt gives you less protection in case the trading peer does not follow the trade protocol.
|
||||
createOffer.tooLowSecDeposit.warning=You have set the security deposit to a lower value than the recommended default value of {0}.\n\
|
||||
Are you sure you want to use a lower security deposit?
|
||||
createOffer.tooLowSecDeposit.makerIsSeller=It gives you less protection in case the trading peer does not follow the trade protocol.
|
||||
createOffer.tooLowSecDeposit.makerIsBuyer=It gives less protection for the trading peer that you follow the trade protocol as you have less deposit at risk. \
|
||||
Other users might prefer to take other offers instead of yours.
|
||||
createOffer.resetToDefault=No, reset to the default value
|
||||
createOffer.useLowerValue=Yes, use my lower value
|
||||
createOffer.priceOutSideOfDeviation=The price you have entered is outside the max. allowed deviation from the market price.\nThe max. allowed deviation is {0} and can be adjusted in the preferences.
|
||||
@ -1553,8 +1557,9 @@ validation.zero=Input of 0 is not allowed.
|
||||
validation.negative=A negative value is not allowed.
|
||||
validation.fiat.toSmall=Input smaller than minimum possible amount is not allowed.
|
||||
validation.fiat.toLarge=Input larger than maximum possible amount is not allowed.
|
||||
validation.btc.toSmall=Input results in a bitcoin value with a fraction of the smallest unit (Satoshi).
|
||||
validation.btc.fraction=Input results in a bitcoin value with a fraction of the smallest unit (Satoshi).
|
||||
validation.btc.toLarge=Input larger than {0} is not allowed.
|
||||
validation.btc.toSmall=Input smaller than {0} is not allowed.
|
||||
validation.securityDeposit.toSmall=Input smaller than {0} is not allowed.
|
||||
validation.passwordTooShort=The password you entered is too short. It needs to have min. 8 characters.
|
||||
validation.passwordTooLong=The password you entered is too long. It cannot be longer than 50 characters.
|
||||
|
@ -1358,7 +1358,7 @@ validation.zero=Eingabe von 0 ist nicht erlaubt.
|
||||
validation.negative=Ein negativer Wert ist nicht erlaubt.
|
||||
validation.fiat.toSmall=Eingabe kleiner als der minimal mögliche Betrag ist nicht erlaubt.
|
||||
validation.fiat.toLarge=Eingabe größer als der maximal mögliche Betrag ist nicht erlaubt.
|
||||
validation.btc.toSmall=Eingabe führt zu einem Bitcoinwert mit einem Bruchteil der kleinsten Einheit (Satoshi).
|
||||
validation.btc.fraction=Eingabe führt zu einem Bitcoinwert mit einem Bruchteil der kleinsten Einheit (Satoshi).
|
||||
validation.btc.toLarge=Eingabe größer als {0} ist nicht erlaubt.
|
||||
validation.securityDeposit.toSmall=Eingabe kleiner als {0} ist nicht erlaubt.
|
||||
validation.passwordTooShort=Das eingegebene Passwort ist zu kurz. Es muss wenigstens 8 Zeichen haben.
|
||||
|
@ -1358,7 +1358,7 @@ validation.zero=El 0 no es un valor permitido.
|
||||
validation.negative=No se permiten entradas negativas.
|
||||
validation.fiat.toSmall=No se permite introducir un valor menor que el mínimo posible
|
||||
validation.fiat.toLarge=No se permiten entradas más gandes que la mayor posible.
|
||||
validation.btc.toSmall=La entrada resulta en un valor de bitcoin con la menor fracción posible (satoshi).
|
||||
validation.btc.fraction=La entrada resulta en un valor de bitcoin con la menor fracción posible (satoshi).
|
||||
validation.btc.toLarge=No se permiten valores mayores que {0}.
|
||||
validation.securityDeposit.toSmall=No se permiten valores menores que {0}.
|
||||
validation.passwordTooShort=La clave introducida es demasiado corta. Se precisan al menos 8 caracteres.
|
||||
|
@ -1375,7 +1375,7 @@ validation.zero=Unos 0 nije dozvoljen.
|
||||
validation.negative=Negativna vrednost nije dozvoljena.
|
||||
validation.fiat.toSmall=Unos manji od minimalnog mogućeg iznosa nije dozvoljen.
|
||||
validation.fiat.toLarge=Unos veći od maksimalnog mogućeg iznosa nije dozvoljen.
|
||||
validation.btc.toSmall=Unos ishodi bitkoin vrednosti manjoj od najmanje jedinice (Satoši).
|
||||
validation.btc.fraction=Unos ishodi bitkoin vrednosti manjoj od najmanje jedinice (Satoši).
|
||||
validation.btc.toLarge=Unos veći od {0} nije dozvoljen.
|
||||
validation.securityDeposit.toSmall=Unos manji od {0} nije dozvoljen.
|
||||
validation.passwordTooShort=Lozinka koju ste uneli je previše kratka. Mora da sadrži minimum 8 karaktera.
|
||||
|
@ -241,19 +241,21 @@ public class DisputeManager implements PersistedDataHost {
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("Message arrived at peer. tradeId={}", disputeCommunicationMessage.getTradeId());
|
||||
disputeCommunicationMessage.setArrived(true);
|
||||
resultHandler.handleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.info("Message stored in mailbox. tradeId={}", disputeCommunicationMessage.getTradeId());
|
||||
disputeCommunicationMessage.setStoredInMailbox(true);
|
||||
resultHandler.handleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMessage failed");
|
||||
log.error("sendEncryptedMailboxMessage failed. disputeCommunicationMessage=" + disputeCommunicationMessage);
|
||||
faultHandler.handleFault("Sending dispute message failed: " + errorMessage, new MessageDeliveryFailedException());
|
||||
}
|
||||
}
|
||||
@ -329,17 +331,19 @@ public class DisputeManager implements PersistedDataHost {
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("Message arrived at peer. tradeId={}", disputeCommunicationMessage.getTradeId());
|
||||
disputeCommunicationMessage.setArrived(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.info("Message stored in mailbox. tradeId={}", disputeCommunicationMessage.getTradeId());
|
||||
disputeCommunicationMessage.setStoredInMailbox(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMessage failed");
|
||||
log.error("sendEncryptedMailboxMessage failed. disputeCommunicationMessage=" + disputeCommunicationMessage);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -391,17 +395,19 @@ public class DisputeManager implements PersistedDataHost {
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("Message arrived at peer. tradeId={}", disputeCommunicationMessage.getTradeId());
|
||||
disputeCommunicationMessage.setArrived(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.info("Message stored in mailbox. tradeId={}", disputeCommunicationMessage.getTradeId());
|
||||
disputeCommunicationMessage.setStoredInMailbox(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMessage failed");
|
||||
log.error("sendEncryptedMailboxMessage failed. disputeCommunicationMessage=" + disputeCommunicationMessage);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -441,17 +447,19 @@ public class DisputeManager implements PersistedDataHost {
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("Message arrived at peer. tradeId={}", disputeCommunicationMessage.getTradeId());
|
||||
disputeCommunicationMessage.setArrived(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.info("Message stored in mailbox. tradeId={}", disputeCommunicationMessage.getTradeId());
|
||||
disputeCommunicationMessage.setStoredInMailbox(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMessage failed");
|
||||
log.error("sendEncryptedMailboxMessage failed. disputeCommunicationMessage=" + disputeCommunicationMessage);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -462,26 +470,27 @@ public class DisputeManager implements PersistedDataHost {
|
||||
PubKeyRing peersPubKeyRing = dispute.isDisputeOpenerIsBuyer() ? contract.getSellerPubKeyRing() : contract.getBuyerPubKeyRing();
|
||||
NodeAddress peerNodeAddress = dispute.isDisputeOpenerIsBuyer() ? contract.getSellerNodeAddress() : contract.getBuyerNodeAddress();
|
||||
log.trace("sendPeerPublishedPayoutTxMessage to peerAddress " + peerNodeAddress);
|
||||
final PeerPublishedDisputePayoutTxMessage message = new PeerPublishedDisputePayoutTxMessage(transaction.bitcoinSerialize(),
|
||||
dispute.getTradeId(),
|
||||
p2PService.getAddress(),
|
||||
UUID.randomUUID().toString());
|
||||
p2PService.sendEncryptedMailboxMessage(peerNodeAddress,
|
||||
peersPubKeyRing,
|
||||
new PeerPublishedDisputePayoutTxMessage(transaction.bitcoinSerialize(),
|
||||
dispute.getTradeId(),
|
||||
p2PService.getAddress(),
|
||||
UUID.randomUUID().toString()),
|
||||
message,
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
|
||||
log.info("Message arrived at peer. tradeId={}", message.getTradeId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
|
||||
log.info("Message stored in mailbox. tradeId={}", message.getTradeId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMessage failed");
|
||||
log.error("sendEncryptedMailboxMessage failed. message=" + message);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -21,14 +21,10 @@ import io.bisq.core.app.BisqEnvironment;
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
public class Restrictions {
|
||||
|
||||
private static Coin MIN_TRADE_AMOUNT;
|
||||
|
||||
private static Coin MAX_BUYER_SECURITY_DEPOSIT;
|
||||
private static Coin MIN_BUYER_SECURITY_DEPOSIT;
|
||||
private static Coin DEFAULT_BUYER_SECURITY_DEPOSIT;
|
||||
|
||||
//TODO maybe move to separate class for constant values which might be changed in future by DAO voting?
|
||||
// For the seller we use a fixed one as there is no way the seller can cancel the trade
|
||||
// To make it editable would just increase complexity.
|
||||
private static Coin SELLER_SECURITY_DEPOSIT;
|
||||
@ -53,13 +49,13 @@ public class Restrictions {
|
||||
if (MIN_TRADE_AMOUNT == null)
|
||||
switch (BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode()) {
|
||||
case "BTC":
|
||||
MIN_TRADE_AMOUNT = Coin.valueOf(10_000); // 0.25 EUR cent @ 2500 EUR/BTC
|
||||
MIN_TRADE_AMOUNT = Coin.valueOf(10_000); // 0.25 EUR @ 2500 EUR/BTC
|
||||
break;
|
||||
case "LTC":
|
||||
MIN_TRADE_AMOUNT = Coin.valueOf(625_000); // 0.25 EUR cent @ 40 EUR/LTC
|
||||
MIN_TRADE_AMOUNT = Coin.valueOf(100_000); // 0.04 EUR @ 40 EUR/LTC
|
||||
break;
|
||||
case "DOGE":
|
||||
MIN_TRADE_AMOUNT = Coin.valueOf(8_000_000_000L);// 0.24 USD at DOGE price 0.003 USD;
|
||||
MIN_TRADE_AMOUNT = Coin.valueOf(1_000_000_000L); // 0.03 EUR at DOGE price 0.003 EUR;
|
||||
break;
|
||||
}
|
||||
return MIN_TRADE_AMOUNT;
|
||||
@ -67,25 +63,66 @@ public class Restrictions {
|
||||
|
||||
public static Coin getMaxBuyerSecurityDeposit() {
|
||||
if (MAX_BUYER_SECURITY_DEPOSIT == null)
|
||||
MAX_BUYER_SECURITY_DEPOSIT = getMinTradeAmount().multiply(2000); // about 500 EUR
|
||||
switch (BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode()) {
|
||||
case "BTC":
|
||||
MAX_BUYER_SECURITY_DEPOSIT = Coin.valueOf(20_000_000); // 500 EUR @ 2500 EUR/BTC
|
||||
break;
|
||||
case "LTC":
|
||||
MAX_BUYER_SECURITY_DEPOSIT = Coin.valueOf(1_200_000_000); // 500 EUR @ 40 EUR/LTC
|
||||
break;
|
||||
case "DOGE":
|
||||
MAX_BUYER_SECURITY_DEPOSIT = Coin.valueOf(20_000_000_000_000L); // 500 EUR @ 0.0025 EUR/DOGE;
|
||||
break;
|
||||
}
|
||||
|
||||
return MAX_BUYER_SECURITY_DEPOSIT;
|
||||
}
|
||||
|
||||
public static Coin getMinBuyerSecurityDeposit() {
|
||||
if (MIN_BUYER_SECURITY_DEPOSIT == null)
|
||||
MIN_BUYER_SECURITY_DEPOSIT = getMinTradeAmount().multiply(10); // about 2.5 eur
|
||||
switch (BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode()) {
|
||||
case "BTC":
|
||||
MIN_BUYER_SECURITY_DEPOSIT = Coin.valueOf(100_000); // 2.5 EUR @ 2500 EUR/BTC
|
||||
break;
|
||||
case "LTC":
|
||||
MIN_BUYER_SECURITY_DEPOSIT = Coin.valueOf(6_000_000); // 2.5 EUR @ 40 EUR/LTC
|
||||
break;
|
||||
case "DOGE":
|
||||
MIN_BUYER_SECURITY_DEPOSIT = Coin.valueOf(100_000_000_000L); // 2.5 EUR @ 0.0025 EUR/DOGE;
|
||||
break;
|
||||
}
|
||||
return MIN_BUYER_SECURITY_DEPOSIT;
|
||||
}
|
||||
|
||||
public static Coin getDefaultBuyerSecurityDeposit() {
|
||||
if (DEFAULT_BUYER_SECURITY_DEPOSIT == null)
|
||||
DEFAULT_BUYER_SECURITY_DEPOSIT = getMinTradeAmount().multiply(300); // about 75 eur
|
||||
switch (BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode()) {
|
||||
case "BTC":
|
||||
DEFAULT_BUYER_SECURITY_DEPOSIT = Coin.valueOf(3_000_000); // 75 EUR @ 2500 EUR/BTC
|
||||
break;
|
||||
case "LTC":
|
||||
DEFAULT_BUYER_SECURITY_DEPOSIT = Coin.valueOf(200_000_000); // 75 EUR @ 40 EUR/LTC
|
||||
break;
|
||||
case "DOGE":
|
||||
DEFAULT_BUYER_SECURITY_DEPOSIT = Coin.valueOf(3_000_000_000_000L); // 75 EUR @ 0.0025 EUR/DOGE;
|
||||
break;
|
||||
}
|
||||
return DEFAULT_BUYER_SECURITY_DEPOSIT;
|
||||
}
|
||||
|
||||
public static Coin getSellerSecurityDeposit() {
|
||||
if (SELLER_SECURITY_DEPOSIT == null)
|
||||
SELLER_SECURITY_DEPOSIT = getMinTradeAmount().multiply(100); // about 25 eur
|
||||
switch (BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode()) {
|
||||
case "BTC":
|
||||
SELLER_SECURITY_DEPOSIT = Coin.valueOf(1_000_000); // 25 EUR @ 2500 EUR/BTC
|
||||
break;
|
||||
case "LTC":
|
||||
SELLER_SECURITY_DEPOSIT = Coin.valueOf(60_000_000); // 25 EUR @ 40 EUR/LTC
|
||||
break;
|
||||
case "DOGE":
|
||||
SELLER_SECURITY_DEPOSIT = Coin.valueOf(1_000_000_000_000L); // 25 EUR @ 0.0025 EUR/DOGE;
|
||||
break;
|
||||
}
|
||||
return SELLER_SECURITY_DEPOSIT;
|
||||
}
|
||||
}
|
||||
|
@ -418,8 +418,9 @@ public class WalletConfig extends AbstractIdleService {
|
||||
vChain = new BlockChain(params, vStore);
|
||||
vPeerGroup = createPeerGroup();
|
||||
|
||||
if (this.userAgent != null)
|
||||
vPeerGroup.setUserAgent(userAgent, version);
|
||||
// protect privacy and don't send agent info
|
||||
/*if (this.userAgent != null)
|
||||
vPeerGroup.setUserAgent(userAgent, version);*/
|
||||
|
||||
// Set up peer addresses or discovery first, so if wallet extensions try to broadcast a transaction
|
||||
// before we're actually connected the broadcast waits for an appropriate number of connections.
|
||||
|
@ -18,6 +18,8 @@
|
||||
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;
|
||||
@ -42,59 +44,77 @@ public class BroadcastMakerFeeTx extends Task<PlaceOfferModel> {
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
model.getTradeWalletService().broadcastTx(model.getTransaction(), new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
log.debug("Broadcast of offer fee payment succeeded: transaction = " + transaction.toString());
|
||||
final Transaction transaction = model.getTransaction();
|
||||
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();
|
||||
}, 5);
|
||||
|
||||
if (model.getTransaction().getHashAsString().equals(transaction.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(transaction.getHashAsString());
|
||||
model.setTransaction(transaction);
|
||||
model.getOfferBookService().addOffer(model.getOffer(),
|
||||
BroadcastMakerFeeTx.this::complete,
|
||||
model.getTradeWalletService().broadcastTx(model.getTransaction(),
|
||||
new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction tx) {
|
||||
if (!completed) {
|
||||
timeoutTimer.stop();
|
||||
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("addOffer failed");
|
||||
addOfferFailed = true;
|
||||
log.error("removeOffer failed");
|
||||
removeOfferFailed = true;
|
||||
updateStateOnFault();
|
||||
model.getOffer().setErrorMessage("An error occurred when adding the offer to the P2P network.\n" +
|
||||
model.getOffer().setErrorMessage("An error occurred when removing the offer from 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 callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
updateStateOnFault();
|
||||
model.getOffer().setErrorMessage("An error occurred.\n" +
|
||||
"Error message:\n"
|
||||
+ t.getMessage());
|
||||
failed(t);
|
||||
}
|
||||
});
|
||||
@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 callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
model.getOffer().setErrorMessage("An error occurred.\n" +
|
||||
"Error message:\n"
|
||||
|
@ -89,10 +89,11 @@ public class FeeService {
|
||||
txFeePerByte = BTC_DEFAULT_TX_FEE;
|
||||
break;
|
||||
case "LTC":
|
||||
MIN_MAKER_FEE_IN_BASE_CUR = 12_500; // 0.25 USD at LTC price 40 USD for 50 LTC
|
||||
MIN_TAKER_FEE_IN_BASE_CUR = 12_500;
|
||||
DEFAULT_MAKER_FEE_IN_BASE_CUR = 125_000; // 2.5 USD at LTC price 40 USD
|
||||
DEFAULT_TAKER_FEE_IN_BASE_CUR = 187_500; // 3.6 USD at LTC price 40 USD
|
||||
// > 0.00 100 000
|
||||
MIN_MAKER_FEE_IN_BASE_CUR = 600_000; // 0.25 USD at LTC price 40 USD for 50 LTC
|
||||
MIN_TAKER_FEE_IN_BASE_CUR = 600_000;
|
||||
DEFAULT_MAKER_FEE_IN_BASE_CUR = 120_000; // 2.5 USD at LTC price 40 USD
|
||||
DEFAULT_TAKER_FEE_IN_BASE_CUR = 180_000; // 3.6 USD at LTC price 40 USD
|
||||
txFeePerByte = LTC_DEFAULT_TX_FEE;
|
||||
break;
|
||||
case "DOGE":
|
||||
|
@ -60,20 +60,21 @@ public class BuyerSendCounterCurrencyTransferStartedMessage extends TradeTask {
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.debug("Message arrived at peer. tradeId={}, message{}", id, message);
|
||||
log.info("Message arrived at peer. tradeId={}", id);
|
||||
trade.setState(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.debug("Message stored in mailbox. tradeId={}, message{}", id, message);
|
||||
log.info("Message stored in mailbox. tradeId={}", id);
|
||||
trade.setState(Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMailboxMessage failed. message=" + message);
|
||||
trade.setState(Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG);
|
||||
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
||||
failed(errorMessage);
|
||||
|
@ -18,6 +18,8 @@
|
||||
package io.bisq.core.trade.protocol.tasks.buyer_as_taker;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.bisq.common.Timer;
|
||||
import io.bisq.common.UserThread;
|
||||
import io.bisq.common.crypto.Hash;
|
||||
import io.bisq.common.taskrunner.TaskRunner;
|
||||
import io.bisq.core.btc.AddressEntry;
|
||||
@ -40,6 +42,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@Slf4j
|
||||
public class BuyerAsTakerSignAndPublishDepositTx extends TradeTask {
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||
public BuyerAsTakerSignAndPublishDepositTx(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
@ -75,6 +78,13 @@ public class BuyerAsTakerSignAndPublishDepositTx extends TradeTask {
|
||||
checkArgument(Arrays.equals(buyerMultiSigPubKey, buyerMultiSigAddressEntry.getPubKey()),
|
||||
"buyerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
|
||||
|
||||
|
||||
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_DEPOSIT_TX);
|
||||
complete();
|
||||
}, 5);
|
||||
|
||||
Transaction depositTx = processModel.getTradeWalletService().takerSignsAndPublishesDepositTx(
|
||||
false,
|
||||
contractHash,
|
||||
@ -87,17 +97,25 @@ public class BuyerAsTakerSignAndPublishDepositTx extends TradeTask {
|
||||
new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
log.trace("takerSignAndPublishTx succeeded " + transaction);
|
||||
|
||||
trade.setDepositTx(transaction);
|
||||
trade.setState(Trade.State.TAKER_PUBLISHED_DEPOSIT_TX);
|
||||
|
||||
complete();
|
||||
if (!completed) {
|
||||
timeoutTimer.stop();
|
||||
log.trace("takerSignAndPublishTx succeeded " + transaction);
|
||||
trade.setDepositTx(transaction);
|
||||
trade.setState(Trade.State.TAKER_PUBLISHED_DEPOSIT_TX);
|
||||
complete();
|
||||
} else {
|
||||
log.warn("We got the callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
failed(t);
|
||||
if (!completed) {
|
||||
timeoutTimer.stop();
|
||||
failed(t);
|
||||
} else {
|
||||
log.warn("We got the callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
});
|
||||
trade.setDepositTx(depositTx);
|
||||
|
@ -76,20 +76,21 @@ public class MakerSendPublishDepositTxRequest extends TradeTask {
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.debug("Message arrived at peer. tradeId={}, message{}", id, message);
|
||||
log.info("Message arrived at peer. tradeId={}", id);
|
||||
trade.setState(Trade.State.MAKER_SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.debug("Message stored in mailbox. tradeId={}, message{}", id, message);
|
||||
log.info("Message stored in mailbox. tradeId={}", id);
|
||||
trade.setState(Trade.State.MAKER_STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMailboxMessage failed. message=" + message);
|
||||
trade.setState(Trade.State.MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
||||
failed(errorMessage);
|
||||
|
@ -18,6 +18,8 @@
|
||||
package io.bisq.core.trade.protocol.tasks.seller;
|
||||
|
||||
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;
|
||||
@ -50,20 +52,36 @@ public class SellerBroadcastPayoutTx extends TradeTask {
|
||||
trade.setState(Trade.State.SELLER_PUBLISHED_PAYOUT_TX);
|
||||
complete();
|
||||
} else {
|
||||
processModel.getTradeWalletService().broadcastTx(payoutTx, new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
log.debug("BroadcastTx succeeded. Transaction:" + transaction);
|
||||
trade.setState(Trade.State.SELLER_PUBLISHED_PAYOUT_TX);
|
||||
complete();
|
||||
}
|
||||
Timer timeoutTimer = UserThread.runAfter(() -> {
|
||||
log.warn("Broadcast not completed after 5 sec. We go on with the trade protocol.");
|
||||
trade.setState(Trade.State.SELLER_PUBLISHED_PAYOUT_TX);
|
||||
complete();
|
||||
}, 5);
|
||||
processModel.getTradeWalletService().broadcastTx(payoutTx,
|
||||
new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
if (!completed) {
|
||||
timeoutTimer.stop();
|
||||
log.debug("BroadcastTx succeeded. Transaction:" + transaction);
|
||||
trade.setState(Trade.State.SELLER_PUBLISHED_PAYOUT_TX);
|
||||
complete();
|
||||
} else {
|
||||
log.warn("We got the callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
log.error("BroadcastTx failed. Error:" + t.getMessage());
|
||||
failed(t);
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
if (!completed) {
|
||||
timeoutTimer.stop();
|
||||
log.error("BroadcastTx failed. Error:" + t.getMessage());
|
||||
failed(t);
|
||||
} else {
|
||||
log.warn("We got the callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
|
@ -46,7 +46,6 @@ public class SellerSendPayoutTxPublishedMessage extends TradeTask {
|
||||
processModel.getMyNodeAddress(),
|
||||
UUID.randomUUID().toString()
|
||||
);
|
||||
log.info("Send message to peer. tradeId={}, message{}", id, message);
|
||||
trade.setState(Trade.State.SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG);
|
||||
processModel.getP2PService().sendEncryptedMailboxMessage(
|
||||
trade.getTradingPeerNodeAddress(),
|
||||
@ -55,20 +54,21 @@ public class SellerSendPayoutTxPublishedMessage extends TradeTask {
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.debug("Message arrived at peer. tradeId={}, message{}", id, message);
|
||||
log.info("Message arrived at peer. tradeId={}", id);
|
||||
trade.setState(Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.debug("Message stored in mailbox. tradeId={}, message{}", id, message);
|
||||
log.info("Message stored in mailbox. tradeId={}", id);
|
||||
trade.setState(Trade.State.SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMailboxMessage failed. message=" + message);
|
||||
trade.setState(Trade.State.SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG);
|
||||
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
||||
failed(errorMessage);
|
||||
|
@ -18,6 +18,8 @@
|
||||
package io.bisq.core.trade.protocol.tasks.seller_as_taker;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.bisq.common.Timer;
|
||||
import io.bisq.common.UserThread;
|
||||
import io.bisq.common.crypto.Hash;
|
||||
import io.bisq.common.taskrunner.TaskRunner;
|
||||
import io.bisq.core.btc.AddressEntry;
|
||||
@ -75,6 +77,13 @@ public class SellerAsTakerSignAndPublishDepositTx extends TradeTask {
|
||||
walletService.saveAddressEntryList();
|
||||
|
||||
TradingPeer tradingPeer = processModel.getTradingPeer();
|
||||
|
||||
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_DEPOSIT_TX);
|
||||
complete();
|
||||
}, 5);
|
||||
|
||||
Transaction depositTx = processModel.getTradeWalletService().takerSignsAndPublishesDepositTx(
|
||||
true,
|
||||
contractHash,
|
||||
@ -87,17 +96,26 @@ public class SellerAsTakerSignAndPublishDepositTx extends TradeTask {
|
||||
new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
log.trace("takerSignAndPublishTx succeeded " + transaction);
|
||||
if (!completed) {
|
||||
timeoutTimer.stop();
|
||||
log.trace("takerSignAndPublishTx succeeded " + transaction);
|
||||
trade.setDepositTx(transaction);
|
||||
trade.setState(Trade.State.TAKER_PUBLISHED_DEPOSIT_TX);
|
||||
|
||||
trade.setDepositTx(transaction);
|
||||
trade.setState(Trade.State.TAKER_PUBLISHED_DEPOSIT_TX);
|
||||
|
||||
complete();
|
||||
complete();
|
||||
} else {
|
||||
log.warn("We got the callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
failed(t);
|
||||
if (!completed) {
|
||||
timeoutTimer.stop();
|
||||
failed(t);
|
||||
} else {
|
||||
log.warn("We got the callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
});
|
||||
trade.setDepositTx(depositTx);
|
||||
|
@ -18,6 +18,8 @@
|
||||
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.arbitration.Arbitrator;
|
||||
import io.bisq.core.btc.AddressEntry;
|
||||
@ -102,27 +104,45 @@ public class CreateTakerFeeTx extends TradeTask {
|
||||
// We need to create another instance, otherwise the tx would trigger an invalid state exception
|
||||
// if it gets committed 2 times
|
||||
tradeWalletService.commitTx(tradeWalletService.getClonedTransaction(signedTx));
|
||||
|
||||
Timer timeoutTimer = UserThread.runAfter(() -> {
|
||||
log.warn("Broadcast not completed after 5 sec. We go on with the trade protocol.");
|
||||
trade.setTakerFeeTxId(signedTx.getHashAsString());
|
||||
processModel.setTakeOfferFeeTx(signedTx);
|
||||
complete();
|
||||
}, 5);
|
||||
|
||||
bsqWalletService.broadcastTx(signedTx, new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable Transaction transaction) {
|
||||
if (transaction != null) {
|
||||
checkArgument(transaction.equals(signedTx));
|
||||
trade.setTakerFeeTxId(transaction.getHashAsString());
|
||||
processModel.setTakeOfferFeeTx(transaction);
|
||||
if (!completed) {
|
||||
timeoutTimer.stop();
|
||||
if (transaction != null) {
|
||||
checkArgument(transaction.equals(signedTx));
|
||||
trade.setTakerFeeTxId(transaction.getHashAsString());
|
||||
processModel.setTakeOfferFeeTx(transaction);
|
||||
|
||||
complete();
|
||||
log.debug("Successfully sent tx with id " + transaction.getHashAsString());
|
||||
complete();
|
||||
log.debug("Successfully sent tx with id " + transaction.getHashAsString());
|
||||
}
|
||||
} else {
|
||||
log.warn("We got the callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
log.error(t.toString());
|
||||
t.printStackTrace();
|
||||
trade.setErrorMessage("An error occurred.\n" +
|
||||
"Error message:\n"
|
||||
+ t.getMessage());
|
||||
failed(t);
|
||||
if (!completed) {
|
||||
timeoutTimer.stop();
|
||||
log.error(t.toString());
|
||||
t.printStackTrace();
|
||||
trade.setErrorMessage("An error occurred.\n" +
|
||||
"Error message:\n"
|
||||
+ t.getMessage());
|
||||
failed(t);
|
||||
} else {
|
||||
log.warn("We got the callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -18,6 +18,8 @@
|
||||
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;
|
||||
@ -36,20 +38,36 @@ public class TakerPublishTakerFeeTx extends TradeTask {
|
||||
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) {
|
||||
log.debug("Trading fee published successfully. Transaction ID = " + transaction.getHashAsString());
|
||||
|
||||
trade.setState(Trade.State.TAKER_PUBLISHED_TAKER_FEE_TX);
|
||||
complete();
|
||||
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 callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
appendToErrorMessage("Trading fee payment failed. Maybe your network connection was lost. Please try again.");
|
||||
failed(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 callback called after the timeout has been triggered a complete().");
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
|
@ -51,20 +51,21 @@ public class TakerSendDepositTxPublishedMessage extends TradeTask {
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.debug("Message arrived at peer. tradeId={}, message{}", id, message);
|
||||
log.info("Message arrived at peer. tradeId={}", id);
|
||||
trade.setState(Trade.State.TAKER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.debug("Message stored in mailbox. tradeId={}, message{}", id, message);
|
||||
log.info("Message stored in mailbox. tradeId={}", id);
|
||||
trade.setState(Trade.State.TAKER_STORED_IN_MAILBOX_DEPOSIT_TX_PUBLISHED_MSG);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMailboxMessage failed. message=" + message);
|
||||
trade.setState(Trade.State.TAKER_SEND_FAILED_DEPOSIT_TX_PUBLISHED_MSG);
|
||||
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
||||
failed();
|
||||
|
@ -57,10 +57,10 @@ public final class Preferences implements PersistedDataHost {
|
||||
));
|
||||
|
||||
private static final ArrayList<BlockChainExplorer> LTC_MAIN_NET_EXPLORERS = new ArrayList<>(Arrays.asList(
|
||||
new BlockChainExplorer("Blockcypher", "https://live.blockcypher.com/ltc/tx", "https://live.blockcypher.com/ltc/address"),
|
||||
new BlockChainExplorer("CryptoID", "https://chainz.cryptoid.info/ltc/tx.dws?", "https://chainz.cryptoid.info/ltc/address.dws?"),
|
||||
new BlockChainExplorer("SoChain", "https://chain.so/tx/LTC/", "https://chain.so/address/LTC/"),
|
||||
new BlockChainExplorer("Abe Search", "http://explorer.litecoin.net/tx/", "http://explorer.litecoin.net/address/"),
|
||||
new BlockChainExplorer("Blockcypher", "https://live.blockcypher.com/ltc/tx", "https://live.blockcypher.com/ltc/address"),
|
||||
new BlockChainExplorer("SoChain", "https://chain.so/tx/LTC/", "https://chain.so/address/LTC/"),
|
||||
new BlockChainExplorer("Blockr.io", "http://ltc.blockr.io/tx/info/", "http://ltc.blockr.io/address/info/")
|
||||
));
|
||||
|
||||
|
@ -166,11 +166,10 @@ public class BisqApp extends Application {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
|
||||
final BaseCurrencyNetwork baseCurrencyNetwork = BisqEnvironment.getBaseCurrencyNetwork();
|
||||
|
||||
Res.setBaseCurrencyCode(baseCurrencyNetwork.getCurrencyCode());
|
||||
final String currencyCode = baseCurrencyNetwork.getCurrencyCode();
|
||||
Res.setBaseCurrencyCode(currencyCode);
|
||||
Res.setBaseCurrencyName(baseCurrencyNetwork.getCurrencyName());
|
||||
|
||||
CurrencyUtil.setBaseCurrencyNetwork(baseCurrencyNetwork.getCurrencyCode());
|
||||
CurrencyUtil.setBaseCurrencyCode(currencyCode);
|
||||
|
||||
try {
|
||||
// Guice
|
||||
|
@ -268,7 +268,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||
// As we use the best fee estimation (for 1 confirmation) that risk should not be too critical as long there are
|
||||
// not too many inputs.
|
||||
|
||||
// trade fee tx: 226 bytes (1 input) - 374 bytes (2 inputs)
|
||||
// trade fee tx: 226 bytes (1 input) - 374 bytes (2 inputs) (148 byte per input)
|
||||
|
||||
// Set the default values (in rare cases if the fee request was not done yet we get the hard coded default values)
|
||||
// But offer creation happens usually after that so we should have already the value from the estimation service.
|
||||
|
@ -387,8 +387,6 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
model.getMakerFee(),
|
||||
model.getTxFee()
|
||||
);
|
||||
//TODO remove
|
||||
log.error(message);
|
||||
new Popup<>().headLine(Res.get("createOffer.createOfferFundWalletInfo.headline"))
|
||||
.instruction(message)
|
||||
.dontShowAgainId(key)
|
||||
|
@ -521,6 +521,8 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||
if (dataModel.paymentAccount != null)
|
||||
btcValidator.setMaxValue(dataModel.paymentAccount.getPaymentMethod().getMaxTradeLimitAsCoin());
|
||||
|
||||
btcValidator.setMinValue(Restrictions.getMinTradeAmount());
|
||||
|
||||
final boolean isBuy = dataModel.getDirection() == OfferPayload.Direction.BUY;
|
||||
directionLabel = isBuy ? Res.get("shared.buyBitcoin") : Res.get("shared.sellBitcoin");
|
||||
amountDescription = Res.get("createOffer.amountPriceBox.amountDescription",
|
||||
@ -733,9 +735,12 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||
String key = "buyerSecurityDepositLowerAsDefault";
|
||||
if (preferences.showAgain(key) &&
|
||||
btcFormatter.parseToCoin(buyerSecurityDeposit.get()).compareTo(defaultSecurityDeposit) < 0) {
|
||||
final String postfix = dataModel.isBuyOffer() ?
|
||||
Res.get("createOffer.tooLowSecDeposit.makerIsBuyer") :
|
||||
Res.get("createOffer.tooLowSecDeposit.makerIsSeller");
|
||||
new Popup<>()
|
||||
.warning(Res.get("createOffer.tooLowSecDeposit.warning",
|
||||
btcFormatter.formatCoinWithCode(defaultSecurityDeposit)))
|
||||
btcFormatter.formatCoinWithCode(defaultSecurityDeposit)) + "\n\n" + postfix)
|
||||
.width(800)
|
||||
.actionButtonText(Res.get("createOffer.resetToDefault"))
|
||||
.onAction(() -> {
|
||||
|
@ -410,8 +410,6 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
model.getTakerFee(),
|
||||
model.getTxFee()
|
||||
);
|
||||
//TODO remove
|
||||
log.error(message);
|
||||
key = "takeOfferFundWalletInfo";
|
||||
new Popup<>().headLine(Res.get("takeOffer.takeOfferFundWalletInfo.headline"))
|
||||
.instruction(message)
|
||||
|
@ -182,6 +182,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
errorMessage.set(offer.getErrorMessage());
|
||||
|
||||
btcValidator.setMaxValue(offer.getAmount());
|
||||
btcValidator.setMinValue(offer.getMinAmount());
|
||||
}
|
||||
|
||||
|
||||
@ -208,8 +209,6 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
|
||||
public void onPaymentAccountSelected(PaymentAccount paymentAccount) {
|
||||
dataModel.onPaymentAccountSelected(paymentAccount);
|
||||
if (offer != null)
|
||||
btcValidator.setMaxValue(offer.getAmount());
|
||||
}
|
||||
|
||||
public void onShowPayFundsScreen() {
|
||||
|
@ -130,20 +130,21 @@ public class SendPrivateNotificationWindow extends Overlay<SendPrivateNotificati
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.trace("PrivateNotificationMessage arrived at peer.");
|
||||
log.info("PrivateNotificationMessage arrived at peer.");
|
||||
new Popup<>().feedback(Res.get("shared.messageArrived"))
|
||||
.onClose(SendPrivateNotificationWindow.this::hide).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.trace("PrivateNotificationMessage was stored in mailbox.");
|
||||
log.info("PrivateNotificationMessage was stored in mailbox.");
|
||||
new Popup<>().feedback(Res.get("shared.messageStoredInMailbox"))
|
||||
.onClose(SendPrivateNotificationWindow.this::hide).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMailboxMessage failed. message=" + message);
|
||||
new Popup<>().feedback(Res.get("shared.messageSendingFailed", errorMessage))
|
||||
.onClose(SendPrivateNotificationWindow.this::hide).show();
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ public class SellerStep3View extends TradeStepView {
|
||||
if (myPaymentAccountPayload instanceof CryptoCurrencyAccountPayload) {
|
||||
myPaymentDetails = ((CryptoCurrencyAccountPayload) myPaymentAccountPayload).getAddress();
|
||||
peersPaymentDetails = ((CryptoCurrencyAccountPayload) peersPaymentAccountPayload).getAddress();
|
||||
myTitle = Res.get("portfolio.pending.step3_seller.yourAddress");
|
||||
myTitle = Res.get("portfolio.pending.step3_seller.yourAddress", nameByCode);
|
||||
peersTitle = Res.get("portfolio.pending.step3_seller.buyersAddress", nameByCode);
|
||||
isBlockChain = true;
|
||||
} else {
|
||||
@ -276,7 +276,7 @@ public class SellerStep3View extends TradeStepView {
|
||||
Optional<String> optionalHolderName = getOptionalHolderName();
|
||||
if (optionalHolderName.isPresent()) {
|
||||
//noinspection UnusedAssignment
|
||||
message = message + Res.get("portfolio.pending.step3_seller.bankCheck" + optionalHolderName.get(), part);
|
||||
message = message + Res.get("portfolio.pending.step3_seller.bankCheck", optionalHolderName.get(), part);
|
||||
}
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
|
@ -88,7 +88,7 @@ public class BsqValidator extends AltcoinValidator {
|
||||
BigDecimal bd = new BigDecimal(input);
|
||||
final BigDecimal satoshis = bd.movePointRight(3);
|
||||
if (satoshis.scale() > 0)
|
||||
return new ValidationResult(false, Res.get("validation.btc.toSmall"));
|
||||
return new ValidationResult(false, Res.get("validation.btc.fraction"));
|
||||
else
|
||||
return new ValidationResult(true);
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ public class BtcValidator extends NumberValidator {
|
||||
|
||||
protected final BSFormatter formatter;
|
||||
|
||||
@Nullable
|
||||
protected Coin minValue;
|
||||
|
||||
@Nullable
|
||||
protected Coin maxValue;
|
||||
@ -40,6 +42,10 @@ public class BtcValidator extends NumberValidator {
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
public void setMinValue(@NotNull Coin minValue) {
|
||||
this.minValue = minValue;
|
||||
}
|
||||
|
||||
public void setMaxValue(@NotNull Coin maxValue) {
|
||||
this.maxValue = maxValue;
|
||||
}
|
||||
@ -57,6 +63,7 @@ public class BtcValidator extends NumberValidator {
|
||||
.and(validateIfNotNegative(input))
|
||||
.and(validateIfNotFractionalBtcValue(input))
|
||||
.and(validateIfNotExceedsMaxBtcValue(input))
|
||||
.and(validateIfNotUnderMinValue(input))
|
||||
.and(validateIfAboveDust(input));
|
||||
}
|
||||
|
||||
@ -75,7 +82,7 @@ public class BtcValidator extends NumberValidator {
|
||||
BigDecimal bd = new BigDecimal(input);
|
||||
final BigDecimal satoshis = bd.movePointRight(8);
|
||||
if (satoshis.scale() > 0)
|
||||
return new ValidationResult(false, Res.get("validation.btc.toSmall"));
|
||||
return new ValidationResult(false, Res.get("validation.btc.fraction"));
|
||||
else
|
||||
return new ValidationResult(true);
|
||||
}
|
||||
@ -91,4 +98,16 @@ public class BtcValidator extends NumberValidator {
|
||||
return new ValidationResult(false, Res.get("validation.invalidInput", t.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
protected ValidationResult validateIfNotUnderMinValue(String input) {
|
||||
try {
|
||||
final Coin coin = Coin.parseCoin(input);
|
||||
if (minValue != null && coin.compareTo(minValue) < 0)
|
||||
return new ValidationResult(false, Res.get("validation.btc.toSmall", formatter.formatCoinWithCode(minValue)));
|
||||
else
|
||||
return new ValidationResult(true);
|
||||
} catch (Throwable t) {
|
||||
return new ValidationResult(false, Res.get("validation.invalidInput", t.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ public class SecurityDepositValidator extends BtcValidator {
|
||||
public SecurityDepositValidator(BSFormatter formatter) {
|
||||
super(formatter);
|
||||
setMaxValue(Restrictions.getMaxBuyerSecurityDeposit());
|
||||
setMinValue(Restrictions.getMinBuyerSecurityDeposit());
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,11 +76,10 @@ public class SeedNode {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
|
||||
final BaseCurrencyNetwork baseCurrencyNetwork = BisqEnvironment.getBaseCurrencyNetwork();
|
||||
|
||||
Res.setBaseCurrencyCode(baseCurrencyNetwork.getCurrencyCode());
|
||||
final String currencyCode = baseCurrencyNetwork.getCurrencyCode();
|
||||
Res.setBaseCurrencyCode(currencyCode);
|
||||
Res.setBaseCurrencyName(baseCurrencyNetwork.getCurrencyName());
|
||||
|
||||
CurrencyUtil.setBaseCurrencyNetwork(baseCurrencyNetwork.getCurrencyCode());
|
||||
CurrencyUtil.setBaseCurrencyCode(currencyCode);
|
||||
|
||||
seedNodeModule = new SeedNodeModule(bisqEnvironment);
|
||||
injector = Guice.createInjector(seedNodeModule);
|
||||
|
@ -84,11 +84,10 @@ public class Statistics {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
|
||||
final BaseCurrencyNetwork baseCurrencyNetwork = BisqEnvironment.getBaseCurrencyNetwork();
|
||||
|
||||
Res.setBaseCurrencyCode(baseCurrencyNetwork.getCurrencyCode());
|
||||
final String currencyCode = baseCurrencyNetwork.getCurrencyCode();
|
||||
Res.setBaseCurrencyCode(currencyCode);
|
||||
Res.setBaseCurrencyName(baseCurrencyNetwork.getCurrencyName());
|
||||
|
||||
CurrencyUtil.setBaseCurrencyNetwork(baseCurrencyNetwork.getCurrencyCode());
|
||||
CurrencyUtil.setBaseCurrencyCode(currencyCode);
|
||||
|
||||
statisticsModule = new StatisticsModule(bisqEnvironment);
|
||||
injector = Guice.createInjector(statisticsModule);
|
||||
|
Loading…
Reference in New Issue
Block a user