increase and decrease maximum on fee rate slider where fee rate equals or exceeds current range, set testnet fallback fee rate to 1 sat/vb

This commit is contained in:
Craig Raw 2023-11-16 16:58:24 +02:00
parent aec26d512b
commit 1d17384152
3 changed files with 56 additions and 9 deletions

View file

@ -83,8 +83,10 @@ public class AppServices {
private static final String TOR_DEFAULT_PROXY_CIRCUIT_ID = "default"; private static final String TOR_DEFAULT_PROXY_CIRCUIT_ID = "default";
public static final List<Integer> TARGET_BLOCKS_RANGE = List.of(1, 2, 3, 4, 5, 10, 25, 50); public static final List<Integer> TARGET_BLOCKS_RANGE = List.of(1, 2, 3, 4, 5, 10, 25, 50);
public static final List<Long> FEE_RATES_RANGE = List.of(1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L, 256L, 512L, 1024L); public static final List<Long> LONG_FEE_RATES_RANGE = List.of(1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L, 256L, 512L, 1024L, 2048L, 4096L, 8192L);
public static final List<Long> FEE_RATES_RANGE = LONG_FEE_RATES_RANGE.subList(0, LONG_FEE_RATES_RANGE.size() - 3);
public static final double FALLBACK_FEE_RATE = 20000d / 1000; public static final double FALLBACK_FEE_RATE = 20000d / 1000;
public static final double TESTNET_FALLBACK_FEE_RATE = 1000d / 1000;
private static AppServices INSTANCE; private static AppServices INSTANCE;
@ -660,15 +662,19 @@ public class AppServices {
public static Double getDefaultFeeRate() { public static Double getDefaultFeeRate() {
int defaultTarget = TARGET_BLOCKS_RANGE.get((TARGET_BLOCKS_RANGE.size() / 2) - 1); int defaultTarget = TARGET_BLOCKS_RANGE.get((TARGET_BLOCKS_RANGE.size() / 2) - 1);
return getTargetBlockFeeRates() == null ? FALLBACK_FEE_RATE : getTargetBlockFeeRates().get(defaultTarget); return getTargetBlockFeeRates() == null ? getFallbackFeeRate() : getTargetBlockFeeRates().get(defaultTarget);
} }
public static Double getMinimumFeeRate() { public static Double getMinimumFeeRate() {
Optional<Double> optMinFeeRate = getTargetBlockFeeRates().values().stream().min(Double::compareTo); Optional<Double> optMinFeeRate = getTargetBlockFeeRates().values().stream().min(Double::compareTo);
Double minRate = optMinFeeRate.orElse(FALLBACK_FEE_RATE); Double minRate = optMinFeeRate.orElse(getFallbackFeeRate());
return Math.max(minRate, Transaction.DUST_RELAY_TX_FEE); return Math.max(minRate, Transaction.DUST_RELAY_TX_FEE);
} }
public static double getFallbackFeeRate() {
return Network.get() == Network.MAINNET ? FALLBACK_FEE_RATE : TESTNET_FALLBACK_FEE_RATE;
}
public static Map<Integer, Double> getTargetBlockFeeRates() { public static Map<Integer, Double> getTargetBlockFeeRates() {
return targetBlockFeeRates; return targetBlockFeeRates;
} }

View file

@ -22,10 +22,14 @@ public class FeeRangeSlider extends Slider {
setShowTickMarks(true); setShowTickMarks(true);
setBlockIncrement(Math.log(1.02) / Math.log(2)); setBlockIncrement(Math.log(1.02) / Math.log(2));
setLabelFormatter(new StringConverter<Double>() { setLabelFormatter(new StringConverter<>() {
@Override @Override
public String toString(Double object) { public String toString(Double object) {
return Long.toString(FEE_RATES_RANGE.get(object.intValue())); Long feeRate = LONG_FEE_RATES_RANGE.get(object.intValue());
if(isLongFeeRange() && feeRate >= 1000) {
return feeRate / 1000 + "k";
}
return Long.toString(feeRate);
} }
@Override @Override
@ -35,6 +39,12 @@ public class FeeRangeSlider extends Slider {
}); });
updateTrackHighlight(); updateTrackHighlight();
valueProperty().addListener((observable, oldValue, newValue) -> {
if(newValue != null) {
updateMaxFeeRange(newValue.doubleValue());
}
});
} }
public double getFeeRate() { public double getFeeRate() {
@ -42,7 +52,23 @@ public class FeeRangeSlider extends Slider {
} }
public void setFeeRate(double feeRate) { public void setFeeRate(double feeRate) {
setValue(Math.log(feeRate) / Math.log(2)); double value = Math.log(feeRate) / Math.log(2);
updateMaxFeeRange(value);
setValue(value);
}
private void updateMaxFeeRange(double value) {
if(value >= getMax() && !isLongFeeRange()) {
setMax(LONG_FEE_RATES_RANGE.size() - 1);
updateTrackHighlight();
} else if(value == getMin() && isLongFeeRange()) {
setMax(FEE_RATES_RANGE.size() - 1);
updateTrackHighlight();
}
}
private boolean isLongFeeRange() {
return getMax() > FEE_RATES_RANGE.size() - 1;
} }
public void updateTrackHighlight() { public void updateTrackHighlight() {
@ -76,7 +102,7 @@ public class FeeRangeSlider extends Slider {
private Map<Integer, Double> getTargetBlocksFeeRates() { private Map<Integer, Double> getTargetBlocksFeeRates() {
Map<Integer, Double> retrievedFeeRates = AppServices.getTargetBlockFeeRates(); Map<Integer, Double> retrievedFeeRates = AppServices.getTargetBlockFeeRates();
if(retrievedFeeRates == null) { if(retrievedFeeRates == null) {
retrievedFeeRates = TARGET_BLOCKS_RANGE.stream().collect(Collectors.toMap(java.util.function.Function.identity(), v -> FALLBACK_FEE_RATE, retrievedFeeRates = TARGET_BLOCKS_RANGE.stream().collect(Collectors.toMap(java.util.function.Function.identity(), v -> getFallbackFeeRate(),
(u, v) -> { throw new IllegalStateException("Duplicate target blocks"); }, (u, v) -> { throw new IllegalStateException("Duplicate target blocks"); },
LinkedHashMap::new)); LinkedHashMap::new));
} }
@ -98,6 +124,9 @@ public class FeeRangeSlider extends Slider {
private int getPercentageOfFeeRange(Double feeRate) { private int getPercentageOfFeeRange(Double feeRate) {
double index = Math.log(feeRate) / Math.log(2); double index = Math.log(feeRate) / Math.log(2);
if(isLongFeeRange()) {
index *= ((double)FEE_RATES_RANGE.size() / (LONG_FEE_RATES_RANGE.size())) * 0.99;
}
return (int)Math.round(index * 10.0); return (int)Math.round(index * 10.0);
} }
} }

View file

@ -4,6 +4,7 @@ import com.google.common.eventbus.Subscribe;
import com.samourai.whirlpool.client.whirlpool.beans.Pool; import com.samourai.whirlpool.client.whirlpool.beans.Pool;
import com.sparrowwallet.drongo.BitcoinUnit; import com.sparrowwallet.drongo.BitcoinUnit;
import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.KeyPurpose;
import com.sparrowwallet.drongo.Network;
import com.sparrowwallet.drongo.SecureString; import com.sparrowwallet.drongo.SecureString;
import com.sparrowwallet.drongo.address.Address; import com.sparrowwallet.drongo.address.Address;
import com.sparrowwallet.drongo.address.InvalidAddressException; import com.sparrowwallet.drongo.address.InvalidAddressException;
@ -243,6 +244,8 @@ public class SendController extends WalletFormController implements Initializabl
private boolean overrideOptimizationStrategy; private boolean overrideOptimizationStrategy;
private boolean updateDefaultFeeRate;
@Override @Override
public void initialize(URL location, ResourceBundle resources) { public void initialize(URL location, ResourceBundle resources) {
EventManager.get().register(this); EventManager.get().register(this);
@ -757,6 +760,10 @@ public class SendController extends WalletFormController implements Initializabl
blockTargetFeeRatesChart.select(defaultTarget); blockTargetFeeRatesChart.select(defaultTarget);
setFeeRangeRate(defaultRate); setFeeRangeRate(defaultRate);
setFeeRate(getFeeRangeRate()); setFeeRate(getFeeRangeRate());
if(Network.get().equals(Network.MAINNET) && defaultRate == getFallbackFeeRate()) {
//Update the selected fee rate once fee rates have been received
updateDefaultFeeRate = true;
}
} }
private Long getFeeValueSats() { private Long getFeeValueSats() {
@ -821,7 +828,7 @@ public class SendController extends WalletFormController implements Initializabl
private Map<Integer, Double> getTargetBlocksFeeRates() { private Map<Integer, Double> getTargetBlocksFeeRates() {
Map<Integer, Double> retrievedFeeRates = AppServices.getTargetBlockFeeRates(); Map<Integer, Double> retrievedFeeRates = AppServices.getTargetBlockFeeRates();
if(retrievedFeeRates == null) { if(retrievedFeeRates == null) {
retrievedFeeRates = TARGET_BLOCKS_RANGE.stream().collect(Collectors.toMap(java.util.function.Function.identity(), v -> FALLBACK_FEE_RATE, retrievedFeeRates = TARGET_BLOCKS_RANGE.stream().collect(Collectors.toMap(java.util.function.Function.identity(), v -> getFallbackFeeRate(),
(u, v) -> { throw new IllegalStateException("Duplicate target blocks"); }, (u, v) -> { throw new IllegalStateException("Duplicate target blocks"); },
LinkedHashMap::new)); LinkedHashMap::new));
} }
@ -860,7 +867,7 @@ public class SendController extends WalletFormController implements Initializabl
private Double getMinimumFeeRate() { private Double getMinimumFeeRate() {
Optional<Double> optMinFeeRate = getTargetBlocksFeeRates().values().stream().min(Double::compareTo); Optional<Double> optMinFeeRate = getTargetBlocksFeeRates().values().stream().min(Double::compareTo);
Double minRate = optMinFeeRate.orElse(FALLBACK_FEE_RATE); Double minRate = optMinFeeRate.orElse(getFallbackFeeRate());
return Math.max(minRate, Transaction.DUST_RELAY_TX_FEE); return Math.max(minRate, Transaction.DUST_RELAY_TX_FEE);
} }
@ -1451,6 +1458,11 @@ public class SendController extends WalletFormController implements Initializabl
setFeeRatePriority(getFeeRangeRate()); setFeeRatePriority(getFeeRangeRate());
} }
feeRange.updateTrackHighlight(); feeRange.updateTrackHighlight();
if(updateDefaultFeeRate) {
setDefaultFeeRate();
updateDefaultFeeRate = false;
}
} }
@Subscribe @Subscribe