Merge pull request #5312 from BtcContributor/sendcustomfee

Add custom withdrawal transaction fee options on Send funds (BTC)
This commit is contained in:
Christoph Atteneder 2021-04-20 09:26:30 +02:00 committed by GitHub
commit fbd7c9fbee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 12 deletions

View File

@ -1031,6 +1031,11 @@ funds.withdrawal.fillDestAddress=Fill in your destination address
funds.withdrawal.warn.noSourceAddressSelected=You need to select a source address in the table above.
funds.withdrawal.warn.amountExceeds=You don't have sufficient funds available from the selected address.\n\
Consider to select multiple addresses in the table above or change the fee toggle to include the miner fee.
funds.withdrawal.txFee=Withdrawal transaction fee (satoshis/vbyte)
funds.withdrawal.useCustomFeeValueInfo=Insert a custom transaction fee value
funds.withdrawal.useCustomFeeValue=Use custom value
funds.withdrawal.txFeeMin=Transaction fee must be at least {0} satoshis/vbyte
funds.withdrawal.txFeeTooLarge=Your input is above any reasonable value (>5000 satoshis/vbyte). Transaction fee is usually in the range of 50-400 satoshis/vbyte.
funds.reserved.noFunds=No funds are reserved in open offers
funds.reserved.reserved=Reserved in local wallet for offer with ID: {0}
@ -1204,10 +1209,8 @@ setting.preferences.autoConfirmRequiredConfirmations=Required confirmations
setting.preferences.autoConfirmMaxTradeSize=Max. trade amount (BTC)
setting.preferences.autoConfirmServiceAddresses=Monero Explorer URLs (uses Tor, except for localhost, LAN IP addresses, and *.local hostnames)
setting.preferences.deviationToLarge=Values higher than {0}% are not allowed.
setting.preferences.txFee=Withdrawal transaction fee (satoshis/vbyte)
setting.preferences.txFee=BSQ Withdrawal transaction fee (satoshis/vbyte)
setting.preferences.useCustomValue=Use custom value
setting.preferences.txFeeMin=Transaction fee must be at least {0} satoshis/vbyte
setting.preferences.txFeeTooLarge=Your input is above any reasonable value (>5000 satoshis/vbyte). Transaction fee is usually in the range of 50-400 satoshis/vbyte.
setting.preferences.ignorePeers=Ignored peers [onion address:port]
setting.preferences.ignoreDustThreshold=Min. non-dust output value
setting.preferences.currenciesInList=Currencies in market price feed list

View File

@ -23,6 +23,7 @@ import bisq.desktop.components.AutoTooltipCheckBox;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.ExternalHyperlink;
import bisq.desktop.components.HyperlinkWithIcon;
import bisq.desktop.components.InputTextField;
import bisq.desktop.components.TitledGroupBg;
import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.main.overlays.windows.TxDetails;
@ -38,6 +39,7 @@ import bisq.core.btc.setup.WalletsSetup;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.locale.Res;
import bisq.core.provider.fee.FeeService;
import bisq.core.trade.Trade;
import bisq.core.trade.TradeManager;
import bisq.core.user.DontShowAgainLookup;
@ -45,7 +47,6 @@ import bisq.core.user.Preferences;
import bisq.core.util.FormattingUtils;
import bisq.core.util.ParsingUtils;
import bisq.core.util.coin.CoinFormatter;
import bisq.core.util.coin.CoinUtil;
import bisq.core.util.validation.BtcAddressValidator;
import bisq.network.p2p.P2PService;
@ -79,6 +80,7 @@ import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
@ -124,7 +126,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
private RadioButton useAllInputsRadioButton, useCustomInputsRadioButton, feeExcludedRadioButton, feeIncludedRadioButton;
private Label amountLabel;
private TextField amountTextField, withdrawFromTextField, withdrawToTextField, withdrawMemoTextField;
private TextField amountTextField, withdrawFromTextField, withdrawToTextField, withdrawMemoTextField, transactionFeeInputTextField;
private final BtcWalletService btcWalletService;
private final TradeManager tradeManager;
@ -142,12 +144,15 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
private Coin totalAvailableAmountOfSelectedItems = Coin.ZERO;
private Coin amountAsCoin = Coin.ZERO;
private ChangeListener<String> amountListener;
private ChangeListener<Boolean> amountFocusListener;
private ChangeListener<Boolean> amountFocusListener, useCustomFeeCheckboxListener, transactionFeeFocusedListener;
private ChangeListener<Toggle> feeToggleGroupListener, inputsToggleGroupListener;
private ChangeListener<Number> transactionFeeChangeListener;
private ToggleGroup feeToggleGroup, inputsToggleGroup;
private ToggleButton useCustomFee;
private final BooleanProperty useAllInputs = new SimpleBooleanProperty(true);
private boolean feeExcluded;
private int rowIndex = 0;
private final FeeService feeService;
///////////////////////////////////////////////////////////////////////////////////////////
@ -162,7 +167,8 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter,
Preferences preferences,
BtcAddressValidator btcAddressValidator,
WalletPasswordWindow walletPasswordWindow) {
WalletPasswordWindow walletPasswordWindow,
FeeService feeService) {
this.btcWalletService = btcWalletService;
this.tradeManager = tradeManager;
this.p2PService = p2PService;
@ -171,6 +177,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
this.preferences = preferences;
this.btcAddressValidator = btcAddressValidator;
this.walletPasswordWindow = walletPasswordWindow;
this.feeService = feeService;
}
@Override
@ -220,6 +227,52 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
withdrawMemoTextField = addTopLabelInputTextField(gridPane, ++rowIndex,
Res.get("funds.withdrawal.memoLabel", Res.getBaseCurrencyCode())).second;
Tuple3<Label, InputTextField, ToggleButton> customFeeTuple = addTopLabelInputTextFieldSlideToggleButton(gridPane, ++rowIndex,
Res.get("funds.withdrawal.txFee"), Res.get("funds.withdrawal.useCustomFeeValue"));
transactionFeeInputTextField = customFeeTuple.second;
useCustomFee = customFeeTuple.third;
useCustomFeeCheckboxListener = (observable, oldValue, newValue) -> {
transactionFeeInputTextField.setEditable(newValue);
if (!newValue) {
try {
transactionFeeInputTextField.setText(String.valueOf(feeService.getTxFeePerVbyte().value));
} catch (Exception e) {
e.printStackTrace();
}
}
};
transactionFeeFocusedListener = (o, oldValue, newValue) -> {
if (oldValue && !newValue) {
String estimatedFee = String.valueOf(feeService.getTxFeePerVbyte().value);
try {
int withdrawalTxFeePerVbyte = Integer.parseInt(transactionFeeInputTextField.getText());
final long minFeePerVbyte = feeService.getMinFeePerVByte();
if (withdrawalTxFeePerVbyte < minFeePerVbyte) {
new Popup().warning(Res.get("funds.withdrawal.txFeeMin", minFeePerVbyte)).show();
transactionFeeInputTextField.setText(estimatedFee);
} else if (withdrawalTxFeePerVbyte > 5000) {
new Popup().warning(Res.get("funds.withdrawal.txFeeTooLarge")).show();
transactionFeeInputTextField.setText(estimatedFee);
} else {
preferences.setWithdrawalTxFeeInVbytes(withdrawalTxFeePerVbyte);
}
} catch (NumberFormatException t) {
log.error(t.toString());
t.printStackTrace();
new Popup().warning(Res.get("validation.integerOnly")).show();
transactionFeeInputTextField.setText(estimatedFee);
} catch (Throwable t) {
log.error(t.toString());
t.printStackTrace();
new Popup().warning(Res.get("validation.inputError", t.getMessage())).show();
transactionFeeInputTextField.setText(estimatedFee);
}
}
};
transactionFeeChangeListener = (observable, oldValue, newValue) -> transactionFeeInputTextField.setText(String.valueOf(feeService.getTxFeePerVbyte().value));
final Button withdrawButton = addButton(gridPane, ++rowIndex, Res.get("funds.withdrawal.withdrawButton"), 15);
withdrawButton.setOnAction(event -> onWithdraw());
@ -303,6 +356,13 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
if (inputsToggleGroup.getSelectedToggle() == null)
inputsToggleGroup.selectToggle(useAllInputsRadioButton);
useCustomFee.setSelected(false);
transactionFeeInputTextField.setEditable(false);
transactionFeeInputTextField.setText(String.valueOf(feeService.getTxFeePerVbyte().value));
feeService.feeUpdateCounterProperty().addListener(transactionFeeChangeListener);
useCustomFee.selectedProperty().addListener(useCustomFeeCheckboxListener);
transactionFeeInputTextField.focusedProperty().addListener(transactionFeeFocusedListener);
updateInputSelection();
GUIUtil.requestFocus(withdrawToTextField);
}
@ -316,6 +376,10 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
amountTextField.focusedProperty().removeListener(amountFocusListener);
feeToggleGroup.selectedToggleProperty().removeListener(feeToggleGroupListener);
inputsToggleGroup.selectedToggleProperty().removeListener(inputsToggleGroupListener);
transactionFeeInputTextField.focusedProperty().removeListener(transactionFeeFocusedListener);
if (transactionFeeChangeListener != null)
feeService.feeUpdateCounterProperty().removeListener(transactionFeeChangeListener);
useCustomFee.selectedProperty().removeListener(useCustomFeeCheckboxListener);
}
@ -362,7 +426,6 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
log.info("Fee for tx with size {}: {} " + Res.getBaseCurrencyCode() + "", txVsize, fee.toPlainString());
if (receiverAmount.isPositive()) {
double feePerVbyte = CoinUtil.getFeePerVbyte(fee, txVsize);
double vkb = txVsize / 1000d;
String messageText = Res.get("shared.sendFundsDetailsWithFee",
@ -370,7 +433,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
withdrawFromTextField.getText(),
withdrawToAddress,
formatter.formatCoinWithCode(fee),
feePerVbyte,
Double.parseDouble(transactionFeeInputTextField.getText()),
vkb,
formatter.formatCoinWithCode(receiverAmount));
if (dust.isPositive()) {
@ -550,6 +613,9 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
withdrawMemoTextField.setText("");
withdrawMemoTextField.setPromptText(Res.get("funds.withdrawal.memo"));
transactionFeeInputTextField.setText("");
transactionFeeInputTextField.setPromptText(Res.get("funds.withdrawal.useCustomFeeValueInfo"));
selectedItems.clear();
tableView.getSelectionModel().clearSelection();
}

View File

@ -131,8 +131,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private PasswordTextField rpcPwTextField;
private TitledGroupBg daoOptionsTitledGroupBg;
private ChangeListener<Boolean> transactionFeeFocusedListener;
private ChangeListener<Boolean> autoConfServiceAddressFocusOutListener, autoConfRequiredConfirmationsFocusOutListener;
private ChangeListener<Boolean> transactionFeeFocusedListener, autoConfServiceAddressFocusOutListener, autoConfRequiredConfirmationsFocusOutListener;
private final Preferences preferences;
private final FeeService feeService;
//private final ReferralIdService referralIdService;
@ -808,7 +807,6 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
transactionFeeInputTextField.setText(String.valueOf(feeService.getTxFeePerVbyte().value));
feeService.feeUpdateCounterProperty().addListener(transactionFeeChangeListener);
}
transactionFeeInputTextField.setText(String.valueOf(getTxFeeForWithdrawalPerVbyte()));
ignoreTradersListInputTextField.setText(String.join(", ", preferences.getIgnoreTradersList()));
/* referralIdService.getOptionalReferralId().ifPresent(referralId -> referralIdInputTextField.setText(referralId));