Skip to content

Commit

Permalink
Update getter methods to use new GetAndDecode method
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewstuart committed Jun 13, 2017
1 parent 216830a commit 29b3ab9
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 98 deletions.
10 changes: 1 addition & 9 deletions account.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package robinhood

import (
"encoding/json"
)

type Account struct {
Meta
AccountNumber string `json:"account_number"`
Expand Down Expand Up @@ -59,13 +55,9 @@ type MarginBalances struct {

func (c *Client) GetAccounts() ([]Account, error) {
var r struct{ Results []Account }
res, err := c.Get(epAccounts)
err := c.GetAndDecode(epAccounts, &r)
if err != nil {
return nil, err
}
defer res.Body.Close()

err = json.NewDecoder(res.Body).Decode(&r)

return r.Results, err
}
23 changes: 18 additions & 5 deletions client.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package robinhood

import (
"encoding/json"
"net/http"
"time"

"astuart.co/clyde"
)

const (
epBase = "https://api.robinhood.com/"
epLogin = epBase + "api-token-auth/"
epAccounts = epBase + "accounts/"
epQuotes = epBase + "quotes/"
epPortfolios = epBase + "portfolios/"
epBase = "https://api.robinhood.com/"
epLogin = epBase + "api-token-auth/"
epAccounts = epBase + "accounts/"
epQuotes = epBase + "quotes/"
epPortfolios = epBase + "portfolios/"
epWatchlists = epBase + "watchlists/"
epInstruments = epBase + "instruments/"
)

type Client struct {
Expand All @@ -33,6 +36,16 @@ func Dial(t TokenGetter) (*Client, error) {
}, nil
}

func (c Client) GetAndDecode(url string, dest interface{}) error {
res, err := c.Get(url)
if err != nil {
return err
}
defer res.Body.Close()

return json.NewDecoder(res.Body).Decode(dest)
}

type Meta struct {
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Expand Down
4 changes: 2 additions & 2 deletions creds.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ func (c Creds) Values() url.Values {
// from the RobinHood API will be cached at the file path, and a new token will
// not be obtained.
type CredsCacher struct {
Creds
Path string
Creds TokenGetter
Path string
}

// GetToken implements TokenGetter. It may fail if an error is encountered
Expand Down
14 changes: 6 additions & 8 deletions instrument.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package robinhood

import "encoding/json"

type Instrument struct {
BloombergUnique string `json:"bloomberg_unique"`
Country string `json:"country"`
Expand All @@ -24,13 +22,13 @@ type Instrument struct {
}

func (c Client) GetInstrument(instURL string) (*Instrument, error) {
res, err := c.Get(instURL)
if err != nil {
return nil, err
}
defer res.Body.Close()
var i Instrument
err := c.GetAndDecode(instURL, &i)
return &i, err
}

func (c Client) GetInstrumentForSymbol(sym string) (*Instrument, error) {
var i Instrument
err = json.NewDecoder(res.Body).Decode(&i)
err := c.GetAndDecode(epInstruments+"?symbol="+sym, &i)
return &i, err
}
31 changes: 6 additions & 25 deletions portfolios.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package robinhood

import (
"encoding/json"
)

type Portfolio struct {
Account string `json:"account"`
AdjustedEquityPreviousClose float64 `json:"adjusted_equity_previous_close,string"`
Expand All @@ -25,25 +21,10 @@ type Portfolio struct {
WithdrawableAmount float64 `json:"withdrawable_amount,string"`
}

func (c *Client) GetPortfolios(acc *Account) ([]Portfolio, error) {
ep := epPortfolios
if acc != nil {
ep = acc.Portfolio
}

res, err := c.Get(ep)
if err != nil {
return nil, err
}
defer res.Body.Close()

if acc == nil {
var p struct{ Results []Portfolio }
err = json.NewDecoder(res.Body).Decode(&p)
return p.Results, err
}

var p Portfolio
err = json.NewDecoder(res.Body).Decode(&p)
return []Portfolio{p}, err
// GetPortfolios returns all the portfolios associated with a client's
// credentials and accounts
func (c *Client) GetPortfolios() ([]Portfolio, error) {
var p struct{ Results []Portfolio }
err := c.GetAndDecode(epPortfolios, &p)
return p.Results, err
}
14 changes: 2 additions & 12 deletions positions.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package robinhood

import (
"encoding/json"
)

type Position struct {
Meta
Account string `json:"account"`
Expand All @@ -16,15 +12,9 @@ type Position struct {
SharesHeldForSells float64 `json:"shares_held_for_sells,string"`
}

// GetPositions returns all the positions associated with an account.
func (c Client) GetPositions(a Account) ([]Position, error) {
res, err := c.Get(a.Positions)
if err != nil {
return nil, err
}
defer res.Body.Close()

var r struct{ Results []Position }
err = json.NewDecoder(res.Body).Decode(&r)

err := c.GetAndDecode(a.Positions, &r)
return r.Results, err
}
13 changes: 4 additions & 9 deletions quote.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package robinhood

import (
"encoding/json"
"strings"
)

// A Quote is a representation of the data returned by the Robinhood API for
// current stock quotes
type Quote struct {
AdjustedPreviousClose float64 `json:"adjusted_previous_close,string"`
AskPrice float64 `json:"ask_price,string"`
Expand All @@ -20,16 +21,10 @@ type Quote struct {
UpdatedAt string `json:"updated_at"`
}

// GetQuote returns all the latest stock quotes for the list of stocks provided
func (c Client) GetQuote(stocks ...string) ([]Quote, error) {
url := epQuotes + "?symbols=" + strings.Join(stocks, ",")
res, err := c.Get(url)
if err != nil {
return nil, err
}
defer res.Body.Close()

var r struct{ Results []Quote }

err = json.NewDecoder(res.Body).Decode(&r)
err := c.GetAndDecode(url, &r)
return r.Results, err
}
36 changes: 8 additions & 28 deletions watchlists.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package robinhood

import (
"encoding/json"
"sync"
)

Expand All @@ -17,58 +16,41 @@ type Watchlist struct {

// GetWatchlists retrieves the watchlists for a given set of credentials/accounts.
func (c *Client) GetWatchlists() ([]Watchlist, error) {
res, err := c.Get(epBase + "watchlists/")
var r struct{ Results []Watchlist }
err := c.GetAndDecode(epWatchlists, &r)
if err != nil {
return nil, err
}
defer res.Body.Close()

var r struct{ Results []Watchlist }
err = json.NewDecoder(res.Body).Decode(&r)
if r.Results != nil {
for i := range r.Results {
r.Results[i].Client = c
}
}
return r.Results, err
return r.Results, nil
}

// GetInstruments returns the list of Instruments associated with a Watchlist.
func (w *Watchlist) GetInstruments() ([]Instrument, error) {
res, err := w.Client.Get(w.URL)
if err != nil {
return nil, err
}
defer res.Body.Close()

var r struct {
Results []struct {
Instrument, URL string
}
}

err = json.NewDecoder(res.Body).Decode(&r)
err := w.Client.GetAndDecode(w.URL, &r)
if err != nil {
return nil, err
}

insts := make([]Instrument, len(r.Results))
insts := make([]*Instrument, len(r.Results))
wg := &sync.WaitGroup{}
wg.Add(len(r.Results))

for i := range r.Results {
go func(i int) {
defer wg.Done()

url := r.Results[i].Instrument
res, err := w.Client.Get(url)
if err != nil {
return
}
defer res.Body.Close()

var inst Instrument
err = json.NewDecoder(res.Body).Decode(&inst)
inst, err := w.Client.GetInstrument(r.Results[i].Instrument)
if err != nil {
return
}
Expand All @@ -82,10 +64,8 @@ func (w *Watchlist) GetInstruments() ([]Instrument, error) {
// Filter slice for empties (if error)
retInsts := []Instrument{}
for _, inst := range insts {
if (inst != Instrument{}) {
}
{
retInsts = append(retInsts, inst)
if inst != nil {
retInsts = append(retInsts, *inst)
}
}

Expand Down

0 comments on commit 29b3ab9

Please sign in to comment.