Skip to content

Commit

Permalink
Implemented Spread endpoint and tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
danmrichards committed Feb 17, 2018
1 parent 32493cc commit 569a920
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 4 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Go Kraken [![GoDoc](https://godoc.org/github.com/danmrichards/gokraken?status.svg)](https://godoc.org/github.com/danmrichards/gokraken) [![License](http://img.shields.io/badge/license-mit_bsd-blue.svg)](https://raw.githubusercontent.com/danmrichards/gokraken/master/LICENSE) [![Go Report Card](https://goreportcard.com/badge/github.com/danmrichards/gokraken)](https://goreportcard.com/report/github.com/danmrichards/gokraken) [![Build Status](https://travis-ci.org/danmrichards/gokraken.svg?branch=master)](https://travis-ci.org/danmrichards/gokraken)
A Go API client for the [Kraken](https://www.kraken.com) cryptocurrency exchange

> Note: This is stupidly early in development. Don't use it please...no really don't
## Usage
### Public API
```go
Expand Down Expand Up @@ -63,7 +61,7 @@ Coming soon
- [x] Public API calls working
- [x] Private API calls working
- [x] Travis CI
- [ ] Implement public market data endpoints
- [x] Implement public market data endpoints
- [ ] Implement private user data endpoints
- [ ] Implement private user trading endpoints
- [ ] Implement private user funding endpoints
Expand Down
2 changes: 1 addition & 1 deletion depth.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type DepthRequest struct {
Count int
}

// TradesResponse represents the response from the Kraken order book endpoint.
// DepthResponse represents the response from the Kraken order book endpoint.
type DepthResponse map[string]Depth

// Depth is an order book response for a given asset pair.
Expand Down
94 changes: 94 additions & 0 deletions market.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,97 @@ func (m *Market) Trades(ctx context.Context, tradeReq *TradesRequest) (res *Trad

return
}

// Spread returns the spread data from Kraken.
// https://www.kraken.com/en-gb/help/api#get-recent-spread-data
func (m *Market) Spread(ctx context.Context, spreadReq *SpreadRequest) (res *SpreadResponse, err error) {
body := url.Values{
"pair": []string{spreadReq.Pair},
}

if spreadReq.Since != 0 {
body["since"] = []string{strconv.FormatInt(spreadReq.Since, 10)}
}

req, err := m.Client.Dial(ctx, http.MethodPost, SpreadResource, body)
if err != nil {
return
}

krakenResp, err := m.Client.Call(req)
if err != nil {
return
}

var tmp map[string]interface{}
err = krakenResp.ExtractResult(&tmp)
if err != nil {
return
}

lastFloat, ok := tmp["last"].(float64)
if !ok {
err = errors.New("could not extract last from ohlc response")
return
}

res = &SpreadResponse{
Last: int64(lastFloat),
Data: make([]SpreadData, 0),
}

spreadData, ok := tmp[spreadReq.Pair].([]interface{})
if !ok {
err = fmt.Errorf("could not extract spread data where pair=%s", spreadReq.Pair)
return
}

for key, spreadDatum := range spreadData {
spreadDatum, ok := spreadDatum.([]interface{})
if !ok {
err = fmt.Errorf("could not extract at spreadDatum=%d", key)
return
}

timestampFloat, ok := spreadDatum[0].(float64)
if !ok {
err = fmt.Errorf("could not extract timestamp at spreadDatum=%d", key)
return
}
timestamp := time.Unix(int64(timestampFloat), 0)

bidStr, ok := spreadDatum[1].(string)
if !ok {
err = fmt.Errorf("could not extract bid at spreadDatum=%d", key)
return
}

var bid float64
bid, err = strconv.ParseFloat(bidStr, 64)
if err != nil {
err = fmt.Errorf("could not parse bid to float at spreadDatum=%d", key)
return
}

askStr, ok := spreadDatum[2].(string)
if !ok {
err = fmt.Errorf("could not extract ask at spreadDatum=%d", key)
return
}

var ask float64
ask, err = strconv.ParseFloat(askStr, 64)
if err != nil {
err = fmt.Errorf("could not parse ask to float at spreadDatum=%d", key)
return
}

res.Data = append(res.Data, SpreadData{
Timestamp: timestamp,
Bid: bid,
Ask: ask,
})
}

return
}
47 changes: 47 additions & 0 deletions market_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -687,3 +687,50 @@ func TestMarket_Trades(t *testing.T) {
})
}
}

func TestMarket_Spread(t *testing.T) {
cases := []struct {
name string
request *SpreadRequest
mockResponse []byte
expectedResponse *SpreadResponse
}{
{
name: "valid request",
request: &SpreadRequest{Pair: "BCHEUR"},
mockResponse: []byte(`{"error":[],"result":{"BCHEUR":[[1518904771,"1225.600000","1229.200000"]],"last":1518905570}}`),
expectedResponse: &SpreadResponse{
Data: []SpreadData{
{
Timestamp: time.Unix(1518904771, 0),
Bid: 1225.6,
Ask: 1229.2,
},
},
Last: 1518905570,
},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)

w.Write(c.mockResponse)
}))

defer ts.Close()

k := New()
k.BaseURL = ts.URL

res, err := k.Market.Spread(context.Background(), &SpreadRequest{Pair: "BCHEUR"})
if err != nil {
t.Fatal(err)
}

assert(c.expectedResponse, res, t)
})
}
}
25 changes: 25 additions & 0 deletions spread.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package gokraken

import "time"

// SpreadResource is the API resource for the Kraken API spread data.
const SpreadResource = "Spread"

// SpreadRequest represents a request to get spread data from Kraken.
type SpreadRequest struct {
Pair string
Since int64
}

// SpreadResponse represents the response from the Kraken spread data endpoint.
type SpreadResponse struct {
Data []SpreadData
Last int64
}

// SpreadData is the spread of data for trades.
type SpreadData struct {
Timestamp time.Time
Bid float64
Ask float64
}

0 comments on commit 569a920

Please sign in to comment.