From 8ca48311ee41535f9c02407c4fccf506d229fce2 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 19 Oct 2023 22:46:43 +0800 Subject: [PATCH] chainfee: add a new interface method `GetFeeMap` This commit adds a new method `GetFeeMap` to handle querying the web API and parse the response into a map that's used by the fee estimator. In doing so we can provide a deeper abstraction over the `WebAPIFeeSource` interface. --- lnwallet/chainfee/estimator.go | 76 ++++++++++++++++++----------- lnwallet/chainfee/estimator_test.go | 4 ++ 2 files changed, 51 insertions(+), 29 deletions(-) diff --git a/lnwallet/chainfee/estimator.go b/lnwallet/chainfee/estimator.go index 1b766fe80..8bf61e0ac 100644 --- a/lnwallet/chainfee/estimator.go +++ b/lnwallet/chainfee/estimator.go @@ -502,6 +502,10 @@ type WebAPIFeeSource interface { // by the above query URL. Typically this will be JSON, but the // specifics are left to the WebAPIFeeSource implementation. ParseResponse(r io.Reader) (map[uint32]uint32, error) + + // GetFeeMap will query the web API, parse the response and return a + // map of confirmation targets to sat/kw fees. + GetFeeMap() (map[uint32]uint32, error) } // SparseConfFeeSource is an implementation of the WebAPIFeeSource that utilizes @@ -543,6 +547,47 @@ func (s SparseConfFeeSource) ParseResponse(r io.Reader) (map[uint32]uint32, erro return resp.FeeByBlockTarget, nil } +// GetFeeMap will query the web API, parse the response and return a map of +// confirmation targets to sat/kw fees. +func (s SparseConfFeeSource) GetFeeMap() (map[uint32]uint32, error) { + // Rather than use the default http.Client, we'll make a custom one + // which will allow us to control how long we'll wait to read the + // response from the service. This way, if the service is down or + // overloaded, we can exit early and use our default fee. + netTransport := &http.Transport{ + Dial: (&net.Dialer{ + Timeout: 5 * time.Second, + }).Dial, + TLSHandshakeTimeout: 5 * time.Second, + } + netClient := &http.Client{ + Timeout: time.Second * 10, + Transport: netTransport, + } + + // With the client created, we'll query the API source to fetch the URL + // that we should use to query for the fee estimation. + targetURL := s.GenQueryURL() + resp, err := netClient.Get(targetURL) + if err != nil { + log.Errorf("unable to query web api for fee response: %v", + err) + return nil, err + } + defer resp.Body.Close() + + // Once we've obtained the response, we'll instruct the WebAPIFeeSource + // to parse out the body to obtain our final result. + feesByBlockTarget, err := s.ParseResponse(resp.Body) + if err != nil { + log.Errorf("unable to parse fee api response: %v", err) + + return nil, err + } + + return feesByBlockTarget, nil +} + // A compile-time assertion to ensure that SparseConfFeeSource implements the // WebAPIFeeSource interface. var _ WebAPIFeeSource = (*SparseConfFeeSource)(nil) @@ -762,38 +807,11 @@ func (w *WebAPIEstimator) getCachedFee(numBlocks uint32) (uint32, error) { // updateFeeEstimates re-queries the API for fresh fees and caches them. func (w *WebAPIEstimator) updateFeeEstimates() { - // Rather than use the default http.Client, we'll make a custom one - // which will allow us to control how long we'll wait to read the - // response from the service. This way, if the service is down or - // overloaded, we can exit early and use our default fee. - netTransport := &http.Transport{ - Dial: (&net.Dialer{ - Timeout: 5 * time.Second, - }).Dial, - TLSHandshakeTimeout: 5 * time.Second, - } - netClient := &http.Client{ - Timeout: time.Second * 10, - Transport: netTransport, - } - - // With the client created, we'll query the API source to fetch the URL - // that we should use to query for the fee estimation. - targetURL := w.apiSource.GenQueryURL() - resp, err := netClient.Get(targetURL) - if err != nil { - log.Errorf("unable to query web api for fee response: %v", - err) - return - } - defer resp.Body.Close() - // Once we've obtained the response, we'll instruct the WebAPIFeeSource // to parse out the body to obtain our final result. - feesByBlockTarget, err := w.apiSource.ParseResponse(resp.Body) + feesByBlockTarget, err := w.apiSource.GetFeeMap() if err != nil { - log.Errorf("unable to query web api for fee response: %v", - err) + log.Errorf("unable to get fee response: %v", err) return } diff --git a/lnwallet/chainfee/estimator_test.go b/lnwallet/chainfee/estimator_test.go index 8227b5f2b..75bf950d8 100644 --- a/lnwallet/chainfee/estimator_test.go +++ b/lnwallet/chainfee/estimator_test.go @@ -24,6 +24,10 @@ func (e mockSparseConfFeeSource) ParseResponse(r io.Reader) (map[uint32]uint32, return e.fees, nil } +func (e mockSparseConfFeeSource) GetFeeMap() (map[uint32]uint32, error) { + return e.fees, nil +} + // TestFeeRateTypes checks that converting fee rates between the // different types that represent fee rates and calculating fees // work as expected.