This repository has been archived by the owner on Feb 27, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
/
price.go
141 lines (110 loc) · 2.96 KB
/
price.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package cryptocomparego
import (
"errors"
"fmt"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"github.com/lucazulian/cryptocomparego/context"
)
const (
priceBasePath = "data/price"
)
// 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 PriceService interface {
List(context.Context, *PriceRequest) ([]Price, *Response, error)
}
type PriceServiceOp struct {
client *Client
}
var _ PriceService = &PriceServiceOp{}
type Price struct {
Name string
Value float64
}
type PriceRequest struct {
Fsym string
Tsyms []string
E string
ExtraParams string
Sign bool
TryConversion bool
}
func NewPriceRequest(fsym string, tsyms []string) *PriceRequest {
pr := PriceRequest{Fsym: fsym, Tsyms: tsyms}
pr.E = "CCCAGG"
pr.Sign = false
pr.TryConversion = true
return &pr
}
func (pr *PriceRequest) 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 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())
}
//TODO try to remove Sorter duplication
type PriceNameSorter []Price
func (a PriceNameSorter) Len() int { return len(a) }
func (a PriceNameSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a PriceNameSorter) Less(i, j int) bool { return a[i].Name < a[j].Name }
type priceRoot map[string]interface{}
func (ds *priceRoot) GetPrices() ([]Price, error) {
var prices []Price
for key, value := range *ds {
price := Price{key, value.(float64)}
prices = append(prices, price)
}
return prices, nil
}
func (ds *priceRoot) HasError() error {
//TODO try to unmarshal with error struct
var priceError error = nil
if val, ok := (*ds)["Response"]; ok {
if val == "Error" {
val, _ = (*ds)["Message"]
priceError = errors.New(val.(string))
}
}
return priceError
}
func (s *PriceServiceOp) List(ctx context.Context, priceRequest *PriceRequest) ([]Price, *Response, error) {
path := priceBasePath
if priceRequest != nil {
path = priceRequest.FormattedQueryString(priceBasePath)
}
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.GetPrices()
if err != nil {
return nil, resp, err
}
sort.Sort(PriceNameSorter(prices))
return prices, resp, err
}