Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

De-lint codebase #2

Merged
merged 1 commit into from
Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,12 @@ linters:
- varcheck
- wastedassign
- whitespace
- gochecknoinits
# - tagliatelle

# Disabled linters, due to being misaligned with Go practices
# - exhaustivestruct
# - gochecknoglobals
# - gochecknoinits
# - goconst
# - godox
# - goerr113
Expand Down
1 change: 0 additions & 1 deletion cmd/example/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ func main() {
Price: 1.0,
Quantity: 1,
})

if err != nil {
log.Fatalf("buy failed: %v", err)
}
Expand Down
10 changes: 5 additions & 5 deletions pkg/roho/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package roho

import "context"

// Account holds the basic account details relevant to the RobinHood API
// Account holds the basic account details relevant to the RobinHood API.
type Account struct {
Meta
AccountNumber string `json:"account_number"`
Expand All @@ -28,7 +28,7 @@ type Account struct {
WithdrawalHalted bool `json:"withdrawal_halted"`
}

// CashBalances reflect the amount of cash available
// CashBalances reflect the amount of cash available.
type CashBalances struct {
Meta
BuyingPower float64 `json:"buying_power,string"`
Expand All @@ -39,7 +39,7 @@ type CashBalances struct {
UnsettledFunds float64 `json:"unsettled_funds,string"`
}

// MarginBalances reflect the balance available in margin accounts
// MarginBalances reflect the balance available in margin accounts.
type MarginBalances struct {
Meta
Cash float64 `json:"cash,string"`
Expand Down Expand Up @@ -70,14 +70,14 @@ func (c *Client) Accounts(ctx context.Context) ([]Account, error) {
return r.Results, err
}

// CryptoAccount holds the basic account details relevant to robinhood API
// CryptoAccount holds the basic account details relevant to robinhood API.
type CryptoAccount struct {
ID string `json:"id"`
Status string `json:"status"`
UserID string `json:"user_id"`
}

// GetCryptoAccounts will return associated cryto account
// CryptoAccounts will return associated crypto account.
func (c *Client) CryptoAccounts(ctx context.Context) ([]CryptoAccount, error) {
var r struct{ Results []CryptoAccount }
err := c.get(ctx, cryptoURL("accounts"), &r)
Expand Down
4 changes: 2 additions & 2 deletions pkg/roho/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ func cryptoURL(s string) string {
// call retrieves from the endpoint and unmarshals resulting json into
// the provided destination interface, which must be a pointer.
func (c *Client) get(ctx context.Context, url string, dest interface{}) error {
req, err := http.NewRequest("GET", url, nil)
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return err
}

return c.call(ctx, req, dest)
}

// ErrorMap encapsulates the helpful error messages returned by the API server
// ErrorMap encapsulates the helpful error messages returned by the API server.
type ErrorMap map[string]interface{}

func (e ErrorMap) Error() string {
Expand Down
22 changes: 9 additions & 13 deletions pkg/roho/creds.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,6 @@ import (
"golang.org/x/oauth2"
)

var defaultPath = ""

func init() {
u, err := user.Current()
if err == nil {
defaultPath = path.Join(u.HomeDir, ".config", "roho.token")
}
}

// A CredsCacher takes user credentials and a file path. The token obtained
// from the RobinHood API will be cached at the file path, and a new token will
// not be obtained.
Expand All @@ -34,14 +25,19 @@ type CredsCacher struct {
// when retrieving their token.
func (c *CredsCacher) Token() (*oauth2.Token, error) {
if c.Path == "" {
c.Path = defaultPath
u, err := user.Current()
if err != nil {
return nil, fmt.Errorf("user lookup failed: %w", err)
}

c.Path = path.Join(u.HomeDir, ".config", "roho.token")
}

mustLogin := false

err := os.MkdirAll(path.Dir(c.Path), 0750)
err := os.MkdirAll(path.Dir(c.Path), 0o750)
if err != nil {
return nil, fmt.Errorf("error creating path for token: %s", err)
return nil, fmt.Errorf("error creating path for token: %w", err)
}

_, err = os.Stat(c.Path)
Expand Down Expand Up @@ -72,7 +68,7 @@ func (c *CredsCacher) Token() (*oauth2.Token, error) {
return nil, err
}

f, err := os.OpenFile(c.Path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0640)
f, err := os.OpenFile(c.Path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o640)
if err != nil {
return nil, err
}
Expand Down
16 changes: 7 additions & 9 deletions pkg/roho/crypto_order.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@ package roho
import (
"bytes"
"context"
"encoding/json"
"fmt"
"math"

"encoding/json"
"net/http"

"github.com/google/uuid"
"github.com/pkg/errors"
)

// CryptoOrder is the payload to create a crypto currency order
// CryptoOrder is the payload to create a crypto currency order.
type CryptoOrder struct {
AccountID string `json:"account_id,omitempty"`
CurrencyPairID string `json:"currency_pair_id,omitempty"`
Expand All @@ -25,7 +24,7 @@ type CryptoOrder struct {
Type string `json:"type,omitempty"`
}

// CryptoOrderOutput holds the response from api
// CryptoOrderOutput holds the response from api.
type CryptoOrderOutput struct {
Meta
Account string `json:"account"`
Expand All @@ -49,7 +48,7 @@ type CryptoOrderOutput struct {
client *Client
}

// CryptoOrderOpts encapsulates differences between order types
// CryptoOrderOpts encapsulates differences between order types.
type CryptoOrderOpts struct {
Side OrderSide
Type OrderType
Expand All @@ -61,9 +60,9 @@ type CryptoOrderOpts struct {
Stop, Force bool
}

// CryptoOrder will actually place the order
// CryptoOrder will actually place the order.
func (c *Client) CryptoOrder(ctx context.Context, cryptoPair CryptoCurrencyPair, o CryptoOrderOpts) (*CryptoOrderOutput, error) {
var quantity = math.Round(o.AmountInDollars / o.Price)
quantity := math.Round(o.AmountInDollars / o.Price)
a := CryptoOrder{
AccountID: c.CryptoAccount.ID,
CurrencyPairID: cryptoPair.ID,
Expand All @@ -76,12 +75,11 @@ func (c *Client) CryptoOrder(ctx context.Context, cryptoPair CryptoCurrencyPair,
}

payload, err := json.Marshal(a)

if err != nil {
return nil, err
}

post, err := http.NewRequest("POST", cryptoURL("orders"), bytes.NewReader(payload))
post, err := http.NewRequestWithContext(ctx, "POST", cryptoURL("orders"), bytes.NewReader(payload))
if err != nil {
return nil, fmt.Errorf("could not create Crypto http.Request: %w", err)
}
Expand Down
14 changes: 6 additions & 8 deletions pkg/roho/currency_pairs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ package roho
import (
"context"
"errors"

"fmt"
)

// CryptoCurrencyPair represent all availabe crypto currencies and whether they are tradeable or not
type CryptoCurrencyPair struct {
CyrptoAssetCurrency AssetCurrency `json:"asset_currency"`
ID string `json:"id"`
Expand All @@ -20,7 +18,7 @@ type CryptoCurrencyPair struct {
Tradability string `json:"tradability"`
}

// QuoteCurrency holds info about currency you can use to buy the cyrpto currency
// QuoteCurrency holds info about currency you can use to buy the cyrpto currency.
type QuoteCurrency struct {
Code string `json:"code"`
ID string `json:"id"`
Expand All @@ -29,7 +27,7 @@ type QuoteCurrency struct {
Type string `json:"type"`
}

// AssetCurrency has code and id of cryptocurrency
// AssetCurrency has code and id of cryptocurrency.
type AssetCurrency struct {
BrandColor string `json:"brand_color"`
Code string `json:"code"`
Expand All @@ -38,19 +36,19 @@ type AssetCurrency struct {
Name string `json:"name"`
}

// GetCryptoCurrencyPairs will give which crypto currencies are tradeable and corresponding ids
// CryptoCurrencyPairs will give which crypto currencies are tradeable and corresponding ids.
func (c *Client) CryptoCurrencyPairs(ctx context.Context) ([]CryptoCurrencyPair, error) {
var r struct{ Results []CryptoCurrencyPair }
err := c.get(ctx, cryptoURL("currency_pairs"), &r)
return r.Results, err
}

// GetCryptoInstrument will take standard crypto symbol and return usable information
// to place the order
// CryptoInstrument will take standard crypto symbol and return usable information
// to place the order.
func (c *Client) CryptoInstrument(ctx context.Context, symbol string) (*CryptoCurrencyPair, error) {
allPairs, err := c.CryptoCurrencyPairs(ctx)
if err != nil {
return nil, fmt.Errorf("crypto currency pairs: %v", err)
return nil, fmt.Errorf("crypto currency pairs: %w", err)
}

for _, pair := range allPairs {
Expand Down
6 changes: 3 additions & 3 deletions pkg/roho/instrument.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type Instrument struct {
MinTickSize interface{} `json:"min_tick_size"`
Name string `json:"name"`
Quote string `json:"quote"`
RhsTradability string `json:"rhs_tradability"`
RHSTRadability string `json:"rhs_tradability"`
SimpleName interface{} `json:"simple_name"`
Splits string `json:"splits"`
State string `json:"state"`
Expand All @@ -42,7 +42,7 @@ func (i Instrument) OrderSymbol() string {
return i.Symbol
}

// GetInstrument returns an Instrument given a URL
// GetInstrument returns an Instrument given a URL.
func (c *Client) Instrument(ctx context.Context, instURL string) (*Instrument, error) {
var i Instrument
err := c.get(ctx, instURL, &i)
Expand All @@ -52,7 +52,7 @@ func (c *Client) Instrument(ctx context.Context, instURL string) (*Instrument, e
return &i, err
}

// Lookup returns an Instrument given a ticker symbol
// Lookup returns an Instrument given a ticker symbol.
func (c *Client) Lookup(ctx context.Context, sym string) (*Instrument, error) {
var i struct {
Results []Instrument
Expand Down
6 changes: 3 additions & 3 deletions pkg/roho/marketdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
)

type EntryPrice struct {
Amount string
Currency_code string
Amount string
CurrencyCode string `json:"currency_code"`
}

type PriceBookEntry struct {
Expand All @@ -24,7 +24,7 @@ type PriceBookData struct {
UpdatedAt string `json:"updated_at"`
}

// Pricebook get the current snapshot of the pricebook data
// Pricebook get the current snapshot of the pricebook data.
func (c *Client) Pricebook(ctx context.Context, instrumentID string) (*PriceBookData, error) {
var out PriceBookData
err := c.get(ctx, fmt.Sprintf("%spricebook/snapshots/%s/", baseURL("marketdata"), instrumentID), &out)
Expand Down
13 changes: 5 additions & 8 deletions pkg/roho/oauth.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package roho

import (
"context"
"encoding/json"
"fmt"
"net/http"
Expand All @@ -15,15 +16,15 @@ import (
// DefaultClientID is used by the website.
const DefaultClientID = "c82SH0WZOsabOXGP2sxqcj34FxkvfnWRZBKlBjFS"

// OAuth implements oauth2 using the robinhood implementation
// OAuth implements oauth2 using the robinhood implementation.
type OAuth struct {
Endpoint, ClientID, Username, Password, MFA string
}

// ErrMFARequired indicates the MFA was required but not provided.
var ErrMFARequired = fmt.Errorf("Two Factor Auth code required and not supplied")
var ErrMFARequired = fmt.Errorf("two-factor auth code required and not supplied")

// Token implements TokenSource
// Token implements TokenSource.
func (p *OAuth) Token() (*oauth2.Token, error) {
cliID := p.ClientID
if cliID == "" {
Expand All @@ -46,11 +47,7 @@ func (p *OAuth) Token() (*oauth2.Token, error) {
v.Add("mfa_code", p.MFA)
}

req, err := http.NewRequest(
"POST",
u.String(),
strings.NewReader(v.Encode()),
)
req, err := http.NewRequestWithContext(context.Background(), "POST", u.String(), strings.NewReader(v.Encode()))
if err != nil {
return nil, errors.Wrap(err, "could not create request")
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/roho/optiondirection.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import (
)

// OptionDirection is a type for whether an option order is opening or closing
// an option position
// an option position.
type OptionDirection int

// MarshalJSON implements json.Marshaler
// MarshalJSON implements json.Marshaler.
func (o OptionDirection) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("%q", strings.ToLower(o.String()))), nil
}

//go:generate stringer -type OptionDirection
// The two directions
// The two directions.
const (
Debit OptionDirection = iota
Credit
Expand Down
9 changes: 4 additions & 5 deletions pkg/roho/options-order.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/google/uuid"
)

// OptionsOrderOpts encapsulates common Options order choices
// OptionsOrderOpts encapsulates common Options order choices.
type OptionsOrderOpts struct {
Quantity float64
Price float64
Expand All @@ -19,7 +19,7 @@ type OptionsOrderOpts struct {
Side OrderSide
}

// optionInput is the input object to the RobinHood API
// optionInput is the input object to the RobinHood API.
type optionInput struct {
Account string `json:"account"`
Direction OptionDirection `json:"direction"`
Expand Down Expand Up @@ -73,7 +73,7 @@ func (c *Client) OrderOptions(ctx context.Context, q *OptionInstrument, o Option
return nil, err
}

req, err := http.NewRequest("POST", baseURL("options")+"orders/", bytes.NewReader(bs))
req, err := http.NewRequestWithContext(ctx, "POST", baseURL("options")+"orders/", bytes.NewReader(bs))
if err != nil {
return nil, err
}
Expand All @@ -87,7 +87,7 @@ func (c *Client) OrderOptions(ctx context.Context, q *OptionInstrument, o Option
return out, nil
}

// GetOptionsOrders returns all outstanding options orders
// GetOptionsOrders returns all outstanding options orders.
func (c *Client) OptionsOrders(ctx context.Context) (json.RawMessage, error) {
var o json.RawMessage
err := c.get(ctx, baseURL("options")+"orders/", &o)
Expand All @@ -96,5 +96,4 @@ func (c *Client) OptionsOrders(ctx context.Context) (json.RawMessage, error) {
}

return o, nil

}
Loading