diff --git a/core/src/main/java/bisq/core/offer/OfferUtil.java b/core/src/main/java/bisq/core/offer/OfferUtil.java index 7e15dd5d471..79035cea92c 100644 --- a/core/src/main/java/bisq/core/offer/OfferUtil.java +++ b/core/src/main/java/bisq/core/offer/OfferUtil.java @@ -140,6 +140,10 @@ public static boolean isBsqForMakerFeeAvailable(BsqWalletService bsqWalletServic if (makerFee == null) return true; + Coin surplusFunds = availableBalance.subtract(makerFee); + if (Restrictions.isDust(surplusFunds)) { + return false; // we can't be left with dust + } return !availableBalance.subtract(makerFee).isNegative(); } @@ -171,6 +175,10 @@ public static boolean isBsqForTakerFeeAvailable(BsqWalletService bsqWalletServic if (takerFee == null) return true; + Coin surplusFunds = availableBalance.subtract(takerFee); + if (Restrictions.isDust(surplusFunds)) { + return false; // we can't be left with dust + } return !availableBalance.subtract(takerFee).isNegative(); } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java index 49f9b5c6e7e..56603360623 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java @@ -718,8 +718,14 @@ ReadOnlyObjectProperty totalToPayAsCoinProperty() { return totalToPayAsCoin; } - Coin getBsqBalance() { - return bsqWalletService.getAvailableConfirmedBalance(); + Coin getUsableBsqBalance() { + // we have to keep a minimum amount of BSQ == bitcoin dust limit + // otherwise there would be dust violations for change UTXOs + // essentially means the minimum usable balance of BSQ is 5.46 + Coin usableBsqBalance = bsqWalletService.getAvailableConfirmedBalance().subtract(Restrictions.getMinNonDustOutput()); + if (usableBsqBalance.isNegative()) + usableBsqBalance = Coin.ZERO; + return usableBsqBalance; } public void setMarketPriceAvailable(boolean marketPriceAvailable) { diff --git a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java index 570da92e465..8924495327b 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java @@ -373,9 +373,9 @@ private void showInsufficientBsqFundsForBtcFeePaymentPopup() { String message = null; if (makerFee != null) { message = Res.get("popup.warning.insufficientBsqFundsForBtcFeePayment", - bsqFormatter.formatCoinWithCode(makerFee.subtract(model.getDataModel().getBsqBalance()))); + bsqFormatter.formatCoinWithCode(makerFee.subtract(model.getDataModel().getUsableBsqBalance()))); - } else if (model.getDataModel().getBsqBalance().isZero()) + } else if (model.getDataModel().getUsableBsqBalance().isZero()) message = Res.get("popup.warning.noBsqFundsForBtcFeePayment"); if (message != null) @@ -1109,9 +1109,9 @@ private void showFeeOption() { String missingBsq = null; if (makerFee != null) { missingBsq = Res.get("popup.warning.insufficientBsqFundsForBtcFeePayment", - bsqFormatter.formatCoinWithCode(makerFee.subtract(model.getDataModel().getBsqBalance()))); + bsqFormatter.formatCoinWithCode(makerFee.subtract(model.getDataModel().getUsableBsqBalance()))); - } else if (model.getDataModel().getBsqBalance().isZero()) { + } else if (model.getDataModel().getUsableBsqBalance().isZero()) { missingBsq = Res.get("popup.warning.noBsqFundsForBtcFeePayment"); } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java index 58711b22868..b35a9d67035 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java @@ -639,8 +639,14 @@ public Coin getSellerSecurityDeposit() { return offer.getSellerSecurityDeposit(); } - public Coin getBsqBalance() { - return bsqWalletService.getAvailableConfirmedBalance(); + public Coin getUsableBsqBalance() { + // we have to keep a minimum amount of BSQ == bitcoin dust limit + // otherwise there would be dust violations for change UTXOs + // essentially means the minimum usable balance of BSQ is 5.46 + Coin usableBsqBalance = bsqWalletService.getAvailableConfirmedBalance().subtract(Restrictions.getMinNonDustOutput()); + if (usableBsqBalance.isNegative()) + usableBsqBalance = Coin.ZERO; + return usableBsqBalance; } public boolean isHalCashAccount() { diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java index 94f35caaca7..c921ca34575 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java @@ -927,9 +927,9 @@ private void showFeeOption() { String missingBsq = null; if (takerFee != null) { missingBsq = Res.get("popup.warning.insufficientBsqFundsForBtcFeePayment", - bsqFormatter.formatCoinWithCode(takerFee.subtract(model.dataModel.getBsqBalance()))); + bsqFormatter.formatCoinWithCode(takerFee.subtract(model.dataModel.getUsableBsqBalance()))); - } else if (model.dataModel.getBsqBalance().isZero()) { + } else if (model.dataModel.getUsableBsqBalance().isZero()) { missingBsq = Res.get("popup.warning.noBsqFundsForBtcFeePayment"); } @@ -1225,9 +1225,9 @@ private void showInsufficientBsqFundsForBtcFeePaymentPopup() { String message = null; if (takerFee != null) message = Res.get("popup.warning.insufficientBsqFundsForBtcFeePayment", - bsqFormatter.formatCoinWithCode(takerFee.subtract(model.dataModel.getBsqBalance()))); + bsqFormatter.formatCoinWithCode(takerFee.subtract(model.dataModel.getUsableBsqBalance()))); - else if (model.dataModel.getBsqBalance().isZero()) + else if (model.dataModel.getUsableBsqBalance().isZero()) message = Res.get("popup.warning.noBsqFundsForBtcFeePayment"); if (message != null)