gitlab.com/SkynetLabs/skyd@v1.6.9/cmd/skyc/cryptowatch.go (about) 1 package main 2 3 // This code pulls SC data from crypto watch for historical pricing information. 4 // 5 // There is a go SDK https://github.com/cryptowatch/cw-sdk-go but the last 6 // version release was 2019 and the one method we would use doesn't support the 7 // necessary arguments. So much of the code is copied from the SDK here to add 8 // the functionality we need. 9 // 10 // ref: https://docs.cryptowat.ch/ 11 12 import ( 13 "encoding/json" 14 "fmt" 15 "net/http" 16 "time" 17 18 "gitlab.com/NebulousLabs/errors" 19 ) 20 21 type ( 22 // ohlcResponse is the data type for the response body of the OHLC 23 // request. This is copied from the cryptowatch go sdk 24 ohlcResponse struct { 25 Result map[string][][]json.Number `json:"result"` 26 } 27 28 // SCPrice defines the response data for an OHLC interval 29 SCPrice struct { 30 // High and Low Price for the interval 31 Average float64 32 High float64 33 Low float64 34 35 // EndTime is the end of the interval. 36 EndTime time.Time 37 38 // StartTime is the beginning of the interval. 39 StartTime time.Time 40 } 41 ) 42 43 // scUSDPrices returns the SCUSD price information 44 func scUSDPrices(start, end int64) ([]SCPrice, error) { 45 return scPrices(start, end, "scusd") 46 } 47 48 // scPrices pulls the historical SC Price information 49 // 50 // ref: https://docs.cryptowat.ch/rest-api/markets/ohlc 51 func scPrices(start, end int64, pair string) (priceInfo []SCPrice, err error) { 52 client := &http.Client{} 53 var period int64 = 86400 // one day in seconds 54 query := fmt.Sprintf("https://api.cryptowat.ch/markets/kraken/%v/ohlc?periods=%v&before=%v&after=%v", pair, period, end, start) 55 req, err := http.NewRequest("GET", query, nil) 56 if err != nil { 57 return nil, errors.AddContext(err, "unable to build request") 58 } 59 resp, err := client.Do(req) 60 if err != nil { 61 return nil, errors.AddContext(err, "unable to fetch historical price info") 62 } 63 defer func() { 64 err = errors.Compose(err, resp.Body.Close()) 65 }() 66 67 srv := ohlcResponse{} 68 69 dec := json.NewDecoder(resp.Body) 70 if err := dec.Decode(&srv); err != nil { 71 return nil, err 72 } 73 74 // Grab the period info 75 periodResults, ok := srv.Result[fmt.Sprint(period)] 76 if !ok { 77 return nil, errors.New("period not found in map") 78 } 79 80 priceInfo = make([]SCPrice, 0, len(periodResults)) 81 for _, pr := range periodResults { 82 if len(pr) < 7 { 83 return nil, fmt.Errorf("unexpected response from the server: wanted 7 elements, got %v", pr) 84 } 85 86 ts, err := pr[0].Int64() 87 if err != nil { 88 return nil, errors.AddContext(err, fmt.Sprintf("getting timestamp %q", pr[0].String())) 89 } 90 high, err := pr[2].Float64() 91 if err != nil { 92 return nil, err 93 } 94 low, err := pr[3].Float64() 95 if err != nil { 96 return nil, err 97 } 98 priceInfo = append(priceInfo, SCPrice{ 99 Average: (high + low) / 2, 100 High: high, 101 Low: low, 102 103 EndTime: time.Unix(ts, 0), 104 StartTime: time.Unix(ts-period, 0), 105 }) 106 } 107 return priceInfo, nil 108 }