optimize initial fee rates fetching by avoiding double server fee estimate and histogram calls where possible

This commit is contained in:
Craig Raw 2024-03-28 15:36:47 +02:00
parent a805d9e036
commit 86ff7b8cf9
3 changed files with 27 additions and 18 deletions

View file

@ -294,8 +294,10 @@ public class AppServices {
EventManager.get().post(event); EventManager.get().post(event);
} }
if(event instanceof ConnectionEvent && Network.get().equals(Network.MAINNET)) { FeeRatesSource feeRatesSource = Config.get().getFeeRatesSource();
EventManager.get().post(new FeeRatesSourceChangedEvent(Config.get().getFeeRatesSource())); feeRatesSource = (feeRatesSource == null ? FeeRatesSource.MEMPOOL_SPACE : feeRatesSource);
if(event instanceof ConnectionEvent && Network.get().equals(Network.MAINNET) && feeRatesSource.isExternal()) {
EventManager.get().post(new FeeRatesSourceChangedEvent(feeRatesSource));
} }
}); });
connectionService.setOnFailed(failEvent -> { connectionService.setOnFailed(failEvent -> {
@ -1122,7 +1124,9 @@ public class AppServices {
@Subscribe @Subscribe
public void mempoolRateSizes(MempoolRateSizesUpdatedEvent event) { public void mempoolRateSizes(MempoolRateSizesUpdatedEvent event) {
addMempoolRateSizes(event.getMempoolRateSizes()); if(event.getMempoolRateSizes() != null) {
addMempoolRateSizes(event.getMempoolRateSizes());
}
} }
@Subscribe @Subscribe

View file

@ -815,16 +815,16 @@ public class ElectrumServer {
public Map<Integer, Double> getFeeEstimates(List<Integer> targetBlocks, boolean useCached) throws ServerException { public Map<Integer, Double> getFeeEstimates(List<Integer> targetBlocks, boolean useCached) throws ServerException {
Map<Integer, Double> targetBlocksFeeRatesSats = getDefaultFeeEstimates(targetBlocks); Map<Integer, Double> targetBlocksFeeRatesSats = getDefaultFeeEstimates(targetBlocks);
if(useCached) { FeeRatesSource feeRatesSource = Config.get().getFeeRatesSource();
feeRatesSource = (feeRatesSource == null ? FeeRatesSource.MEMPOOL_SPACE : feeRatesSource);
if(!feeRatesSource.isExternal()) {
targetBlocksFeeRatesSats.putAll(feeRatesSource.getBlockTargetFeeRates(targetBlocksFeeRatesSats));
} else if(useCached) {
if(AppServices.getTargetBlockFeeRates() != null) { if(AppServices.getTargetBlockFeeRates() != null) {
targetBlocksFeeRatesSats.putAll(AppServices.getTargetBlockFeeRates()); targetBlocksFeeRatesSats.putAll(AppServices.getTargetBlockFeeRates());
} }
} else { } else if(Network.get().equals(Network.MAINNET)) {
FeeRatesSource feeRatesSource = Config.get().getFeeRatesSource(); targetBlocksFeeRatesSats.putAll(feeRatesSource.getBlockTargetFeeRates(targetBlocksFeeRatesSats));
feeRatesSource = (feeRatesSource == null ? FeeRatesSource.MEMPOOL_SPACE : feeRatesSource);
if(Network.get().equals(Network.MAINNET)) {
targetBlocksFeeRatesSats.putAll(feeRatesSource.getBlockTargetFeeRates(targetBlocksFeeRatesSats));
}
} }
return targetBlocksFeeRatesSats; return targetBlocksFeeRatesSats;
@ -1686,8 +1686,7 @@ public class ElectrumServer {
protected FeeRatesUpdatedEvent call() throws ServerException { protected FeeRatesUpdatedEvent call() throws ServerException {
ElectrumServer electrumServer = new ElectrumServer(); ElectrumServer electrumServer = new ElectrumServer();
Map<Integer, Double> blockTargetFeeRates = electrumServer.getFeeEstimates(AppServices.TARGET_BLOCKS_RANGE, false); Map<Integer, Double> blockTargetFeeRates = electrumServer.getFeeEstimates(AppServices.TARGET_BLOCKS_RANGE, false);
Set<MempoolRateSize> mempoolRateSizes = electrumServer.getMempoolRateSizes(); return new FeeRatesUpdatedEvent(blockTargetFeeRates, null);
return new FeeRatesUpdatedEvent(blockTargetFeeRates, mempoolRateSizes);
} }
}; };
} }

View file

@ -9,27 +9,27 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
public enum FeeRatesSource { public enum FeeRatesSource {
ELECTRUM_SERVER("Server") { ELECTRUM_SERVER("Server", false) {
@Override @Override
public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) { public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
}, },
MEMPOOL_SPACE("mempool.space") { MEMPOOL_SPACE("mempool.space", true) {
@Override @Override
public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) { public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) {
String url = AppServices.isUsingProxy() ? "http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/api/v1/fees/recommended" : "https://mempool.space/api/v1/fees/recommended"; String url = AppServices.isUsingProxy() ? "http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/api/v1/fees/recommended" : "https://mempool.space/api/v1/fees/recommended";
return getThreeTierFeeRates(this, defaultblockTargetFeeRates, url); return getThreeTierFeeRates(this, defaultblockTargetFeeRates, url);
} }
}, },
BITCOINFEES_EARN_COM("bitcoinfees.earn.com") { BITCOINFEES_EARN_COM("bitcoinfees.earn.com", true) {
@Override @Override
public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) { public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) {
String url = "https://bitcoinfees.earn.com/api/v1/fees/recommended"; String url = "https://bitcoinfees.earn.com/api/v1/fees/recommended";
return getThreeTierFeeRates(this, defaultblockTargetFeeRates, url); return getThreeTierFeeRates(this, defaultblockTargetFeeRates, url);
} }
}, },
MINIMUM("Minimum (1 sat/vB)") { MINIMUM("Minimum (1 sat/vB)", false) {
@Override @Override
public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) { public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) {
Map<Integer, Double> blockTargetFeeRates = new LinkedHashMap<>(); Map<Integer, Double> blockTargetFeeRates = new LinkedHashMap<>();
@ -40,7 +40,7 @@ public enum FeeRatesSource {
return blockTargetFeeRates; return blockTargetFeeRates;
} }
}, },
OXT_ME("oxt.me") { OXT_ME("oxt.me", true) {
@Override @Override
public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) { public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) {
String url = AppServices.isUsingProxy() ? "http://oxtwshnfyktikbflierkwcxxksbonl6v73l5so5zky7ur72w52tktkid.onion/stats/global/mempool" : "https://api.oxt.me/stats/global/mempool"; String url = AppServices.isUsingProxy() ? "http://oxtwshnfyktikbflierkwcxxksbonl6v73l5so5zky7ur72w52tktkid.onion/stats/global/mempool" : "https://api.oxt.me/stats/global/mempool";
@ -63,9 +63,11 @@ public enum FeeRatesSource {
public static final int BLOCKS_IN_TWO_HOURS = 12; public static final int BLOCKS_IN_TWO_HOURS = 12;
private final String name; private final String name;
private final boolean external;
FeeRatesSource(String name) { FeeRatesSource(String name, boolean external) {
this.name = name; this.name = name;
this.external = external;
} }
public abstract Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates); public abstract Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates);
@ -74,6 +76,10 @@ public enum FeeRatesSource {
return name; return name;
} }
public boolean isExternal() {
return external;
}
private static Map<Integer, Double> getThreeTierFeeRates(FeeRatesSource feeRatesSource, Map<Integer, Double> defaultblockTargetFeeRates, String url) { private static Map<Integer, Double> getThreeTierFeeRates(FeeRatesSource feeRatesSource, Map<Integer, Double> defaultblockTargetFeeRates, String url) {
if(log.isInfoEnabled()) { if(log.isInfoEnabled()) {
log.info("Requesting fee rates from " + url); log.info("Requesting fee rates from " + url);