Clear account payload info & chats from closed trades & disputes.

This commit is contained in:
jmacxx 2022-01-28 00:03:13 -06:00
parent 44b02b3cbb
commit 57821b7474
No known key found for this signature in database
GPG Key ID: 155297BABFE94A1B
15 changed files with 193 additions and 6 deletions

View File

@ -100,7 +100,7 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
private final PubKeyRing traderPubKeyRing; private final PubKeyRing traderPubKeyRing;
private final long tradeDate; private final long tradeDate;
private final long tradePeriodEnd; private final long tradePeriodEnd;
private final Contract contract; private Contract contract;
@Nullable @Nullable
private final byte[] contractHash; private final byte[] contractHash;
@Nullable @Nullable
@ -111,7 +111,7 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
private final String depositTxId; private final String depositTxId;
@Nullable @Nullable
private final String payoutTxId; private final String payoutTxId;
private final String contractAsJson; private String contractAsJson;
@Nullable @Nullable
private final String makerContractSignature; private final String makerContractSignature;
@Nullable @Nullable
@ -351,6 +351,31 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
} }
} }
public boolean removeAllChatMessages() {
if (chatMessages.size() > 0) {
chatMessages.clear();
return true;
}
return false;
}
public void maybeClearSensitiveData() {
String change = "";
if (contract.maybeClearSensitiveData()) {
change += "contract;";
}
String edited = contract.sanitizeContractAsJson(contractAsJson);
if (!edited.equals(contractAsJson)) {
contractAsJson = edited;
change += "contractAsJson;";
}
if (removeAllChatMessages()) {
change += "chat messages;";
}
if (change.length() > 0) {
log.info("cleared sensitive data from {} of dispute for trade {}", change, Utilities.getShortId(getTradeId()));
}
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Setters // Setters

View File

@ -66,6 +66,8 @@ import javafx.collections.ObservableList;
import java.security.KeyPair; import java.security.KeyPair;
import java.time.Instant;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -282,6 +284,8 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
log.error(disputeReplayException.toString()); log.error(disputeReplayException.toString());
validationExceptions.add(disputeReplayException); validationExceptions.add(disputeReplayException);
}); });
maybeClearSensitiveData();
} }
public boolean isTrader(Dispute dispute) { public boolean isTrader(Dispute dispute) {
@ -298,6 +302,15 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
return disputeList.stream().filter(e -> e.getTradeId().equals(tradeId)).findAny(); return disputeList.stream().filter(e -> e.getTradeId().equals(tradeId)).findAny();
} }
public void maybeClearSensitiveData() {
log.info("{} checking closed disputes eligibility for having sensitive data cleared", super.getClass().getSimpleName());
Instant safeDate = closedTradableManager.getSafeDateForSensitiveDataClearing();
getDisputeList().getList().stream()
.filter(e -> e.isClosed())
.filter(e -> e.getTradeDate().toInstant().isBefore(safeDate))
.forEach(Dispute::maybeClearSensitiveData);
requestPersistence();
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Message handler // Message handler

View File

@ -338,6 +338,7 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
sendAckMessage(chatMessage, dispute.getAgentPubKeyRing(), success, errorMessage); sendAckMessage(chatMessage, dispute.getAgentPubKeyRing(), success, errorMessage);
} }
maybeClearSensitiveData();
requestPersistence(); requestPersistence();
} }

View File

@ -223,6 +223,7 @@ public final class MediationManager extends DisputeManager<MediationDisputeList>
} }
sendAckMessage(chatMessage, dispute.getAgentPubKeyRing(), true, null); sendAckMessage(chatMessage, dispute.getAgentPubKeyRing(), true, null);
maybeClearSensitiveData();
requestPersistence(); requestPersistence();
} }

View File

@ -224,6 +224,7 @@ public final class RefundManager extends DisputeManager<RefundDisputeList> {
openOfferOptional.ifPresent(openOffer -> openOfferManager.closeOpenOffer(openOffer.getOffer())); openOfferOptional.ifPresent(openOffer -> openOfferManager.closeOpenOffer(openOffer.getOffer()));
} }
maybeClearSensitiveData();
requestPersistence(); requestPersistence();
} }

View File

@ -49,9 +49,12 @@ import com.google.common.collect.ImmutableList;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import java.time.Instant;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -120,10 +123,12 @@ public class ClosedTradableManager implements PersistedDataHost {
public void onAllServicesInitialized() { public void onAllServicesInitialized() {
cleanupMailboxMessagesService.handleTrades(getClosedTrades()); cleanupMailboxMessagesService.handleTrades(getClosedTrades());
maybeClearSensitiveData();
} }
public void add(Tradable tradable) { public void add(Tradable tradable) {
if (closedTradables.add(tradable)) { if (closedTradables.add(tradable)) {
maybeClearSensitiveData();
requestPersistence(); requestPersistence();
} }
} }
@ -153,6 +158,29 @@ public class ClosedTradableManager implements PersistedDataHost {
return closedTradables.stream().filter(e -> e.getId().equals(id)).findFirst(); return closedTradables.stream().filter(e -> e.getId().equals(id)).findFirst();
} }
public void maybeClearSensitiveData() {
log.info("checking closed trades eligibility for having sensitive data cleared");
closedTradables.stream()
.filter(e -> e instanceof Trade)
.map(e -> (Trade) e)
.filter(e -> canTradeHaveSensitiveDataCleared(e.getId()))
.forEach(Trade::maybeClearSensitiveData);
requestPersistence();
}
public boolean canTradeHaveSensitiveDataCleared(String tradeId) {
Instant safeDate = getSafeDateForSensitiveDataClearing();
return closedTradables.stream()
.filter(e -> e.getId().equals(tradeId))
.filter(e -> e.getDate().toInstant().isBefore(safeDate))
.count() > 0;
}
public Instant getSafeDateForSensitiveDataClearing() {
return Instant.ofEpochSecond(Instant.now().getEpochSecond()
- TimeUnit.DAYS.toSeconds(preferences.getClearDataAfterDays()));
}
public Stream<Trade> getTradesStreamWithFundsLockedIn() { public Stream<Trade> getTradesStreamWithFundsLockedIn() {
return getClosedTrades().stream() return getClosedTrades().stream()
.filter(Trade::isFundsLockedIn); .filter(Trade::isFundsLockedIn);

View File

@ -350,6 +350,30 @@ public final class Contract implements NetworkPayload {
return isBuyerMakerAndSellerTaker() == isMyRoleBuyer(myPubKeyRing); return isBuyerMakerAndSellerTaker() == isMyRoleBuyer(myPubKeyRing);
} }
public boolean maybeClearSensitiveData() {
boolean changed = false;
if (makerPaymentAccountPayload != null) {
makerPaymentAccountPayload = null;
changed = true;
}
if (takerPaymentAccountPayload != null) {
takerPaymentAccountPayload = null;
changed = true;
}
return changed;
}
// edits a contract json string, removing the payment account payloads
public static String sanitizeContractAsJson(String contractAsJson) {
return contractAsJson
.replaceAll(
"\"takerPaymentAccountPayload\": \\{[^}]*}",
"\"takerPaymentAccountPayload\": null")
.replaceAll(
"\"makerPaymentAccountPayload\": \\{[^}]*}",
"\"makerPaymentAccountPayload\": null");
}
public void printDiff(@Nullable String peersContractAsJson) { public void printDiff(@Nullable String peersContractAsJson) {
String json = JsonUtil.objectToJson(this); String json = JsonUtil.objectToJson(this);
String diff = StringUtils.difference(json, peersContractAsJson); String diff = StringUtils.difference(json, peersContractAsJson);

View File

@ -689,6 +689,14 @@ public abstract class Trade extends TradeModel {
} }
} }
public boolean removeAllChatMessages() {
if (chatMessages.size() > 0) {
chatMessages.clear();
return true;
}
return false;
}
public boolean mediationResultAppliedPenaltyToSeller() { public boolean mediationResultAppliedPenaltyToSeller() {
// If mediated payout is same or more then normal payout we enable otherwise a penalty was applied // If mediated payout is same or more then normal payout we enable otherwise a penalty was applied
// by mediators and we keep the confirm disabled to avoid that the seller can complete the trade // by mediators and we keep the confirm disabled to avoid that the seller can complete the trade
@ -698,6 +706,26 @@ public abstract class Trade extends TradeModel {
return payoutAmountFromMediation < normalPayoutAmount; return payoutAmountFromMediation < normalPayoutAmount;
} }
public void maybeClearSensitiveData() {
String change = "";
if (contract != null && contract.maybeClearSensitiveData()) {
change += "contract;";
}
if (contractAsJson != null) {
String edited = contract.sanitizeContractAsJson(contractAsJson);
if (!edited.equals(contractAsJson)) {
contractAsJson = edited;
change += "contractAsJson;";
}
}
if (removeAllChatMessages()) {
change += "chat messages;";
}
if (change.length() > 0) {
log.info("cleared sensitive data from {} of trade {}", change, getShortId());
}
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// TradeModel implementation // TradeModel implementation

View File

@ -145,7 +145,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
)); ));
public static final boolean USE_SYMMETRIC_SECURITY_DEPOSIT = true; public static final boolean USE_SYMMETRIC_SECURITY_DEPOSIT = true;
public static final int CLEAR_DATA_AFTER_DAYS_INITIAL = 99999; // feature effectively disabled until user agrees to settings notification
public static final int CLEAR_DATA_AFTER_DAYS_DEFAULT = 20; // used when user has agreed to settings notification
// payload is initialized so the default values are available for Property initialization. // payload is initialized so the default values are available for Property initialization.
@Setter @Setter
@ -355,6 +356,10 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
setIgnoreDustThreshold(600); setIgnoreDustThreshold(600);
} }
if (prefPayload.getClearDataAfterDays() < 1) {
setClearDataAfterDays(Preferences.CLEAR_DATA_AFTER_DAYS_INITIAL);
}
// For users from old versions the 4 flags a false but we want to have it true by default // For users from old versions the 4 flags a false but we want to have it true by default
// PhoneKeyAndToken is also null so we can use that to enable the flags // PhoneKeyAndToken is also null so we can use that to enable the flags
if (prefPayload.getPhoneKeyAndToken() == null) { if (prefPayload.getPhoneKeyAndToken() == null) {
@ -785,6 +790,11 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
requestPersistence(); requestPersistence();
} }
public void setClearDataAfterDays(int value) {
prefPayload.setClearDataAfterDays(value);
requestPersistence();
}
public void setShowOffersMatchingMyAccounts(boolean value) { public void setShowOffersMatchingMyAccounts(boolean value) {
prefPayload.setShowOffersMatchingMyAccounts(value); prefPayload.setShowOffersMatchingMyAccounts(value);
requestPersistence(); requestPersistence();

View File

@ -121,6 +121,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
private String takeOfferSelectedPaymentAccountId; private String takeOfferSelectedPaymentAccountId;
private double buyerSecurityDepositAsPercent = getDefaultBuyerSecurityDepositAsPercent(); private double buyerSecurityDepositAsPercent = getDefaultBuyerSecurityDepositAsPercent();
private int ignoreDustThreshold = 600; private int ignoreDustThreshold = 600;
private int clearDataAfterDays = Preferences.CLEAR_DATA_AFTER_DAYS_INITIAL;
private double buyerSecurityDepositAsPercentForCrypto = getDefaultBuyerSecurityDepositAsPercent(); private double buyerSecurityDepositAsPercentForCrypto = getDefaultBuyerSecurityDepositAsPercent();
private int blockNotifyPort; private int blockNotifyPort;
private boolean tacAcceptedV120; private boolean tacAcceptedV120;
@ -192,6 +193,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
.setIsDaoFullNode(isDaoFullNode) .setIsDaoFullNode(isDaoFullNode)
.setBuyerSecurityDepositAsPercent(buyerSecurityDepositAsPercent) .setBuyerSecurityDepositAsPercent(buyerSecurityDepositAsPercent)
.setIgnoreDustThreshold(ignoreDustThreshold) .setIgnoreDustThreshold(ignoreDustThreshold)
.setClearDataAfterDays(clearDataAfterDays)
.setBuyerSecurityDepositAsPercentForCrypto(buyerSecurityDepositAsPercentForCrypto) .setBuyerSecurityDepositAsPercentForCrypto(buyerSecurityDepositAsPercentForCrypto)
.setBlockNotifyPort(blockNotifyPort) .setBlockNotifyPort(blockNotifyPort)
.setTacAcceptedV120(tacAcceptedV120) .setTacAcceptedV120(tacAcceptedV120)
@ -290,6 +292,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
proto.getTakeOfferSelectedPaymentAccountId().isEmpty() ? null : proto.getTakeOfferSelectedPaymentAccountId(), proto.getTakeOfferSelectedPaymentAccountId().isEmpty() ? null : proto.getTakeOfferSelectedPaymentAccountId(),
proto.getBuyerSecurityDepositAsPercent(), proto.getBuyerSecurityDepositAsPercent(),
proto.getIgnoreDustThreshold(), proto.getIgnoreDustThreshold(),
proto.getClearDataAfterDays(),
proto.getBuyerSecurityDepositAsPercentForCrypto(), proto.getBuyerSecurityDepositAsPercentForCrypto(),
proto.getBlockNotifyPort(), proto.getBlockNotifyPort(),
proto.getTacAcceptedV120(), proto.getTacAcceptedV120(),

View File

@ -1324,6 +1324,7 @@ 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.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.ignorePeers=Ignored peers [onion address:port]
setting.preferences.ignoreDustThreshold=Min. non-dust output value setting.preferences.ignoreDustThreshold=Min. non-dust output value
setting.preferences.clearDataAfterDays=Clear sensitive data after (days)
setting.preferences.currenciesInList=Currencies in market price feed list setting.preferences.currenciesInList=Currencies in market price feed list
setting.preferences.prefCurrency=Preferred currency setting.preferences.prefCurrency=Preferred currency
setting.preferences.displayFiat=Display national currencies setting.preferences.displayFiat=Display national currencies
@ -1386,6 +1387,15 @@ settings.preferences.editCustomExplorer.name=Name
settings.preferences.editCustomExplorer.txUrl=Transaction URL settings.preferences.editCustomExplorer.txUrl=Transaction URL
settings.preferences.editCustomExplorer.addressUrl=Address URL settings.preferences.editCustomExplorer.addressUrl=Address URL
setting.info.headline=New data-privacy feature
settings.preferences.sensitiveDataRemoval.msg=To protect the privacy of yourself and other traders, Bisq intends to \
remove payment account details from old trades. This is particularly important for fiat trades which may include bank \
account details. Read more about this at [HYPERLINK:https://bisq.wiki/Data_Privacy].\n\n\
The threshold for data removal can be configured on this screen via the field "Clear sensitive data after (days)". \
It is recommended to set it as low as possible, for example 20 days. That means trades from more than 20 \
days ago will have payment account details cleared, as long as they are finished. Finished trades are ones which \
are found in the Portfolio / History tab.
settings.net.btcHeader=Bitcoin network settings.net.btcHeader=Bitcoin network
settings.net.p2pHeader=Bisq network settings.net.p2pHeader=Bisq network
settings.net.onionAddressLabel=My onion address settings.net.onionAddressLabel=My onion address

View File

@ -58,5 +58,6 @@ public class SettingsPresentation {
} }
public void setup() { public void setup() {
showNotification.set(preferences.showAgain(SETTINGS_NEWS));
} }
} }

View File

@ -24,11 +24,14 @@ import bisq.desktop.common.view.FxmlView;
import bisq.desktop.common.view.View; import bisq.desktop.common.view.View;
import bisq.desktop.common.view.ViewLoader; import bisq.desktop.common.view.ViewLoader;
import bisq.desktop.main.MainView; import bisq.desktop.main.MainView;
import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.main.presentation.SettingsPresentation;
import bisq.desktop.main.settings.about.AboutView; import bisq.desktop.main.settings.about.AboutView;
import bisq.desktop.main.settings.network.NetworkSettingsView; import bisq.desktop.main.settings.network.NetworkSettingsView;
import bisq.desktop.main.settings.preferences.PreferencesView; import bisq.desktop.main.settings.preferences.PreferencesView;
import bisq.core.locale.Res; import bisq.core.locale.Res;
import bisq.core.user.DontShowAgainLookup;
import bisq.core.user.Preferences; import bisq.core.user.Preferences;
import javax.inject.Inject; import javax.inject.Inject;
@ -85,6 +88,9 @@ public class SettingsView extends ActivatableView<TabPane, Void> {
@Override @Override
protected void activate() { protected void activate() {
// Hide new badge if user saw this section
preferences.dontShowAgain(SettingsPresentation.SETTINGS_NEWS, true);
root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener); root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
navigation.addListener(navigationListener); navigation.addListener(navigationListener);

View File

@ -127,7 +127,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private int gridRow = 0; private int gridRow = 0;
private int displayCurrenciesGridRowIndex = 0; private int displayCurrenciesGridRowIndex = 0;
private InputTextField transactionFeeInputTextField, ignoreTradersListInputTextField, ignoreDustThresholdInputTextField, private InputTextField transactionFeeInputTextField, ignoreTradersListInputTextField, ignoreDustThresholdInputTextField,
autoConfRequiredConfirmationsTf, autoConfServiceAddressTf, autoConfTradeLimitTf, autoConfRequiredConfirmationsTf, autoConfServiceAddressTf, autoConfTradeLimitTf, clearDataAfterDaysInputTextField,
rpcUserTextField, blockNotifyPortTextField; rpcUserTextField, blockNotifyPortTextField;
private PasswordTextField rpcPwTextField; private PasswordTextField rpcPwTextField;
private TitledGroupBg daoOptionsTitledGroupBg; private TitledGroupBg daoOptionsTitledGroupBg;
@ -156,7 +156,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private ObservableList<TradeCurrency> tradeCurrencies; private ObservableList<TradeCurrency> tradeCurrencies;
private InputTextField deviationInputTextField, bsqAverageTrimThresholdTextField; private InputTextField deviationInputTextField, bsqAverageTrimThresholdTextField;
private ChangeListener<String> deviationListener, bsqAverageTrimThresholdListener, ignoreTradersListListener, ignoreDustThresholdListener, private ChangeListener<String> deviationListener, bsqAverageTrimThresholdListener, ignoreTradersListListener, ignoreDustThresholdListener,
rpcUserListener, rpcPwListener, blockNotifyPortListener, rpcUserListener, rpcPwListener, blockNotifyPortListener, clearDataAfterDaysListener,
autoConfTradeLimitListener, autoConfServiceAddressListener; autoConfTradeLimitListener, autoConfServiceAddressListener;
private ChangeListener<Boolean> deviationFocusedListener, bsqAverageTrimThresholdFocusedListener; private ChangeListener<Boolean> deviationFocusedListener, bsqAverageTrimThresholdFocusedListener;
private ChangeListener<Boolean> useCustomFeeCheckboxListener; private ChangeListener<Boolean> useCustomFeeCheckboxListener;
@ -225,6 +225,22 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
@Override @Override
protected void activate() { protected void activate() {
String key = "sensitiveDataRemovalInfo";
if (DontShowAgainLookup.showAgain(key)) {
new Popup()
.headLine(Res.get("setting.info.headline"))
.backgroundInfo(Res.get("settings.preferences.sensitiveDataRemoval.msg"))
.actionButtonText(Res.get("shared.iUnderstand"))
.onAction(() -> {
DontShowAgainLookup.dontShowAgain(key, true);
// user has acknowledged, enable the feature with a reasonable default value
preferences.setClearDataAfterDays(preferences.CLEAR_DATA_AFTER_DAYS_DEFAULT);
clearDataAfterDaysInputTextField.setText(String.valueOf(preferences.getClearDataAfterDays()));
})
.closeButtonText(Res.get("shared.cancel"))
.show();
}
// We want to have it updated in case an asset got removed // We want to have it updated in case an asset got removed
allCryptoCurrencies = FXCollections.observableArrayList(CurrencyUtil.getActiveSortedCryptoCurrencies(assetService, filterManager)); allCryptoCurrencies = FXCollections.observableArrayList(CurrencyUtil.getActiveSortedCryptoCurrencies(assetService, filterManager));
allCryptoCurrencies.removeAll(cryptoCurrencies); allCryptoCurrencies.removeAll(cryptoCurrencies);
@ -250,7 +266,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
private void initializeGeneralOptions() { private void initializeGeneralOptions() {
int titledGroupBgRowSpan = displayStandbyModeFeature ? 9 : 8; int titledGroupBgRowSpan = displayStandbyModeFeature ? 10 : 9;
TitledGroupBg titledGroupBg = addTitledGroupBg(root, gridRow, titledGroupBgRowSpan, Res.get("setting.preferences.general")); TitledGroupBg titledGroupBg = addTitledGroupBg(root, gridRow, titledGroupBgRowSpan, Res.get("setting.preferences.general"));
GridPane.setColumnSpan(titledGroupBg, 1); GridPane.setColumnSpan(titledGroupBg, 1);
@ -382,6 +398,22 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
} }
}; };
// clearDataAfterDays
clearDataAfterDaysInputTextField = addInputTextField(root, ++gridRow, Res.get("setting.preferences.clearDataAfterDays"));
IntegerValidator clearDataAfterDaysValidator = new IntegerValidator();
clearDataAfterDaysValidator.setMinValue(1);
clearDataAfterDaysValidator.setMaxValue(Preferences.CLEAR_DATA_AFTER_DAYS_INITIAL);
clearDataAfterDaysInputTextField.setValidator(clearDataAfterDaysValidator);
clearDataAfterDaysListener = (observable, oldValue, newValue) -> {
try {
int value = Integer.parseInt(newValue);
if (!newValue.equals(oldValue)) {
preferences.setClearDataAfterDays(value);
}
} catch (Throwable ignore) {
}
};
if (displayStandbyModeFeature) { if (displayStandbyModeFeature) {
// AvoidStandbyModeService feature works only on OSX & Windows // AvoidStandbyModeService feature works only on OSX & Windows
avoidStandbyMode = addSlideToggleButton(root, ++gridRow, avoidStandbyMode = addSlideToggleButton(root, ++gridRow,
@ -825,6 +857,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
/* referralIdService.getOptionalReferralId().ifPresent(referralId -> referralIdInputTextField.setText(referralId)); /* referralIdService.getOptionalReferralId().ifPresent(referralId -> referralIdInputTextField.setText(referralId));
referralIdInputTextField.setPromptText(Res.get("setting.preferences.refererId.prompt"));*/ referralIdInputTextField.setPromptText(Res.get("setting.preferences.refererId.prompt"));*/
ignoreDustThresholdInputTextField.setText(String.valueOf(preferences.getIgnoreDustThreshold())); ignoreDustThresholdInputTextField.setText(String.valueOf(preferences.getIgnoreDustThreshold()));
clearDataAfterDaysInputTextField.setText(String.valueOf(preferences.getClearDataAfterDays()));
userLanguageComboBox.setItems(languageCodes); userLanguageComboBox.setItems(languageCodes);
userLanguageComboBox.getSelectionModel().select(preferences.getUserLanguage()); userLanguageComboBox.getSelectionModel().select(preferences.getUserLanguage());
userLanguageComboBox.setConverter(new StringConverter<>() { userLanguageComboBox.setConverter(new StringConverter<>() {
@ -889,6 +922,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
useCustomFee.selectedProperty().addListener(useCustomFeeCheckboxListener); useCustomFee.selectedProperty().addListener(useCustomFeeCheckboxListener);
//referralIdInputTextField.textProperty().addListener(referralIdListener); //referralIdInputTextField.textProperty().addListener(referralIdListener);
ignoreDustThresholdInputTextField.textProperty().addListener(ignoreDustThresholdListener); ignoreDustThresholdInputTextField.textProperty().addListener(ignoreDustThresholdListener);
clearDataAfterDaysInputTextField.textProperty().addListener(clearDataAfterDaysListener);
} }
private Coin getTxFeeForWithdrawalPerVbyte() { private Coin getTxFeeForWithdrawalPerVbyte() {
@ -1165,6 +1199,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
useCustomFee.selectedProperty().removeListener(useCustomFeeCheckboxListener); useCustomFee.selectedProperty().removeListener(useCustomFeeCheckboxListener);
//referralIdInputTextField.textProperty().removeListener(referralIdListener); //referralIdInputTextField.textProperty().removeListener(referralIdListener);
ignoreDustThresholdInputTextField.textProperty().removeListener(ignoreDustThresholdListener); ignoreDustThresholdInputTextField.textProperty().removeListener(ignoreDustThresholdListener);
clearDataAfterDaysInputTextField.textProperty().removeListener(clearDataAfterDaysListener);
} }
private void deactivateDisplayCurrencies() { private void deactivateDisplayCurrencies() {

View File

@ -1999,6 +1999,7 @@ message PreferencesPayload {
bool deny_api_taker = 60; bool deny_api_taker = 60;
bool notify_on_pre_release = 61; bool notify_on_pre_release = 61;
bool use_full_mode_dao_monitor = 62; bool use_full_mode_dao_monitor = 62;
int32 clear_data_after_days = 63;
} }
message AutoConfirmSettings { message AutoConfirmSettings {