Skip to content

Commit

Permalink
multi: init fiat backends with proxy if provided
Browse files Browse the repository at this point in the history
This commit adds support for the coindesk backends to be initialized
with a socks proxy if one is provided.
  • Loading branch information
ellemouton committed May 19, 2021
1 parent f7a85d4 commit 99c02d7
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 16 deletions.
3 changes: 3 additions & 0 deletions accounting/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ type CommonConfig struct {
// Categories is a set of custom categories which should be added to the
// report.
Categories []CustomCategory

// SocksProxy is the URL to be used as a proxy for http requests.
SocksProxy string
}

// NewOnChainConfig returns an on chain config from the lnd services provided.
Expand Down
6 changes: 4 additions & 2 deletions accounting/conversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func invertMsat(msat int64) int64 {
// individual price points from this data.
func getConversion(ctx context.Context, startTime, endTime time.Time,
disableFiat bool, fiatBackend fiat.PriceBackend,
granularity *fiat.Granularity) (usdPrice, error) {
granularity *fiat.Granularity, socksProxy string) (usdPrice, error) {

// If we don't want fiat values, just return a price which will yield
// a zero price and timestamp.
Expand All @@ -49,7 +49,9 @@ func getConversion(ctx context.Context, startTime, endTime time.Time,
return nil, err
}

fiatClient, err := fiat.NewPricePriceSource(fiatBackend, granularity)
fiatClient, err := fiat.NewPricePriceSource(
fiatBackend, granularity, socksProxy,
)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion accounting/off_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func OffChainReport(ctx context.Context, cfg *OffChainConfig) (Report, error) {
// or a no-op function if we do not want prices.
getPrice, err := getConversion(
ctx, cfg.StartTime, cfg.EndTime, cfg.DisableFiat,
cfg.FiatBackend, cfg.Granularity,
cfg.FiatBackend, cfg.Granularity, cfg.SocksProxy,
)
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion accounting/on_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func OnChainReport(ctx context.Context, cfg *OnChainConfig) (Report, error) {
// or a no-op function if we do not want prices.
getPrice, err := getConversion(
ctx, cfg.StartTime, cfg.EndTime, cfg.DisableFiat,
cfg.FiatBackend, cfg.Granularity,
cfg.FiatBackend, cfg.Granularity, cfg.SocksProxy,
)
if err != nil {
return nil, err
Expand Down
11 changes: 6 additions & 5 deletions fiat/coindesk_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,25 @@ const (
)

// coinDeskAPI implements the fiatBackend interface.
type coinDeskAPI struct{}
type coinDeskAPI struct {
httpClient *http.Client
}

type coinDeskResponse struct {
Data map[string]float64 `json:"bpi"`
}

// queryCoinDesk constructs and sends a request to coindesk to query historical
// price information.
func queryCoinDesk(start, end time.Time) ([]byte, error) {
func (c *coinDeskAPI) queryCoinDesk(start, end time.Time) ([]byte, error) {
queryURL := fmt.Sprintf("%v?start=%v&end=%v",
coinDeskHistoryAPI, start.Format(coinDeskTimeFormat),
end.Format(coinDeskTimeFormat))

log.Debugf("coindesk url: %v", queryURL)

// Query the http endpoint with the url provided
// #nosec G107
response, err := http.Get(queryURL)
response, err := c.httpClient.Get(queryURL)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -77,7 +78,7 @@ func (c *coinDeskAPI) rawPriceData(ctx context.Context, start,
end time.Time) ([]*USDPrice, error) {

query := func() ([]byte, error) {
return queryCoinDesk(start, end)
return c.queryCoinDesk(start, end)
}

// CoinDesk uses a granularity of 1 day and does not include the current
Expand Down
55 changes: 49 additions & 6 deletions fiat/prices.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package fiat
import (
"context"
"errors"
"net/http"
"net/url"
"sort"
"time"

Expand Down Expand Up @@ -91,18 +93,57 @@ var priceBackendNames = map[PriceBackend]string{
CoinDeskPriceBackend: "coindesk",
}

var priceBackendProxySupport = map[PriceBackend]bool{
CoinCapPriceBackend: false,
CoinDeskPriceBackend: true,
}

// String returns the string representation of a price backend.
func (p PriceBackend) String() string {
return priceBackendNames[p]
}

// NewPricePriceSource returns a PriceSource which can be used to query price
// data.
func NewPricePriceSource(backend PriceBackend, granularity *Granularity) (
*PriceSource, error) {
func NewPricePriceSource(backend PriceBackend, granularity *Granularity,
proxy string) (*PriceSource, error) {

// If no specific backend is specified then choose a default backend
// based on whether or not a proxy is specified.
if backend == UnknownPriceBackend {
if proxy != "" {
backend = CoinDeskPriceBackend
} else {
backend = CoinCapPriceBackend
}
}

// Check that the proxy flag is not set for a price backend that does
// not support requests through a socks proxy.
if proxy != "" && !priceBackendProxySupport[backend] {
return nil, errors.New("can't use a socks proxy for the " +
"given backend")
}

httpClient := http.DefaultClient
if proxy != "" {
// Parse socks proxy URL string to a URL type
socksProxyURL, err := url.Parse("socks5://" + proxy)
if err != nil {
return nil, err
}

// Set up a custom HTTP transport to use the proxy and
// create the client
httpClient = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(socksProxyURL),
},
}
}

switch backend {
case UnknownPriceBackend, CoinCapPriceBackend:
case CoinCapPriceBackend:
if granularity == nil {
return nil, errGranularityRequired
}
Expand All @@ -112,7 +153,9 @@ func NewPricePriceSource(backend PriceBackend, granularity *Granularity) (

case CoinDeskPriceBackend:
return &PriceSource{
impl: &coinDeskAPI{},
impl: &coinDeskAPI{
httpClient: httpClient,
},
}, nil
}

Expand All @@ -133,7 +176,7 @@ type PriceRequest struct {

// GetPrices gets a set of prices for a set of timestamps.
func GetPrices(ctx context.Context, timestamps []time.Time,
backend PriceBackend, granularity Granularity) (
backend PriceBackend, granularity Granularity, socksProxy string) (
map[time.Time]*USDPrice, error) {

if len(timestamps) == 0 {
Expand All @@ -152,7 +195,7 @@ func GetPrices(ctx context.Context, timestamps []time.Time,
// timestamp if we have 1 entry, but that's ok.
start, end := timestamps[0], timestamps[len(timestamps)-1]

client, err := NewPricePriceSource(backend, &granularity)
client, err := NewPricePriceSource(backend, &granularity, socksProxy)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion frdrpc/rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ func (s *RPCServer) ExchangeRate(ctx context.Context,
}

prices, err := fiat.GetPrices(
ctx, timestamps, fiatBackend, *granularity,
ctx, timestamps, fiatBackend, *granularity, "",
)
if err != nil {
return nil, err
Expand Down

0 comments on commit 99c02d7

Please sign in to comment.