From 4294c684af06fe0a1584a0db711ff928756fb2aa Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Thu, 23 Nov 2017 10:03:39 +1100 Subject: [PATCH] Fixed linter issues and added testing. --- exchanges/lakebtc/lakebtc.go | 185 +++++++++++++---------------- exchanges/lakebtc/lakebtc_test.go | 113 ++++++++++++++++++ exchanges/lakebtc/lakebtc_types.go | 43 ++++--- 3 files changed, 226 insertions(+), 115 deletions(-) create mode 100644 exchanges/lakebtc/lakebtc_test.go diff --git a/exchanges/lakebtc/lakebtc.go b/exchanges/lakebtc/lakebtc.go index 639619d2..402ada43 100644 --- a/exchanges/lakebtc/lakebtc.go +++ b/exchanges/lakebtc/lakebtc.go @@ -15,26 +15,28 @@ import ( ) const ( - LAKEBTC_API_URL = "https://api.lakebtc.com/api_v2" - LAKEBTC_API_VERSION = "2" - LAKEBTC_TICKER = "ticker" - LAKEBTC_ORDERBOOK = "bcorderbook" - LAKEBTC_TRADES = "bctrades" - LAKEBTC_GET_ACCOUNT_INFO = "getAccountInfo" - LAKEBTC_BUY_ORDER = "buyOrder" - LAKEBTC_SELL_ORDER = "sellOrder" - LAKEBTC_OPEN_ORDERS = "openOrders" - LAKEBTC_GET_ORDERS = "getOrders" - LAKEBTC_CANCEL_ORDER = "cancelOrder" - LAKEBTC_GET_TRADES = "getTrades" - LAKEBTC_GET_EXTERNAL_ACCOUNTS = "getExternalAccounts" - LAKEBTC_CREATE_WITHDRAW = "createWithdraw" + lakeBTCAPIURL = "https://api.lakebtc.com/api_v2" + lakeBTCAPIVersion = "2" + lakeBTCTicker = "ticker" + lakeBTCOrderbook = "bcorderbook" + lakeBTCTrades = "bctrades" + lakeBTCGetAccountInfo = "getAccountInfo" + lakeBTCBuyOrder = "buyOrder" + lakeBTCSellOrder = "sellOrder" + lakeBTCOpenOrders = "openOrders" + lakeBTCGetOrders = "getOrders" + lakeBTCCancelOrder = "cancelOrder" + lakeBTCGetTrades = "getTrades" + lakeBTCGetExternalAccounts = "getExternalAccounts" + lakeBTCCreateWithdraw = "createWithdraw" ) +// LakeBTC is the overarching type across the LakeBTC package type LakeBTC struct { exchange.Base } +// SetDefaults sets LakeBTC defaults func (l *LakeBTC) SetDefaults() { l.Name = "LakeBTC" l.Enabled = false @@ -50,6 +52,7 @@ func (l *LakeBTC) SetDefaults() { l.AssetTypes = []string{ticker.Spot} } +// Setup sets exchange configuration profile func (l *LakeBTC) Setup(exch config.ExchangeConfig) { if !exch.Enabled { l.SetEnabled(false) @@ -74,26 +77,28 @@ func (l *LakeBTC) Setup(exch config.ExchangeConfig) { } } +// GetFee returns maker or taker fee func (l *LakeBTC) GetFee(maker bool) float64 { if maker { return l.MakerFee - } else { - return l.TakerFee } + return l.TakerFee } -func (l *LakeBTC) GetTicker() (map[string]LakeBTCTicker, error) { - response := make(map[string]LakeBTCTickerResponse) - path := fmt.Sprintf("%s/%s", LAKEBTC_API_URL, LAKEBTC_TICKER) - err := common.SendHTTPGetRequest(path, true, l.Verbose, &response) - if err != nil { +// GetTicker returns the current ticker from lakeBTC +func (l *LakeBTC) GetTicker() (map[string]Ticker, error) { + response := make(map[string]TickerResponse) + path := fmt.Sprintf("%s/%s", lakeBTCAPIURL, lakeBTCTicker) + + if err := common.SendHTTPGetRequest(path, true, l.Verbose, &response); err != nil { return nil, err } - result := make(map[string]LakeBTCTicker) + + result := make(map[string]Ticker) var addresses []string for k, v := range response { - var ticker LakeBTCTicker + var ticker Ticker key := common.StringToUpper(k) if v.Ask != nil { ticker.Ask, _ = strconv.ParseFloat(v.Ask.(string), 64) @@ -119,18 +124,19 @@ func (l *LakeBTC) GetTicker() (map[string]LakeBTCTicker, error) { return result, nil } -func (l *LakeBTC) GetOrderBook(currency string) (LakeBTCOrderbook, error) { +// GetOrderBook returns the order book from LakeBTC +func (l *LakeBTC) GetOrderBook(currency string) (Orderbook, error) { type Response struct { Bids [][]string `json:"bids"` Asks [][]string `json:"asks"` } - path := fmt.Sprintf("%s/%s?symbol=%s", LAKEBTC_API_URL, LAKEBTC_ORDERBOOK, common.StringToLower(currency)) + path := fmt.Sprintf("%s/%s?symbol=%s", lakeBTCAPIURL, lakeBTCOrderbook, common.StringToLower(currency)) resp := Response{} err := common.SendHTTPGetRequest(path, true, l.Verbose, &resp) if err != nil { - return LakeBTCOrderbook{}, err + return Orderbook{}, err } - orderbook := LakeBTCOrderbook{} + orderbook := Orderbook{} for _, x := range resp.Bids { price, err := strconv.ParseFloat(x[0], 64) @@ -143,7 +149,7 @@ func (l *LakeBTC) GetOrderBook(currency string) (LakeBTCOrderbook, error) { log.Println(err) continue } - orderbook.Bids = append(orderbook.Bids, LakeBTCOrderbookStructure{price, amount}) + orderbook.Bids = append(orderbook.Bids, OrderbookStructure{price, amount}) } for _, x := range resp.Asks { @@ -157,45 +163,40 @@ func (l *LakeBTC) GetOrderBook(currency string) (LakeBTCOrderbook, error) { log.Println(err) continue } - orderbook.Asks = append(orderbook.Asks, LakeBTCOrderbookStructure{price, amount}) + orderbook.Asks = append(orderbook.Asks, OrderbookStructure{price, amount}) } return orderbook, nil } -func (l *LakeBTC) GetTradeHistory(currency string) ([]LakeBTCTradeHistory, error) { - path := fmt.Sprintf("%s/%s?symbol=%s", LAKEBTC_API_URL, LAKEBTC_TRADES, common.StringToLower(currency)) - resp := []LakeBTCTradeHistory{} - err := common.SendHTTPGetRequest(path, true, l.Verbose, &resp) - if err != nil { - return nil, err - } - return resp, nil +// GetTradeHistory returns the trade history for a given currency pair +func (l *LakeBTC) GetTradeHistory(currency string) ([]TradeHistory, error) { + path := fmt.Sprintf("%s/%s?symbol=%s", lakeBTCAPIURL, lakeBTCTrades, common.StringToLower(currency)) + resp := []TradeHistory{} + + return resp, common.SendHTTPGetRequest(path, true, l.Verbose, &resp) } -func (l *LakeBTC) GetAccountInfo() (LakeBTCAccountInfo, error) { - resp := LakeBTCAccountInfo{} - err := l.SendAuthenticatedHTTPRequest(LAKEBTC_GET_ACCOUNT_INFO, "", &resp) +// GetAccountInfo returns your current account information +func (l *LakeBTC) GetAccountInfo() (AccountInfo, error) { + resp := AccountInfo{} - if err != nil { - return resp, err - } - - return resp, nil + return resp, l.SendAuthenticatedHTTPRequest(lakeBTCGetAccountInfo, "", &resp) } -func (l *LakeBTC) Trade(orderType int, amount, price float64, currency string) (LakeBTCTrade, error) { - resp := LakeBTCTrade{} +// Trade executes an order on the exchange and returns trade inforamtion or an +// error +func (l *LakeBTC) Trade(orderType int, amount, price float64, currency string) (Trade, error) { + resp := Trade{} params := strconv.FormatFloat(price, 'f', -1, 64) + "," + strconv.FormatFloat(amount, 'f', -1, 64) + "," + currency - err := errors.New("") if orderType == 1 { - err = l.SendAuthenticatedHTTPRequest(LAKEBTC_BUY_ORDER, params, &resp) + if err := l.SendAuthenticatedHTTPRequest(lakeBTCBuyOrder, params, &resp); err != nil { + return resp, err + } } else { - err = l.SendAuthenticatedHTTPRequest(LAKEBTC_SELL_ORDER, params, &resp) - } - - if err != nil { - return resp, err + if err := l.SendAuthenticatedHTTPRequest(lakeBTCSellOrder, params, &resp); err != nil { + return resp, err + } } if resp.Result != "order received" { @@ -205,31 +206,26 @@ func (l *LakeBTC) Trade(orderType int, amount, price float64, currency string) ( return resp, nil } -func (l *LakeBTC) GetOpenOrders() ([]LakeBTCOpenOrders, error) { - orders := []LakeBTCOpenOrders{} - err := l.SendAuthenticatedHTTPRequest(LAKEBTC_OPEN_ORDERS, "", &orders) +// GetOpenOrders returns all open orders associated with your account +func (l *LakeBTC) GetOpenOrders() ([]OpenOrders, error) { + orders := []OpenOrders{} - if err != nil { - return nil, err - } - return orders, nil + return orders, l.SendAuthenticatedHTTPRequest(lakeBTCOpenOrders, "", &orders) } -func (l *LakeBTC) GetOrders(orders []int64) ([]LakeBTCOrders, error) { +// GetOrders returns your orders +func (l *LakeBTC) GetOrders(orders []int64) ([]Orders, error) { var ordersStr []string for _, x := range orders { ordersStr = append(ordersStr, strconv.FormatInt(x, 10)) } - resp := []LakeBTCOrders{} - err := l.SendAuthenticatedHTTPRequest(LAKEBTC_GET_ORDERS, common.JoinStrings(ordersStr, ","), &resp) - - if err != nil { - return nil, err - } - return resp, nil + resp := []Orders{} + return resp, + l.SendAuthenticatedHTTPRequest(lakeBTCGetOrders, common.JoinStrings(ordersStr, ","), &resp) } +// CancelOrder cancels an order by ID number and returns an error func (l *LakeBTC) CancelOrder(orderID int64) error { type Response struct { Result bool `json:"Result"` @@ -237,54 +233,45 @@ func (l *LakeBTC) CancelOrder(orderID int64) error { resp := Response{} params := strconv.FormatInt(orderID, 10) - err := l.SendAuthenticatedHTTPRequest(LAKEBTC_CANCEL_ORDER, params, &resp) + err := l.SendAuthenticatedHTTPRequest(lakeBTCCancelOrder, params, &resp) if err != nil { return err } if resp.Result != true { - return errors.New("Unable to cancel order.") + return errors.New("unable to cancel order") } - return nil } -func (l *LakeBTC) GetTrades(timestamp int64) ([]LakeBTCAuthenticaltedTradeHistory, error) { +// GetTrades returns trades associated with your account by timestamp +func (l *LakeBTC) GetTrades(timestamp int64) ([]AuthenticatedTradeHistory, error) { params := "" if timestamp != 0 { params = strconv.FormatInt(timestamp, 10) } - trades := []LakeBTCAuthenticaltedTradeHistory{} - err := l.SendAuthenticatedHTTPRequest(LAKEBTC_GET_TRADES, params, &trades) - if err != nil { - return nil, err - } - - return trades, nil + trades := []AuthenticatedTradeHistory{} + return trades, l.SendAuthenticatedHTTPRequest(lakeBTCGetTrades, params, &trades) } -/* Only for BTC */ -func (l *LakeBTC) GetExternalAccounts() ([]LakeBTCExternalAccounts, error) { - resp := []LakeBTCExternalAccounts{} - err := l.SendAuthenticatedHTTPRequest(LAKEBTC_GET_EXTERNAL_ACCOUNTS, "", &resp) - if err != nil { - return resp, err - } - return resp, nil +// GetExternalAccounts returns your external accounts WARNING: Only for BTC! +func (l *LakeBTC) GetExternalAccounts() ([]ExternalAccounts, error) { + resp := []ExternalAccounts{} + + return resp, l.SendAuthenticatedHTTPRequest(lakeBTCGetExternalAccounts, "", &resp) } -/* Only for BTC */ -func (l *LakeBTC) CreateWithdraw(amount float64, accountID int64) (LakeBTCWithdraw, error) { - resp := LakeBTCWithdraw{} +// CreateWithdraw allows your to withdraw to external account WARNING: Only for +// BTC! +func (l *LakeBTC) CreateWithdraw(amount float64, accountID int64) (Withdraw, error) { + resp := Withdraw{} params := strconv.FormatFloat(amount, 'f', -1, 64) + ",btc," + strconv.FormatInt(accountID, 10) - err := l.SendAuthenticatedHTTPRequest(LAKEBTC_CREATE_WITHDRAW, params, &resp) - if err != nil { - return resp, err - } - return resp, nil + + return resp, l.SendAuthenticatedHTTPRequest(lakeBTCCreateWithdraw, params, &resp) } +// SendAuthenticatedHTTPRequest sends an autheticated HTTP request to a LakeBTC func (l *LakeBTC) SendAuthenticatedHTTPRequest(method, params string, result interface{}) (err error) { if !l.AuthenticatedAPISupport { return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, l.Name) @@ -300,7 +287,7 @@ func (l *LakeBTC) SendAuthenticatedHTTPRequest(method, params string, result int hmac := common.GetHMAC(common.HashSHA1, []byte(req), []byte(l.APISecret)) if l.Verbose { - log.Printf("Sending POST request to %s calling method %s with params %s\n", LAKEBTC_API_URL, method, req) + log.Printf("Sending POST request to %s calling method %s with params %s\n", lakeBTCAPIURL, method, req) } postData := make(map[string]interface{}) @@ -318,7 +305,7 @@ func (l *LakeBTC) SendAuthenticatedHTTPRequest(method, params string, result int headers["Authorization"] = "Basic " + common.Base64Encode([]byte(l.APIKey+":"+common.HexEncodeToString(hmac))) headers["Content-Type"] = "application/json-rpc" - resp, err := common.SendHTTPRequest("POST", LAKEBTC_API_URL, headers, strings.NewReader(string(data))) + resp, err := common.SendHTTPRequest("POST", lakeBTCAPIURL, headers, strings.NewReader(string(data))) if err != nil { return err } @@ -342,10 +329,8 @@ func (l *LakeBTC) SendAuthenticatedHTTPRequest(method, params string, result int } err = common.JSONDecode([]byte(resp), &result) - if err != nil { return errors.New("unable to JSON Unmarshal response") } - return nil } diff --git a/exchanges/lakebtc/lakebtc_test.go b/exchanges/lakebtc/lakebtc_test.go new file mode 100644 index 00000000..8239c3bf --- /dev/null +++ b/exchanges/lakebtc/lakebtc_test.go @@ -0,0 +1,113 @@ +package lakebtc + +import ( + "testing" + + "github.com/thrasher-/gocryptotrader/config" +) + +var l LakeBTC + +// Please add your own APIkeys to do correct due diligence testing. +const ( + apiKey = "" + apiSecret = "" +) + +func TestSetDefaults(t *testing.T) { + l.SetDefaults() +} + +func TestSetup(t *testing.T) { + cfg := config.GetConfig() + cfg.LoadConfig("../../testdata/configtest.json") + lakebtcConfig, err := cfg.GetExchangeConfig("LakeBTC") + if err != nil { + t.Error("Test Failed - LakeBTC Setup() init error") + } + + lakebtcConfig.AuthenticatedAPISupport = true + lakebtcConfig.APIKey = apiKey + lakebtcConfig.APISecret = apiSecret + + l.Setup(lakebtcConfig) +} + +func TestGetFee(t *testing.T) { + if l.GetFee(false) != 0.2 { + t.Error("Test Failed - GetFee() error") + } + if l.GetFee(true) != 0.15 { + t.Error("Test Failed - GetFee() error") + } +} + +func TestGetTicker(t *testing.T) { + _, err := l.GetTicker() + if err != nil { + t.Error("Test Failed - GetTicker() error", err) + } +} + +func TestGetOrderBook(t *testing.T) { + _, err := l.GetOrderBook("BTCUSD") + if err != nil { + t.Error("Test Failed - GetOrderBook() error", err) + } +} + +func TestGetTradeHistory(t *testing.T) { + _, err := l.GetTradeHistory("BTCUSD") + if err != nil { + t.Error("Test Failed - GetTradeHistory() error", err) + } +} + +func TestTrade(t *testing.T) { + _, err := l.Trade(0, 0, 0, "USD") + if err == nil { + t.Error("Test Failed - Trade() error", err) + } +} + +func TestGetOpenOrders(t *testing.T) { + _, err := l.GetOpenOrders() + if err == nil { + t.Error("Test Failed - GetOpenOrders() error", err) + } +} + +func TestGetOrders(t *testing.T) { + _, err := l.GetOrders([]int64{1, 2}) + if err == nil { + t.Error("Test Failed - GetOrders() error", err) + } +} + +func TestCancelOrder(t *testing.T) { + err := l.CancelOrder(1337) + if err == nil { + t.Error("Test Failed - CancelOrder() error", err) + } +} + +func TestGetTrades(t *testing.T) { + _, err := l.GetTrades(1337) + if err == nil { + t.Error("Test Failed - GetTrades() error", err) + } +} + +func TestGetExternalAccounts(t *testing.T) { + _, err := l.GetExternalAccounts() + if err == nil { + t.Error("Test Failed - GetExternalAccounts() error", err) + } +} + +func TestCreateWithdraw(t *testing.T) { + _, err := l.CreateWithdraw(0, 1337) + if err == nil { + t.Error("Test Failed - CreateWithdraw() error", err) + } +} diff --git a/exchanges/lakebtc/lakebtc_types.go b/exchanges/lakebtc/lakebtc_types.go index ea8a7455..ffbf6fd1 100644 --- a/exchanges/lakebtc/lakebtc_types.go +++ b/exchanges/lakebtc/lakebtc_types.go @@ -1,6 +1,7 @@ package lakebtc -type LakeBTCTicker struct { +// Ticker holds ticker information +type Ticker struct { Last float64 Bid float64 Ask float64 @@ -9,18 +10,21 @@ type LakeBTCTicker struct { Volume float64 } -type LakeBTCOrderbookStructure struct { +// OrderbookStructure stores price and amount for order books +type OrderbookStructure struct { Price float64 Amount float64 } -type LakeBTCOrderbook struct { - Bids []LakeBTCOrderbookStructure `json:"bids"` - Asks []LakeBTCOrderbookStructure `json:"asks"` +// Orderbook contains arrays of orderbook information +type Orderbook struct { + Bids []OrderbookStructure `json:"bids"` + Asks []OrderbookStructure `json:"asks"` } -/* Silly hack due to API returning null instead of strings */ -type LakeBTCTickerResponse struct { +// TickerResponse stores temp response +// Silly hack due to API returning null instead of strings +type TickerResponse struct { Last interface{} Bid interface{} Ask interface{} @@ -29,14 +33,16 @@ type LakeBTCTickerResponse struct { Volume interface{} } -type LakeBTCTradeHistory struct { +// TradeHistory holds trade history data +type TradeHistory struct { Date int64 `json:"data"` Price float64 `json:"price,string"` Amount float64 `json:"amount,string"` TID int64 `json:"tid"` } -type LakeBTCAccountInfo struct { +// AccountInfo contains account information +type AccountInfo struct { Balance map[string]string `json:"balance"` Locked map[string]string `json:"locked"` Profile struct { @@ -46,12 +52,14 @@ type LakeBTCAccountInfo struct { } `json:"profile"` } -type LakeBTCTrade struct { +// Trade holds trade information +type Trade struct { ID int64 `json:"id"` Result string `json:"result"` } -type LakeBTCOpenOrders struct { +// OpenOrders stores full information on your open orders +type OpenOrders struct { ID int64 `json:"id"` Amount float64 `json:"amount,string"` Price float64 `json:"price,string"` @@ -60,7 +68,8 @@ type LakeBTCOpenOrders struct { At int64 `json:"at"` } -type LakeBTCOrders struct { +// Orders holds current order information +type Orders struct { ID int64 `json:"id"` OriginalAmount float64 `json:"original_amount,string"` Amount float64 `json:"amount,string"` @@ -71,14 +80,17 @@ type LakeBTCOrders struct { At int64 `json:"at"` } -type LakeBTCAuthenticaltedTradeHistory struct { +// AuthenticatedTradeHistory is a store of personalised auth trade history +type AuthenticatedTradeHistory struct { Type string `json:"type"` Symbol string `json:"symbol"` Amount float64 `json:"amount,string"` Total float64 `json:"total,string"` At int64 `json:"at"` } -type LakeBTCExternalAccounts struct { + +// ExternalAccounts holds external account information +type ExternalAccounts struct { ID int64 `json:"id,string"` Type string `json:"type"` Address string `json:"address"` @@ -88,7 +100,8 @@ type LakeBTCExternalAccounts struct { UpdatedAt int64 `json:"updated_at,string"` } -type LakeBTCWithdraw struct { +// Withdraw holds withdrawal information +type Withdraw struct { ID int64 `json:"id,string"` Amount float64 `json:"amount,string"` Currency string `json:"currency"`