Skip to content

Commit

Permalink
Merge pull request #4 from majk-p/master
Browse files Browse the repository at this point in the history
Extract private utils, minor refactor, format readme
  • Loading branch information
spekulant authored May 6, 2021
2 parents db957b6 + 6bbd16e commit 6445788
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 101 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ import (
func main() {
apisample := glassnode.NewClient("your_api_key")

yesterday := glassnode.YesterdayTimestamp()
yesterday := glassnode.YesterdayTimestamp()

opts := glassnode.APIOptionsList{
Asset: "BTC", // or "ETH"
Category: "indicators", // market, derivatives etc
Metric: "sopr", // or "nupl"
Since: yesterday, // UNIX timestamp, 0 means all
Until: 0, // UNIX timestamp, 0 means all
Asset: "BTC", // or "ETH"
Category: "indicators", // market, derivatives etc
Metric: "sopr", // or "nupl"
Since: yesterday, // UNIX timestamp, 0 means all
Until: 0, // UNIX timestamp, 0 means all
}

d, err := glassnode.GetMetricData(context.Background(), *apisample, &opts)
Expand Down
96 changes: 1 addition & 95 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@ import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"time"
)

const (
BaseURLV1 = "https://api.glassnode.com/v1/"
MetricsPrefix = "metrics/"
MetricsPrefix = "metrics"
)

func NewClient(apiKey string) *Client {
Expand Down Expand Up @@ -128,99 +127,6 @@ func GetMetricData(ctx context.Context, api Client, options *APIOptionsList) (in
return parsedResponse, nil
}

func constructURL(api Client, options *APIOptionsList) (string, error) {

// --------
// Base URL
// --------

baseURL, err := url.Parse(api.BaseURL)
if err != nil {
return "", fmt.Errorf("[GetMetricData] couldn't parse url: %s", err.Error())
}
baseURL.Path += MetricsPrefix

// -------------
// Data Category
// -------------

if options.Category == "" {
return "", fmt.Errorf("APIOptionsList.Category appears to be empty but is required")
}
baseURL.Path += options.Category + "/"

// ---------------
// Specific metric
// ---------------

if options.Metric == "" {
return "", fmt.Errorf("APIOptionsList.Metric appears to be empty but is required")
}
baseURL.Path += options.Metric

// ---------------
// Parsing helpers
// ---------------

unrefinedParams := make(map[string]string)
finalParams := url.Values{}

//
// apply raw params, if any
//

for key, value := range options.DirectMapping {
unrefinedParams[key] = value
}

//
// required params
//

if api.apiKey == "" {
return "", fmt.Errorf("api key appears to be empty but is required")
}
unrefinedParams["api_key"] = api.apiKey

if options.Asset != "" {
unrefinedParams["a"] = options.Asset
}
if unrefinedParams["a"] == "" {
return "", fmt.Errorf("parameter a (Asset) appears to be empty but is required")
}

//
// optional params
//

if options.Since != 0 {
unrefinedParams["s"] = fmt.Sprint(options.Since)
}
if options.Until != 0 {
unrefinedParams["u"] = fmt.Sprint(options.Until)
}
if options.Frequency != "" {
unrefinedParams["i"] = fmt.Sprint(options.Frequency)
}

//
// Unsupported options:
if unrefinedParams["f"] != "" {
return "", fmt.Errorf("parameter f (Format) shouldn't be specified")
}

// -----------------------
// Construct the final URL
// -----------------------

for key, value := range unrefinedParams {
finalParams.Add(key, value)
}
baseURL.RawQuery = finalParams.Encode()

return baseURL.String(), nil
}

// -----------
// Data models
// -----------
Expand Down
27 changes: 27 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,30 @@ func Test_liveintegration_directmappings(t *testing.T) {
t.Log(time.Unix(e[i].Time, 0))
}
}

func Test_constructURL(t *testing.T) {

apisample := NewClient("x")

opts := APIOptionsList{
Asset: "BTC",
Category: "indicators",
Metric: "difficulty_ribbon",
DirectMapping: map[string]string{
"s": "123",
"u": "456",
},
}
expectation := "https://api.glassnode.com/v1/metrics/indicators/difficulty_ribbon?a=BTC&api_key=x&s=123&u=456"
result, err := constructURL(*apisample, &opts)

if err != nil {
t.Fail()
}

if expectation != result {
t.Logf("Result: %s didn't match expectation: %s", result, expectation)
t.Fail()
}

}
108 changes: 108 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package glassnode

import (
"fmt"
"net/url"
"path"
)

func constructURL(api Client, options *APIOptionsList) (string, error) {

// --------
// Base URL
// --------

baseURL, err := url.Parse(api.BaseURL)
if err != nil {
return "", fmt.Errorf("[GetMetricData] couldn't parse url: %s", err.Error())
}
baseURL.Path = path.Join(baseURL.Path, MetricsPrefix)

// -------------
// Data Category
// -------------

if options.Category == "" {
return "", fmt.Errorf("APIOptionsList.Category appears to be empty but is required")
}
baseURL.Path = path.Join(baseURL.Path, options.Category)

// ---------------
// Specific metric
// ---------------

if options.Metric == "" {
return "", fmt.Errorf("APIOptionsList.Metric appears to be empty but is required")
}
baseURL.Path = path.Join(baseURL.Path, options.Metric)

finalParams, err := makeParams(api.apiKey, options)
if err != nil {
return "", fmt.Errorf("[GetMetricData] couldn't prepare parameters: %s", err.Error())
}
baseURL.RawQuery = finalParams.Encode()

return baseURL.String(), nil
}

func makeParams(apiKey string, options *APIOptionsList) (*url.Values, error) {
// ---------------
// Parsing helpers
// ---------------

unrefinedParams := make(map[string]string)
finalParams := url.Values{}

//
// apply raw params, if any
//

for key, value := range options.DirectMapping {
unrefinedParams[key] = value
}

//
// required params
//

if apiKey == "" {
return nil, fmt.Errorf("api key appears to be empty but is required")
}
unrefinedParams["api_key"] = apiKey

if options.Asset != "" {
unrefinedParams["a"] = options.Asset
}
if unrefinedParams["a"] == "" {
return nil, fmt.Errorf("parameter a (Asset) appears to be empty but is required")
}

//
// optional params
//

if options.Since != 0 {
unrefinedParams["s"] = fmt.Sprint(options.Since)
}
if options.Until != 0 {
unrefinedParams["u"] = fmt.Sprint(options.Until)
}
if options.Frequency != "" {
unrefinedParams["i"] = fmt.Sprint(options.Frequency)
}

//
// Unsupported options:
if unrefinedParams["f"] != "" {
return nil, fmt.Errorf("parameter f (Format) shouldn't be specified")
}

// -----------------------
// Construct the final URL
// -----------------------

for key, value := range unrefinedParams {
finalParams.Add(key, value)
}
return &finalParams, nil
}

0 comments on commit 6445788

Please sign in to comment.