diff --git a/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java b/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java index 3bb4721b17a..27b27a9e863 100644 --- a/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java +++ b/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java @@ -450,7 +450,7 @@ public Transaction completePreparedBsqTx(Transaction preparedBsqTx, boolean useC // typical size for a tx with 2 inputs int txSizeWithUnsignedInputs = 203; // If useCustomTxFee we allow overriding the estimated fee from preferences - Coin txFeePerByte = useCustomTxFee ? getTxFeeForWithdrawalPerByte() : feeService.getTxFeePerByte(); + Coin txFeePerByte = useCustomTxFee ? getTxFeePerByte() : feeService.getTxFeePerByte(); // In case there are no change outputs we force a change by adding min dust to the BTC input Coin forcedChangeValue = Coin.ZERO; @@ -785,7 +785,7 @@ public void doubleSpendTransaction(String txId, Runnable resultHandler, ErrorMes int txSize = 0; Transaction tx; SendRequest sendRequest; - Coin txFeeForWithdrawalPerByte = getTxFeeForWithdrawalPerByte(); + Coin txFeeForWithdrawalPerByte = getTxFeePerByte(); do { counter++; fee = txFeeForWithdrawalPerByte.multiply(txSize); @@ -902,7 +902,7 @@ public Transaction getFeeEstimationTransaction(String fromAddress, int counter = 0; int txSize = 0; Transaction tx; - Coin txFeeForWithdrawalPerByte = getTxFeeForWithdrawalPerByte(); + Coin txFeeForWithdrawalPerByte = getTxFeePerByte(); do { counter++; fee = txFeeForWithdrawalPerByte.multiply(txSize); @@ -949,7 +949,7 @@ public Transaction getFeeEstimationTransactionForMultipleAddresses(Set f int counter = 0; int txSize = 0; Transaction tx; - Coin txFeeForWithdrawalPerByte = getTxFeeForWithdrawalPerByte(); + Coin txFeeForWithdrawalPerByte = getTxFeePerByte(); do { counter++; fee = txFeeForWithdrawalPerByte.multiply(txSize); @@ -974,7 +974,7 @@ public Transaction getFeeEstimationTransactionForMultipleAddresses(Set f } private boolean feeEstimationNotSatisfied(int counter, Transaction tx) { - long targetFee = getTxFeeForWithdrawalPerByte().multiply(tx.bitcoinSerialize().length).value; + long targetFee = getTxFeePerByte().multiply(tx.bitcoinSerialize().length).value; return counter < 10 && (tx.getFee().value < targetFee || tx.getFee().value - targetFee > 1000); diff --git a/core/src/main/java/bisq/core/btc/wallet/WalletService.java b/core/src/main/java/bisq/core/btc/wallet/WalletService.java index d56b34a7c95..d279677782a 100644 --- a/core/src/main/java/bisq/core/btc/wallet/WalletService.java +++ b/core/src/main/java/bisq/core/btc/wallet/WalletService.java @@ -449,9 +449,9 @@ public Coin getBalance(TransactionOutput output) { return getBalanceForAddress(getAddressFromOutput(output)); } - public Coin getTxFeeForWithdrawalPerByte() { - Coin fee = (preferences.isUseCustomWithdrawalTxFee()) ? - Coin.valueOf(preferences.getWithdrawalTxFeeInBytes()) : + public Coin getTxFeePerByte() { + Coin fee = (preferences.isUseCustomTxFee()) ? + Coin.valueOf(preferences.getTxFeePerByte()) : feeService.getTxFeePerByte(); log.info("tx fee = " + fee.toFriendlyString()); return fee; @@ -491,7 +491,7 @@ public void emptyWallet(String toAddress, throws InsufficientMoneyException, AddressFormatException { SendRequest sendRequest = SendRequest.emptyWallet(Address.fromBase58(params, toAddress)); sendRequest.fee = Coin.ZERO; - sendRequest.feePerKb = getTxFeeForWithdrawalPerByte().multiply(1000); + sendRequest.feePerKb = getTxFeePerByte().multiply(1000); sendRequest.aesKey = aesKey; Wallet.SendResult sendResult = wallet.sendCoins(sendRequest); printTx("empty wallet", sendResult.tx); diff --git a/core/src/main/java/bisq/core/provider/fee/FeeService.java b/core/src/main/java/bisq/core/provider/fee/FeeService.java index f93a5a1c3b8..8b676beaa9d 100644 --- a/core/src/main/java/bisq/core/provider/fee/FeeService.java +++ b/core/src/main/java/bisq/core/provider/fee/FeeService.java @@ -20,6 +20,7 @@ import bisq.core.dao.governance.param.Param; import bisq.core.dao.governance.period.PeriodService; import bisq.core.dao.state.DaoStateService; +import bisq.core.user.Preferences; import bisq.common.UserThread; import bisq.common.config.Config; @@ -93,6 +94,7 @@ public static Coin getMinTakerFee(boolean currencyForFeeIsBtc) { private final FeeProvider feeProvider; private final IntegerProperty feeUpdateCounter = new SimpleIntegerProperty(0); + private final Preferences preferences; private long txFeePerByte = BTC_DEFAULT_TX_FEE; private Map timeStampMap; private long lastRequest; @@ -105,8 +107,12 @@ public static Coin getMinTakerFee(boolean currencyForFeeIsBtc) { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public FeeService(FeeProvider feeProvider, DaoStateService daoStateService, PeriodService periodService) { + public FeeService(FeeProvider feeProvider, + DaoStateService daoStateService, + PeriodService periodService, + Preferences preferences) { this.feeProvider = feeProvider; + this.preferences = preferences; FeeService.daoStateService = daoStateService; FeeService.periodService = periodService; } @@ -135,6 +141,19 @@ public void requestFees(Runnable resultHandler) { } public void requestFees(@Nullable Runnable resultHandler, @Nullable FaultHandler faultHandler) { + + // If the user set a custom fee, use that one and skip querying the external fee API endpoint + if (preferences.isUseCustomTxFee()) { + txFeePerByte = preferences.getTxFeePerByte(); + log.info("Using custom tx fee: {} sats/vByte", txFeePerByte); + + if (resultHandler != null) + resultHandler.run(); + + return; + } + + // If user did not set a custom fee in their preferences, then query the fee API endpoint long now = Instant.now().getEpochSecond(); // We all requests only each 2 minutes if (now - lastRequest > MIN_PAUSE_BETWEEN_REQUESTS_IN_MIN * 60) { diff --git a/core/src/main/java/bisq/core/user/Preferences.java b/core/src/main/java/bisq/core/user/Preferences.java index 972fc5346f8..f161eefd748 100644 --- a/core/src/main/java/bisq/core/user/Preferences.java +++ b/core/src/main/java/bisq/core/user/Preferences.java @@ -494,13 +494,13 @@ public void setBitcoinNodes(String bitcoinNodes) { persist(); } - public void setUseCustomWithdrawalTxFee(boolean useCustomWithdrawalTxFee) { - prefPayload.setUseCustomWithdrawalTxFee(useCustomWithdrawalTxFee); + public void setUseCustomTxFee(boolean useCustomTxFee) { + prefPayload.setUseCustomTxFee(useCustomTxFee); persist(); } - public void setWithdrawalTxFeeInBytes(long withdrawalTxFeeInBytes) { - prefPayload.setWithdrawalTxFeeInBytes(withdrawalTxFeeInBytes); + public void setTxFeeInBytes(long txFeeInBytes) { + prefPayload.setTxFeePerByte(txFeeInBytes); persist(); } @@ -772,8 +772,8 @@ public List getBridgeAddresses() { return prefPayload.getBridgeAddresses(); } - public long getWithdrawalTxFeeInBytes() { - return Math.max(prefPayload.getWithdrawalTxFeeInBytes(), Config.baseCurrencyNetwork().getDefaultMinFeePerByte()); + public long getTxFeePerByte() { + return Math.max(prefPayload.getTxFeePerByte(), Config.baseCurrencyNetwork().getDefaultMinFeePerByte()); } public boolean isDaoFullNode() { @@ -881,9 +881,9 @@ private interface ExcludesDelegateMethods { void setBitcoinNodes(String bitcoinNodes); - void setUseCustomWithdrawalTxFee(boolean useCustomWithdrawalTxFee); + void setUseCustomTxFee(boolean useCustomTxFee); - void setWithdrawalTxFeeInBytes(long withdrawalTxFeeInBytes); + void getTxFeePerByte(long txFeePerByte); void setSelectedPaymentAccountForCreateOffer(@Nullable PaymentAccount paymentAccount); @@ -929,7 +929,7 @@ private interface ExcludesDelegateMethods { List getBridgeAddresses(); - long getWithdrawalTxFeeInBytes(); + long getTxFeePerByte(); void setUseStandbyMode(boolean useStandbyMode); diff --git a/core/src/main/java/bisq/core/user/PreferencesPayload.java b/core/src/main/java/bisq/core/user/PreferencesPayload.java index 3e0997d68b4..9f701622e1d 100644 --- a/core/src/main/java/bisq/core/user/PreferencesPayload.java +++ b/core/src/main/java/bisq/core/user/PreferencesPayload.java @@ -69,8 +69,8 @@ public final class PreferencesPayload implements UserThreadMappedPersistableEnve private boolean showOwnOffersInOfferBook = true; @Nullable private TradeCurrency preferredTradeCurrency; - private long withdrawalTxFeeInBytes = 100; - private boolean useCustomWithdrawalTxFee = false; + private long txFeePerByte = 100; + private boolean useCustomTxFee = false; private double maxPriceDistanceInPercent = 0.3; @Nullable private String offerBookChartScreenCurrencyCode; @@ -158,8 +158,8 @@ public Message toProtoMessage() { .setTacAccepted(tacAccepted) .setUseTorForBitcoinJ(useTorForBitcoinJ) .setShowOwnOffersInOfferBook(showOwnOffersInOfferBook) - .setWithdrawalTxFeeInBytes(withdrawalTxFeeInBytes) - .setUseCustomWithdrawalTxFee(useCustomWithdrawalTxFee) + .setTxFeePerByte(txFeePerByte) + .setUseCustomTxFee(useCustomTxFee) .setMaxPriceDistanceInPercent(maxPriceDistanceInPercent) .setTradeStatisticsTickUnitIndex(tradeStatisticsTickUnitIndex) .setResyncSpvRequested(resyncSpvRequested) @@ -234,8 +234,8 @@ public static PreferencesPayload fromProto(protobuf.PreferencesPayload proto, Co proto.getUseTorForBitcoinJ(), proto.getShowOwnOffersInOfferBook(), proto.hasPreferredTradeCurrency() ? TradeCurrency.fromProto(proto.getPreferredTradeCurrency()) : null, - proto.getWithdrawalTxFeeInBytes(), - proto.getUseCustomWithdrawalTxFee(), + proto.getTxFeePerByte(), + proto.getUseCustomTxFee(), proto.getMaxPriceDistanceInPercent(), ProtoUtil.stringOrNullFromProto(proto.getOfferBookChartScreenCurrencyCode()), ProtoUtil.stringOrNullFromProto(proto.getTradeChartsScreenCurrencyCode()), diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index ed7e335087b..5cd8c3d5a8f 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -1046,7 +1046,7 @@ setting.preferences.explorer.bsq=BSQ block explorer setting.preferences.deviation=Max. deviation from market price setting.preferences.avoidStandbyMode=Avoid standby mode setting.preferences.deviationToLarge=Values higher than {0}% are not allowed. -setting.preferences.txFee=Withdrawal transaction fee (satoshis/byte) +setting.preferences.txFee=Transaction fee (satoshis/byte) setting.preferences.useCustomValue=Use custom value setting.preferences.txFeeMin=Transaction fee must be at least {0} satoshis/byte setting.preferences.txFeeTooLarge=Your input is above any reasonable value (>5000 satoshis/byte). Transaction fee is usually in the range of 50-400 satoshis/byte. diff --git a/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java b/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java index b8e182c4a9b..9801684a698 100644 --- a/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java +++ b/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java @@ -259,34 +259,34 @@ private void initializeGeneralOptions() { useCustomFee = tuple.third; useCustomFeeCheckboxListener = (observable, oldValue, newValue) -> { - preferences.setUseCustomWithdrawalTxFee(newValue); + preferences.setUseCustomTxFee(newValue); transactionFeeInputTextField.setEditable(newValue); if (!newValue) { transactionFeeInputTextField.setText(String.valueOf(feeService.getTxFeePerByte().value)); try { - preferences.setWithdrawalTxFeeInBytes(feeService.getTxFeePerByte().value); + preferences.setTxFeeInBytes(feeService.getTxFeePerByte().value); } catch (Exception e) { e.printStackTrace(); } } - preferences.setUseCustomWithdrawalTxFee(newValue); + preferences.setUseCustomTxFee(newValue); }; transactionFeeFocusedListener = (o, oldValue, newValue) -> { if (oldValue && !newValue) { String estimatedFee = String.valueOf(feeService.getTxFeePerByte().value); try { - int withdrawalTxFeePerByte = Integer.parseInt(transactionFeeInputTextField.getText()); + int txFeePerByte = Integer.parseInt(transactionFeeInputTextField.getText()); final long minFeePerByte = Config.baseCurrencyNetwork().getDefaultMinFeePerByte(); - if (withdrawalTxFeePerByte < minFeePerByte) { + if (txFeePerByte < minFeePerByte) { new Popup().warning(Res.get("setting.preferences.txFeeMin", minFeePerByte)).show(); transactionFeeInputTextField.setText(estimatedFee); - } else if (withdrawalTxFeePerByte > 5000) { + } else if (txFeePerByte > 5000) { new Popup().warning(Res.get("setting.preferences.txFeeTooLarge")).show(); transactionFeeInputTextField.setText(estimatedFee); } else { - preferences.setWithdrawalTxFeeInBytes(withdrawalTxFeePerByte); + preferences.setTxFeeInBytes(txFeePerByte); } } catch (NumberFormatException t) { log.error(t.toString()); @@ -661,11 +661,11 @@ private void activateGeneralOptions() { selectBaseCurrencyNetworkComboBox.setOnAction(e -> onSelectNetwork()); selectBaseCurrencyNetworkComboBox.getSelectionModel().select(BaseCurrencyNetwork.CURRENT_VALUE);*/ - boolean useCustomWithdrawalTxFee = preferences.isUseCustomWithdrawalTxFee(); - useCustomFee.setSelected(useCustomWithdrawalTxFee); + boolean useCustomTxFee = preferences.isUseCustomTxFee(); + useCustomFee.setSelected(useCustomTxFee); - transactionFeeInputTextField.setEditable(useCustomWithdrawalTxFee); - if (!useCustomWithdrawalTxFee) { + transactionFeeInputTextField.setEditable(useCustomTxFee); + if (!useCustomTxFee) { transactionFeeInputTextField.setText(String.valueOf(feeService.getTxFeePerByte().value)); feeService.feeUpdateCounterProperty().addListener(transactionFeeChangeListener); } @@ -780,8 +780,8 @@ public BlockChainExplorer fromString(String string) { } private Coin getTxFeeForWithdrawalPerByte() { - Coin fee = (preferences.isUseCustomWithdrawalTxFee()) ? - Coin.valueOf(preferences.getWithdrawalTxFeeInBytes()) : + Coin fee = (preferences.isUseCustomTxFee()) ? + Coin.valueOf(preferences.getTxFeePerByte()) : feeService.getTxFeePerByte(); log.info("tx fee = " + fee.toFriendlyString()); return fee; diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index e1cc8b39c4c..a644d1f836c 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -1508,8 +1508,8 @@ message PreferencesPayload { bool use_tor_for_bitcoin_j = 12; bool show_own_offers_in_offer_book = 13; TradeCurrency preferred_trade_currency = 14; - int64 withdrawal_tx_fee_in_bytes = 15; - bool use_custom_withdrawal_tx_fee = 16; + int64 tx_fee_per_byte = 15; + bool use_custom_tx_fee = 16; double max_price_distance_in_percent = 17; string offer_book_chart_screen_currency_code = 18; string trade_charts_screen_currency_code = 19;