Skip to content

Commit

Permalink
Merge pull request bitfinexcom#111 from brobits/maintenance
Browse files Browse the repository at this point in the history
Maintenance
  • Loading branch information
prdn authored Mar 29, 2018
2 parents b193d51 + f5bee0a commit 0021a6a
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 34 deletions.
70 changes: 55 additions & 15 deletions v2/rest/client.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package rest

import (
"crypto/hmac"
"crypto/sha512"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/bitfinexcom/bitfinex-api-go/utils"
"io"
"io/ioutil"
"net/http"
Expand All @@ -11,6 +15,11 @@ import (

var productionBaseURL = "https://api.bitfinex.com/v2/"

type requestFactory interface {
NewAuthenticatedRequestWithData(refURL string, data map[string]interface{}) (Request, error)
NewAuthenticatedRequest(refURL string) (Request, error)
}

type Synchronous interface {
Request(request Request) ([]interface{}, error)
}
Expand All @@ -19,6 +28,7 @@ type Client struct {
// base members for synchronous API
apiKey string
apiSecret string
nonce utils.NonceGenerator

// service providers
Orders OrderService
Expand Down Expand Up @@ -48,7 +58,7 @@ func NewClientWithURLHttpDo(base string, httpDo func(c *http.Client, r *http.Req
httpDo: httpDo,
HTTPClient: http.DefaultClient,
}
return NewClientWithSynchronous(sync)
return NewClientWithSynchronousNonce(sync, utils.NewEpochNonceGenerator()) // make nonce easier to inject?
}

func NewClientWithURL(url string) *Client {
Expand All @@ -58,31 +68,33 @@ func NewClientWithURL(url string) *Client {
return NewClientWithURLHttpDo(url, httpDo)
}

// mock me
func NewClientWithSynchronous(sync Synchronous) *Client {
// mock me in tests
func NewClientWithSynchronousNonce(sync Synchronous, nonce utils.NonceGenerator) *Client {
c := &Client{
Synchronous: sync,
nonce: nonce,
}
c.Orders = OrderService{Synchronous: c}
c.Orders = OrderService{Synchronous: c, requestFactory: c}
c.Book = BookService{Synchronous: c}
c.Trades = TradeService{Synchronous: c}
c.Trades = TradeService{Synchronous: c, requestFactory: c}
c.Platform = PlatformService{Synchronous: c}
c.Positions = PositionService{Synchronous: c}
c.Positions = PositionService{Synchronous: c, requestFactory: c}
return c
}

func (c Client) Credentials(key string, secret string) *Client {
func (c *Client) Credentials(key string, secret string) *Client {
c.apiKey = key
c.apiSecret = secret
return &c
return c
}

// Request is a wrapper for standard http.Request. Default method is POST with no data.
type Request struct {
RefURL string // ref url
Data map[string]interface{} // body data
Method string // http method
Params url.Values // query parameters
RefURL string // ref url
Data map[string]interface{} // body data
Method string // http method
Params url.Values // query parameters
Headers map[string]string
}

// Response is a wrapper for standard http.Response and provides more methods.
Expand All @@ -91,6 +103,33 @@ type Response struct {
Body []byte
}

func (c *Client) sign(msg string) string {
sig := hmac.New(sha512.New384, []byte(c.apiSecret))
sig.Write([]byte(msg))
return hex.EncodeToString(sig.Sum(nil))
}

func (c *Client) NewAuthenticatedRequest(refURL string) (Request, error) {
return c.NewAuthenticatedRequestWithData(refURL, nil)
}

func (c *Client) NewAuthenticatedRequestWithData(refURL string, data map[string]interface{}) (Request, error) {
authURL := "auth/r/" + refURL
req := NewRequestWithData(authURL, data)
nonce := c.nonce.GetNonce()
b, err := json.Marshal(data)
if err != nil {
return Request{}, err
}
msg := "/api/v2/" + authURL + nonce + string(b)
req.Headers["Content-Type"] = "applicaiton/json"
req.Headers["Accept"] = "application/json"
req.Headers["bfx-nonce"] = nonce
req.Headers["bfx-signature"] = c.sign(msg)
req.Headers["bfx-apikey"] = c.apiKey
return req, nil
}

func NewRequest(refURL string) Request {
return NewRequestWithDataMethod(refURL, nil, "POST")
}
Expand All @@ -105,9 +144,10 @@ func NewRequestWithData(refURL string, data map[string]interface{}) Request {

func NewRequestWithDataMethod(refURL string, data map[string]interface{}, method string) Request {
return Request{
RefURL: refURL,
Data: data,
Method: method,
RefURL: refURL,
Data: data,
Method: method,
Headers: make(map[string]string),
}
}

Expand Down
16 changes: 11 additions & 5 deletions v2/rest/orders.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ import (

// OrderService manages data flow for the Order API endpoint
type OrderService struct {
requestFactory
Synchronous
}

// All returns all orders for the authenticated account.
func (s *OrderService) All(symbol string) (*bitfinex.OrderSnapshot, error) {
raw, err := s.Request(NewRequest(path.Join("orders", symbol)))

req, err := s.requestFactory.NewAuthenticatedRequest(path.Join("orders", symbol))
if err != nil {
return nil, err
}
raw, err := s.Request(req)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -54,9 +58,11 @@ func (s *OrderService) History(symbol string) (*bitfinex.OrderSnapshot, error) {
if symbol == "" {
return nil, fmt.Errorf("symbol cannot be empty")
}

raw, err := s.Request(NewRequest(path.Join("orders", symbol, "hist")))

req, err := s.requestFactory.NewAuthenticatedRequest(path.Join("orders", symbol, "hist"))
if err != nil {
return nil, err
}
raw, err := s.Request(req)
if err != nil {
return nil, err
}
Expand Down
16 changes: 8 additions & 8 deletions v2/rest/platform_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ func (p *PlatformService) Status() (bool, error) {
if err != nil {
return false, err
}
/*
// raw is an interface type, but we only care about len & index 0
s := make([]int, len(raw))
for i, v := range raw {
s[i] = v.(int)
}
*/
return len(raw) > 0 && raw[0].(int) == 1, nil
/*
// raw is an interface type, but we only care about len & index 0
s := make([]int, len(raw))
for i, v := range raw {
s[i] = v.(int)
}
*/
return len(raw) > 0 && raw[0].(float64) == 1, nil
}
7 changes: 6 additions & 1 deletion v2/rest/positions.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ import (

// PositionService manages the Position endpoint.
type PositionService struct {
requestFactory
Synchronous
}

// All returns all positions for the authenticated account.
func (s *PositionService) All() (*bitfinex.PositionSnapshot, error) {
raw, err := s.Request(NewRequest("positions"))
req, err := s.requestFactory.NewAuthenticatedRequest("positions")
if err != nil {
return nil, err
}
raw, err := s.Request(req)

if err != nil {
return nil, err
Expand Down
8 changes: 6 additions & 2 deletions v2/rest/trades.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ import (

// TradeService manages the Trade endpoint.
type TradeService struct {
requestFactory
Synchronous
}

// All returns all orders for the authenticated account.
func (s *TradeService) All(symbol string) (*bitfinex.TradeSnapshot, error) {

raw, err := s.Request(NewRequestWithData(path.Join("trades", symbol, "hist"), map[string]interface{}{"start": nil, "end": nil, "limit": nil}))
req, err := s.requestFactory.NewAuthenticatedRequestWithData(path.Join("trades", symbol, "hist"), map[string]interface{}{"start": nil, "end": nil, "limit": nil})
if err != nil {
return nil, err
}
raw, err := s.Request(req)

if err != nil {
return nil, err
Expand Down
3 changes: 0 additions & 3 deletions v2/websocket/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ func (w *ws) Connect() error {
log.Printf("connecting ws to %s", w.BaseURL)
ws, resp, err := d.Dial(w.BaseURL, nil)
if err != nil {
close(w.downstream) // signal to parent connection failure thru listen channel
if err == websocket.ErrBadHandshake {
log.Printf("bad handshake: status code %d", resp.StatusCode)
}
Expand All @@ -76,7 +75,6 @@ func (w *ws) Send(ctx context.Context, msg interface{}) error {
if err != nil {
return err
}
log.Printf("ws->srv: %s", string(bs))

select {
case <-ctx.Done():
Expand Down Expand Up @@ -128,7 +126,6 @@ func (w *ws) listenWs() {
w.cleanup(err)
return
}
log.Printf("srv->ws: %s", string(msg))
w.downstream <- msg
}
}
Expand Down

0 comments on commit 0021a6a

Please sign in to comment.