From 6452bf8184fe556432cb012b338e8524cc1d0534 Mon Sep 17 00:00:00 2001 From: Liz Lightning Date: Tue, 25 Nov 2025 00:32:33 -0800 Subject: [PATCH] add block.xyz augur fee estimator --- .../sparrow/net/FeeRatesSource.java | 56 +++++++++++++++++++ .../sparrow/settings/general.fxml | 1 + .../image/feeratesource/block.xyz-icon.svg | 14 +++++ 3 files changed, 71 insertions(+) create mode 100644 src/main/resources/image/feeratesource/block.xyz-icon.svg diff --git a/src/main/java/com/sparrowwallet/sparrow/net/FeeRatesSource.java b/src/main/java/com/sparrowwallet/sparrow/net/FeeRatesSource.java index 4eebee6e..9a3b7eef 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/FeeRatesSource.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/FeeRatesSource.java @@ -3,6 +3,7 @@ package com.sparrowwallet.sparrow.net; import com.sparrowwallet.drongo.Network; import com.sparrowwallet.drongo.Utils; import com.sparrowwallet.drongo.protocol.Sha256Hash; +import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.wallet.BlockTransaction; import com.sparrowwallet.drongo.wallet.BlockTransactionHash; import com.sparrowwallet.sparrow.AppServices; @@ -71,6 +72,30 @@ public enum FeeRatesSource { return network == Network.MAINNET || network == Network.TESTNET || network == Network.TESTNET4 || network == Network.SIGNET; } }, + BLOCK_XYZ("block.xyz", true) { + /* + https://engineering.block.xyz/blog/augur-an-open-source-bitcoin-fee-estimation-library + */ + @Override + public Map getBlockTargetFeeRates(Map defaultblockTargetFeeRates) { + String url = "https://pricing.bitcoin.block.xyz/fees"; + return getThreeTierFeeRates(this, defaultblockTargetFeeRates, url); + } + + @Override + public boolean supportsNetwork(Network network) { + return network == Network.MAINNET; + } + + @Override + protected ThreeTierRates getThreeTierRates(String url, HttpClientService httpClientService) throws Exception { + BlockXyzRates rates = httpClientService.requestJson(url, BlockXyzRates.class, null); + if(rates.estimates == null) { + throw new Exception("Invalid response from " + url); + } + return rates.getThreeTierRates(); + } + }, BITCOINFEES_EARN_COM("bitcoinfees.earn.com", true) { @Override public Map getBlockTargetFeeRates(Map defaultblockTargetFeeRates) { @@ -343,6 +368,37 @@ public enum FeeRatesSource { } } + private record BlockXyzRates(Map estimates) { + public ThreeTierRates getThreeTierRates() { + // see https://engineering.block.xyz/blog/augur-an-open-source-bitcoin-fee-estimation-library + // + // fastestFee: 95% confidence at 3 blocks + // halfHourFee: 80% confidence at 3 blocks + // hourFee: 80% confidence at 6 blocks + // minimumFee: 80% confidence at 144 blocks + Double fastestFee = getFeeRate("3", "0.95"); + Double halfHourFee = getFeeRate("3", "0.80"); + Double hourFee = getFeeRate("6", "0.80"); + Double minimumFee = getFeeRate("144", "0.80"); + return new ThreeTierRates(fastestFee, halfHourFee, hourFee, minimumFee); + } + + private Double getFeeRate(String blocks, String probability) { + BlockXyzEstimate estimate = estimates.get(blocks); + if(estimate != null && estimate.probabilities != null) { + BlockXyzFeeRate feeRate = estimate.probabilities.get(probability); + if(feeRate != null) { + return feeRate.fee_rate; + } + } + return Transaction.DEFAULT_MIN_RELAY_FEE; + } + } + + private record BlockXyzEstimate(Map probabilities) {} + + private record BlockXyzFeeRate(Double fee_rate) {} + protected record MempoolBlock(Integer nTx, Double medianFee) {} protected record MempoolBlockSummary(String id, Integer height, Long timestamp, Integer tx_count, Integer weight, MempoolBlockSummaryExtras extras) { diff --git a/src/main/resources/com/sparrowwallet/sparrow/settings/general.fxml b/src/main/resources/com/sparrowwallet/sparrow/settings/general.fxml index 69946fdb..67e0b350 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/settings/general.fxml +++ b/src/main/resources/com/sparrowwallet/sparrow/settings/general.fxml @@ -36,6 +36,7 @@ + diff --git a/src/main/resources/image/feeratesource/block.xyz-icon.svg b/src/main/resources/image/feeratesource/block.xyz-icon.svg new file mode 100644 index 00000000..aad459ae --- /dev/null +++ b/src/main/resources/image/feeratesource/block.xyz-icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file