Skip to content
This repository has been archived by the owner on Feb 27, 2020. It is now read-only.

Adds historical price api #10

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cryptocomparego.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ type Client struct {

Price PriceService

PriceHist PriceHistService

PriceMulti PriceMultiService

PriceMultiFull PriceMultiFullService
Expand Down Expand Up @@ -99,6 +101,7 @@ func NewClient(httpClient *http.Client) *Client {

c := &Client{client: httpClient, BaseURL: baseURL, MinURL: minURL, UserAgent: userAgent}
c.Coin = &CoinServiceOp{client: c}
c.PriceHist = &PriceHistServiceOp{client: c}
c.Price = &PriceServiceOp{client: c}
c.PriceMulti = &PriceMultiServiceOp{client: c}
c.PriceMultiFull = &PriceMultiFullServiceOp{client: c}
Expand Down
30 changes: 30 additions & 0 deletions example/price_historical/pricehist_example.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package main

import (
"fmt"

"github.com/lucazulian/cryptocomparego/context"
"github.com/nwops/cryptocomparego"
)

func main() {

client := cryptocomparego.NewClient(nil)
ctx := context.TODO()

// Using a 0 as the timestamp gets the current time
// You can use time.Now().Unix() to get the current time and manipulate it from there
// Or pass in a unix timestamp that was computed elsewhere
//priceHistRequest := NewPriceHistRequest("ETH", []string{"BTC", "USD", "EUR"}, 1560918228)
priceHistRequest := cryptocomparego.NewPriceHistRequest("ETH", []string{"BTC", "USD", "EUR"}, 0)

priceHistList, _, err := client.PriceHist.List(ctx, priceHistRequest)

if err != nil {
fmt.Printf("Something bad happened: %s\n", err)
}

for _, coin := range priceHistList {
fmt.Printf("Coin %s - %f\n", coin.Name, coin.Value)
}
}
141 changes: 141 additions & 0 deletions pricehist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package cryptocomparego

import (
"fmt"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"

"github.com/lucazulian/cryptocomparego/context"
)

const (
priceHistBasePath = "data/pricehistorical"
)

// Get the current price of any cryptocurrency in any other currency that you need.
// If the crypto does not trade directly into the toSymbol requested, BTC will be used for conversion.
// If the oposite pair trades we invert it (eg.: BTC-XMR).
type PriceHistService interface {
List(context.Context, *PriceHistRequest) ([]PriceHist, *Response, error)
}

type PriceHist struct {
Name string
Value float64
}

type PriceHistServiceOp struct {
client *Client
}
type PriceHistNameSorter []PriceHist

var _ PriceHistService = &PriceHistServiceOp{}

type PriceHistRequest struct {
Fsym string
Tsyms []string
E string
ExtraParams string
Ts int64
CalculationType string
Sign bool
TryConversion bool
}

func NewPriceHistRequest(fsym string, tsyms []string, ts int64) *PriceHistRequest {
if ts < 1 {
ts = time.Now().Unix()
}
pr := PriceHistRequest{Fsym: fsym, Tsyms: tsyms}
pr.E = "CCCAGG"
pr.Ts = ts
pr.CalculationType = "Close"
pr.Sign = false
pr.TryConversion = true
return &pr
}

func (pr *PriceHistRequest) FormattedQueryString(baseUrl string) string {
values := url.Values{}

if len(pr.Fsym) > 0 {
values.Add("fsym", pr.Fsym)
}

if len(pr.Tsyms) > 0 {
values.Add("tsyms", strings.Join(pr.Tsyms, ","))
}

if len(pr.E) > 0 {
values.Add("e", pr.E)
}

if pr.Ts > 0 {
values.Add("ts", strconv.FormatInt(pr.Ts, 10))
}

if len(pr.CalculationType) > 0 {
values.Add("calculationType", pr.CalculationType)
}

if len(pr.ExtraParams) > 0 {
values.Add("extraParams", pr.ExtraParams)
}

values.Add("sign", strconv.FormatBool(pr.Sign))
values.Add("tryConversion", strconv.FormatBool(pr.TryConversion))

return fmt.Sprintf("%s?%s", baseUrl, values.Encode())
}
func (a PriceHistNameSorter) Len() int { return len(a) }
func (a PriceHistNameSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a PriceHistNameSorter) Less(i, j int) bool { return a[i].Name < a[j].Name }

func (ds *priceRoot) GetHistPrices() ([]PriceHist, error) {
var prices []PriceHist
for _, value := range *ds {
for coinPair, coinPairPrice := range value.(map[string]interface{}) {
priceHist := PriceHist{coinPair, coinPairPrice.(float64)}
prices = append(prices, priceHist)
}
}

return prices, nil
}

func (s *PriceHistServiceOp) List(ctx context.Context, priceHistRequest *PriceHistRequest) ([]PriceHist, *Response, error) {

path := priceHistBasePath

if priceHistRequest != nil {
path = priceHistRequest.FormattedQueryString(priceHistBasePath)
}

req, err := s.client.NewRequest(ctx, http.MethodGet, *s.client.MinURL, path, nil)
if err != nil {
return nil, nil, err
}

root := new(priceRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}

if err := root.HasError(); err != nil {
return nil, resp, err
}

prices, err := root.GetHistPrices()
if err != nil {
return nil, resp, err
}

sort.Sort(PriceHistNameSorter(prices))

return prices, resp, err
}
156 changes: 156 additions & 0 deletions pricehist_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package cryptocomparego

import (
"errors"
"fmt"
"net/http"
"reflect"
"testing"

"github.com/lucazulian/cryptocomparego/context"
)

func TestFormattedQueryStringNilPriceHistRequest(t *testing.T) {

priceHistRequest := NewPriceHistRequest("", nil, 1560918228)
acct := priceHistRequest.FormattedQueryString("/data/pricehistorical")

expected := "/data/pricehistorical?calculationType=Close&e=CCCAGG&sign=false&tryConversion=true&ts=1560918228"

if acct != expected {
t.Errorf("PriceHistRequest.FormattedQueryString returned %+v, expected %+v", acct, expected)
}
}

func TestFormattedQueryStringPriceHistRequest(t *testing.T) {

priceHistRequest := NewPriceHistRequest("ETH", []string{"BTC", "USD", "EUR"}, 1560918228)
acct := priceHistRequest.FormattedQueryString("/data/pricehistorical")

expected := "/data/pricehistorical?calculationType=Close&e=CCCAGG&fsym=ETH&sign=false&tryConversion=true&ts=1560918228&tsyms=BTC%2CUSD%2CEUR"

if acct != expected {
t.Errorf("PriceRequest.FormattedQueryString returned %+v, expected %+v", acct, expected)
}
}

func TestPriceListNilPriceHistRequest(t *testing.T) {
setup()
defer teardown()

mux.HandleFunc("/data/pricehistorical", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)

if r.URL.Query().Get("fsym") != "" || r.URL.Query().Get("tsyms") != "" {
t.Errorf("PriceHist.List did not request the correct fsym or tsyms")
}

response := `
{
"BTC": 0.04502,
"EUR": 313.82,
"USD": 368.87
}`

fmt.Fprint(w, response)
})

acct, _, err := client.PriceHist.List(ctx, nil)
if err != nil {
t.Errorf("PriceHist.List returned error: %v", err)
}

expected := []PriceHist{{"BTC", 0.04502}, {"EUR", 313.82}, {"USD", 368.87}}

if !reflect.DeepEqual(acct, expected) {
t.Errorf("PriceHist.List returned %+v, expected %+v", acct, expected)
}
}

func TestPriceListWrongPriceHistRequest(t *testing.T) {
setup()
defer teardown()

mux.HandleFunc("/data/pricehistorical", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)

if r.URL.Query().Get("fsym") != "ETH" || r.URL.Query().Get("tsyms") != "" {
t.Errorf("PriceHist.List did not request the correct fsym or tsyms")
}

response := `
{
"Response": "Error",
"Message": "tsyms param seems to be missing.",
"Type": 1,
"Aggregated": false,
"Data": []
}`

fmt.Fprint(w, response)
})

priceHistRequest := NewPriceHistRequest("ETH", nil, 1560918228)

acct, _, err := client.PriceHist.List(ctx, priceHistRequest)
if acct != nil {
t.Errorf("PriceHist.List returned a value: %v", err)
}

expected := errors.New("tsyms param seems to be missing.")

if !reflect.DeepEqual(err, expected) {
t.Errorf("PriceHist.List returned %+v, expected %+v", acct, expected)
}
}

func TestPriceHistList(t *testing.T) {
setup()
defer teardown()

mux.HandleFunc("/data/pricehistorical", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)

if r.URL.Query().Get("fsym") != "ETH" || r.URL.Query().Get("tsyms") != "BTC,USD,EUR" {
t.Errorf("PriceHist.List did not request the correct fsym or tsyms")
}

response := `
{
"BTC": 0.04502,
"EUR": 313.82,
"USD": 368.87
}`

fmt.Fprint(w, response)
})

priceHistRequest := &PriceHistRequest{Fsym: "ETH", Tsyms: []string{"BTC", "USD", "EUR"}}

acct, _, err := client.PriceHist.List(ctx, priceHistRequest)
if err != nil {
t.Errorf("PriceHist.List returned error: %v", err)
}

expected := []PriceHist{{"BTC", 0.04502}, {"EUR", 313.82}, {"USD", 368.87}}

if !reflect.DeepEqual(acct, expected) {
t.Errorf("PriceHist.List returned %+v, expected %+v", acct, expected)
}
}

func TestGetPriceHist(t *testing.T) {
client := NewClient(nil)
ctx := context.TODO()
priceHistRequest := NewPriceHistRequest("ETH", []string{"BTC", "USD", "EUR"}, 1560918228)
acct, _, err := client.PriceHist.List(ctx, priceHistRequest)

if err != nil {
t.Errorf("PriceHist.List returned error: %v", err)
}
expected := []PriceHist{{"BTC", 0.029150}, {"EUR", 235.630000}, {"USD", 263.870000}}

if !reflect.DeepEqual(err, expected) {
t.Errorf("PriceHist.List returned %+v, expected %+v", acct, expected)
}
}