From e18f0406af08aebfa2b4448f5bdf02198eaf1510 Mon Sep 17 00:00:00 2001 From: cd2357 Date: Tue, 5 May 2020 17:00:08 +0200 Subject: [PATCH] Switch to more accurate fee estimation endpoint The API endpoint for fee estimations has been changed to one that delivers more accurate fee estimations. This is a temporary solution, until a more decentralized approach is found. Fixes projects/issues/27 --- .../main/settings/about/AboutView.java | 2 +- .../providers/BitcoinFeeRateProvider.java | 21 +++++---- .../providers/BitcoinFeeRateProviderTest.java | 45 +++++++++++++++++++ 3 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 pricenode/src/test/java/bisq/price/mining/providers/BitcoinFeeRateProviderTest.java diff --git a/desktop/src/main/java/bisq/desktop/main/settings/about/AboutView.java b/desktop/src/main/java/bisq/desktop/main/settings/about/AboutView.java index 04298a2762..4e7a1fd9d5 100644 --- a/desktop/src/main/java/bisq/desktop/main/settings/about/AboutView.java +++ b/desktop/src/main/java/bisq/desktop/main/settings/about/AboutView.java @@ -83,7 +83,7 @@ public class AboutView extends ActivatableView { "Poloniex (https://poloniex.com)", "Coinmarketcap (https://coinmarketcap.com)")); if (isBtc) - addCompactTopLabelTextField(root, ++gridRow, Res.get("setting.about.feeEstimation.label"), "Earn.com (https://bitcoinfees.earn.com)"); + addCompactTopLabelTextField(root, ++gridRow, Res.get("setting.about.feeEstimation.label"), "mempool.space (https://mempool.space)"); addTitledGroupBg(root, ++gridRow, 2, Res.get("setting.about.versionDetails"), Layout.GROUP_DISTANCE); addCompactTopLabelTextField(root, gridRow, Res.get("setting.about.version"), Version.VERSION, Layout.TWICE_FIRST_ROW_AND_GROUP_DISTANCE); diff --git a/pricenode/src/main/java/bisq/price/mining/providers/BitcoinFeeRateProvider.java b/pricenode/src/main/java/bisq/price/mining/providers/BitcoinFeeRateProvider.java index 9d4c9fa0be..c27c8c0a7f 100644 --- a/pricenode/src/main/java/bisq/price/mining/providers/BitcoinFeeRateProvider.java +++ b/pricenode/src/main/java/bisq/price/mining/providers/BitcoinFeeRateProvider.java @@ -42,8 +42,8 @@ import java.util.stream.Stream; @Component class BitcoinFeeRateProvider extends FeeRateProvider { - private static final long MIN_FEE_RATE = 10; // satoshi/byte - private static final long MAX_FEE_RATE = 1000; + protected static final long MIN_FEE_RATE = 10; // satoshi/byte + protected static final long MAX_FEE_RATE = 1000; private static final int DEFAULT_MAX_BLOCKS = 2; private static final int DEFAULT_REFRESH_INTERVAL = 2; @@ -63,9 +63,9 @@ class BitcoinFeeRateProvider extends FeeRateProvider { private long getEstimatedFeeRate() { return getFeeRatePredictions() - .filter(p -> p.get("maxDelay") <= maxBlocks) + .filter(p -> p.getKey().equalsIgnoreCase("halfHourFee")) + .map(Map.Entry::getValue) .findFirst() - .map(p -> p.get("maxFee")) .map(r -> { log.info("latest fee rate prediction is {} sat/byte", r); return r; @@ -75,19 +75,18 @@ class BitcoinFeeRateProvider extends FeeRateProvider { .orElse(MIN_FEE_RATE); } - private Stream> getFeeRatePredictions() { + private Stream> getFeeRatePredictions() { return restTemplate.exchange( RequestEntity .get(UriComponentsBuilder - // now using /fees/list because /fees/recommended estimates were too high - .fromUriString("https://bitcoinfees.earn.com/api/v1/fees/list") + // Temporarily call mempool.space centralized API endpoint + // A more de-centralized solution discussed in https://github.com/bisq-network/projects/issues/27 + .fromUriString("https://mempool.space/api/v1/fees/recommended") .build().toUri()) .header("User-Agent", "") // required to avoid 403 .build(), - new ParameterizedTypeReference>>>() { - } - ).getBody().entrySet().stream() - .flatMap(e -> e.getValue().stream()); + new ParameterizedTypeReference>() { } + ).getBody().entrySet().stream(); } private static Optional args(Environment env) { diff --git a/pricenode/src/test/java/bisq/price/mining/providers/BitcoinFeeRateProviderTest.java b/pricenode/src/test/java/bisq/price/mining/providers/BitcoinFeeRateProviderTest.java new file mode 100644 index 0000000000..916c39d9e0 --- /dev/null +++ b/pricenode/src/test/java/bisq/price/mining/providers/BitcoinFeeRateProviderTest.java @@ -0,0 +1,45 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.price.mining.providers; + +import bisq.price.mining.FeeRate; + +import org.springframework.context.support.GenericXmlApplicationContext; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class BitcoinFeeRateProviderTest { + + @Test + public void doGet_successfulCall() { + + GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); + BitcoinFeeRateProvider feeRateProvider = new BitcoinFeeRateProvider(ctx.getEnvironment()); + + // Make a call to the API, retrieve the recommended fee rate + // If the API call fails, or the response body cannot be parsed, the test will fail with an exception + FeeRate retrievedFeeRate = feeRateProvider.doGet(); + + // Check that the FeeRateProvider returns a fee within the defined parameters + assertTrue(retrievedFeeRate.getPrice() >= BitcoinFeeRateProvider.MIN_FEE_RATE); + assertTrue(retrievedFeeRate.getPrice() <= BitcoinFeeRateProvider.MAX_FEE_RATE); + } + +}