diff --git a/core/src/main/java/haveno/core/offer/CreateOfferService.java b/core/src/main/java/haveno/core/offer/CreateOfferService.java index 0d6824c231..d0a79be77c 100644 --- a/core/src/main/java/haveno/core/offer/CreateOfferService.java +++ b/core/src/main/java/haveno/core/offer/CreateOfferService.java @@ -205,8 +205,8 @@ public class CreateOfferService { useMarketBasedPriceValue, amountAsLong, minAmountAsLong, - hasBuyerAsTakerWithoutDeposit ? HavenoUtils.MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT : HavenoUtils.MAKER_FEE_PCT, - hasBuyerAsTakerWithoutDeposit ? 0d : HavenoUtils.TAKER_FEE_PCT, + HavenoUtils.getMakerFeePct(currencyCode, hasBuyerAsTakerWithoutDeposit), + HavenoUtils.getTakerFeePct(currencyCode, hasBuyerAsTakerWithoutDeposit), HavenoUtils.PENALTY_FEE_PCT, hasBuyerAsTakerWithoutDeposit ? 0d : securityDepositPct, // buyer as taker security deposit is optional for private offers securityDepositPct, diff --git a/core/src/main/java/haveno/core/offer/OpenOfferManager.java b/core/src/main/java/haveno/core/offer/OpenOfferManager.java index 31ad71d5fa..e4895fbe07 100644 --- a/core/src/main/java/haveno/core/offer/OpenOfferManager.java +++ b/core/src/main/java/haveno/core/offer/OpenOfferManager.java @@ -1595,8 +1595,9 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe if (hasBuyerAsTakerWithoutDeposit) { // verify maker's trade fee - if (offer.getMakerFeePct() != HavenoUtils.MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT) { - errorMessage = "Wrong maker fee for offer " + request.offerId + ". Expected " + HavenoUtils.MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT + " but got " + offer.getMakerFeePct(); + double makerFeePct = HavenoUtils.getMakerFeePct(request.getOfferPayload().getCounterCurrencyCode(), hasBuyerAsTakerWithoutDeposit); + if (offer.getMakerFeePct() != makerFeePct) { + errorMessage = "Wrong maker fee for offer " + request.offerId + ". Expected " + makerFeePct + " but got " + offer.getMakerFeePct(); log.warn(errorMessage); sendAckMessage(request.getClass(), peer, request.getPubKeyRing(), request.getOfferId(), request.getUid(), false, errorMessage); return; @@ -1636,16 +1637,18 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe } // verify maker's trade fee - if (offer.getMakerFeePct() != HavenoUtils.MAKER_FEE_PCT) { - errorMessage = "Wrong maker fee for offer " + request.offerId + ". Expected " + HavenoUtils.MAKER_FEE_PCT + " but got " + offer.getMakerFeePct(); + double makerFeePct = HavenoUtils.getMakerFeePct(request.getOfferPayload().getCounterCurrencyCode(), hasBuyerAsTakerWithoutDeposit); + if (offer.getMakerFeePct() != makerFeePct) { + errorMessage = "Wrong maker fee for offer " + request.offerId + ". Expected " + makerFeePct + " but got " + offer.getMakerFeePct(); log.warn(errorMessage); sendAckMessage(request.getClass(), peer, request.getPubKeyRing(), request.getOfferId(), request.getUid(), false, errorMessage); return; } // verify taker's trade fee - if (offer.getTakerFeePct() != HavenoUtils.TAKER_FEE_PCT) { - errorMessage = "Wrong taker fee for offer " + request.offerId + ". Expected " + HavenoUtils.TAKER_FEE_PCT + " but got " + offer.getTakerFeePct(); + double takerFeePct = HavenoUtils.getTakerFeePct(request.getOfferPayload().getCounterCurrencyCode(), hasBuyerAsTakerWithoutDeposit); + if (offer.getTakerFeePct() != takerFeePct) { + errorMessage = "Wrong taker fee for offer " + request.offerId + ". Expected " + takerFeePct + " but got " + offer.getTakerFeePct(); log.warn(errorMessage); sendAckMessage(request.getClass(), peer, request.getPubKeyRing(), request.getOfferId(), request.getUid(), false, errorMessage); return; @@ -1685,7 +1688,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe } // verify maker's reserve tx (double spend, trade fee, trade amount, mining fee) - BigInteger maxTradeFee = HavenoUtils.multiply(offer.getAmount(), hasBuyerAsTakerWithoutDeposit ? HavenoUtils.MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT : HavenoUtils.MAKER_FEE_PCT); + double makerFeePct = HavenoUtils.getMakerFeePct(request.getOfferPayload().getCounterCurrencyCode(), hasBuyerAsTakerWithoutDeposit); + BigInteger maxTradeFee = HavenoUtils.multiply(offer.getAmount(), makerFeePct); BigInteger sendTradeAmount = offer.getDirection() == OfferDirection.BUY ? BigInteger.ZERO : offer.getAmount(); BigInteger securityDeposit = offer.getDirection() == OfferDirection.BUY ? offer.getMaxBuyerSecurityDeposit() : offer.getMaxSellerSecurityDeposit(); BigInteger penaltyFee = HavenoUtils.multiply(securityDeposit, HavenoUtils.PENALTY_FEE_PCT); diff --git a/core/src/main/java/haveno/core/trade/HavenoUtils.java b/core/src/main/java/haveno/core/trade/HavenoUtils.java index 1d9c154b5c..9dd3760e6d 100644 --- a/core/src/main/java/haveno/core/trade/HavenoUtils.java +++ b/core/src/main/java/haveno/core/trade/HavenoUtils.java @@ -34,6 +34,7 @@ import haveno.core.api.CoreNotificationService; import haveno.core.api.CorePaymentAccountsService; import haveno.core.api.XmrConnectionService; import haveno.core.app.HavenoSetup; +import haveno.core.locale.CurrencyUtil; import haveno.core.offer.OfferPayload; import haveno.core.offer.OpenOfferManager; import haveno.core.support.dispute.arbitration.ArbitrationManager; @@ -94,10 +95,13 @@ public class HavenoUtils { // configure fees public static final boolean ARBITRATOR_ASSIGNS_TRADE_FEE_ADDRESS = true; - public static final double PENALTY_FEE_PCT = 0.25; // percent of security deposit to charge for penalty - public static final double MAKER_FEE_PCT = 0.0015; // 0.15% - public static final double TAKER_FEE_PCT = 0.0075; // 0.75% - public static final double MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT = MAKER_FEE_PCT + TAKER_FEE_PCT; // customize maker's fee when no deposit or fee from taker + public static final double PENALTY_FEE_PCT = 0.25; // charge 25% of security deposit for penalty + private static final double MAKER_FEE_PCT_CRYPTO = 0.0015; + private static final double TAKER_FEE_PCT_CRYPTO = 0.0075; + private static final double MAKER_FEE_PCT_TRADITIONAL = 0.0015; + private static final double TAKER_FEE_PCT_TRADITIONAL = 0.0075; + private static final double MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT_CRYPTO = MAKER_FEE_PCT_CRYPTO + TAKER_FEE_PCT_CRYPTO; // can customize maker's fee when no deposit from taker + private static final double MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT_TRADITIONAL = MAKER_FEE_PCT_TRADITIONAL + TAKER_FEE_PCT_TRADITIONAL; public static final double MINER_FEE_TOLERANCE_FACTOR = 5.0; // miner fees must be within 5x of each other // other configuration @@ -178,6 +182,26 @@ public class HavenoUtils { GenUtils.waitFor(waitMs); } + public static double getMakerFeePct(String currencyCode, boolean hasBuyerAsTakerWithoutDeposit) { + if (CurrencyUtil.isCryptoCurrency(currencyCode)) { + return hasBuyerAsTakerWithoutDeposit ? MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT_CRYPTO : MAKER_FEE_PCT_CRYPTO; + } else if (CurrencyUtil.isTraditionalCurrency(currencyCode)) { + return hasBuyerAsTakerWithoutDeposit ? MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT_TRADITIONAL : MAKER_FEE_PCT_TRADITIONAL; + } else { + throw new IllegalArgumentException("Unsupported currency code: " + currencyCode); + } + } + + public static double getTakerFeePct(String currencyCode, boolean hasBuyerAsTakerWithoutDeposit) { + if (CurrencyUtil.isCryptoCurrency(currencyCode)) { + return hasBuyerAsTakerWithoutDeposit ? 0d : TAKER_FEE_PCT_CRYPTO; + } else if (CurrencyUtil.isTraditionalCurrency(currencyCode)) { + return hasBuyerAsTakerWithoutDeposit ? 0d : TAKER_FEE_PCT_TRADITIONAL; + } else { + throw new IllegalArgumentException("Unsupported currency code: " + currencyCode); + } + } + // ----------------------- CONVERSION UTILS ------------------------------- public static BigInteger coinToAtomicUnits(Coin coin) { diff --git a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java index fa286767b8..bcb18c32c9 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java @@ -697,7 +697,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel { } public BigInteger getMaxMakerFee() { - return HavenoUtils.multiply(amount.get(), buyerAsTakerWithoutDeposit.get() ? HavenoUtils.MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT : HavenoUtils.MAKER_FEE_PCT); + return HavenoUtils.multiply(amount.get(), HavenoUtils.getMakerFeePct(tradeCurrencyCode.get(), buyerAsTakerWithoutDeposit.get())); } boolean canPlaceOffer() {