From 10d5abacb3dfed457b11514a33f742c50abcd517 Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 09:00:30 +1100 Subject: [PATCH 01/12] Initial implementation of interface function for getting exchange history. --- exchanges/alphapoint/alphapoint_wrapper.go | 9 +++++++++ exchanges/anx/anx_wrapper.go | 8 ++++++++ exchanges/binance/binance_test.go | 5 ++++- exchanges/binance/binance_wrapper.go | 7 +++++++ exchanges/bitfinex/bitfinex_wrapper.go | 8 ++++++++ exchanges/bitflyer/bitflyer_wrapper.go | 7 +++++++ exchanges/bithumb/bithumb_wrapper.go | 7 +++++++ exchanges/bitstamp/bitstamp_wrapper.go | 8 ++++++++ exchanges/bittrex/bittrex_wrapper.go | 8 ++++++++ exchanges/btcc/btcc_wrapper.go | 8 ++++++++ exchanges/btcmarkets/btcmarkets_wrapper.go | 8 ++++++++ exchanges/coinut/coinut_wrapper.go | 8 ++++++++ exchanges/exchange.go | 11 +++++++++++ exchanges/exmo/exmo_wrapper.go | 8 ++++++++ exchanges/gdax/gdax_wrapper.go | 8 ++++++++ exchanges/gemini/gemini_wrapper.go | 8 ++++++++ exchanges/hitbtc/hitbtc_wrapper.go | 8 ++++++++ exchanges/huobi/huobi_wrapper.go | 8 ++++++++ exchanges/itbit/itbit_wrapper.go | 8 ++++++++ exchanges/kraken/kraken_wrapper.go | 8 ++++++++ exchanges/lakebtc/lakebtc_wrapper.go | 8 ++++++++ exchanges/liqui/liqui_wrapper.go | 8 ++++++++ exchanges/localbitcoins/localbitcoins_wrapper.go | 8 ++++++++ exchanges/okcoin/okcoin_wrapper.go | 8 ++++++++ exchanges/okex/okex_wrapper.go | 7 +++++++ exchanges/poloniex/poloniex_wrapper.go | 8 ++++++++ exchanges/wex/wex_wrapper.go | 8 ++++++++ exchanges/yobit/yobit_wrapper.go | 8 ++++++++ 28 files changed, 220 insertions(+), 1 deletion(-) diff --git a/exchanges/alphapoint/alphapoint_wrapper.go b/exchanges/alphapoint/alphapoint_wrapper.go index 62cfec72..2b706bc9 100644 --- a/exchanges/alphapoint/alphapoint_wrapper.go +++ b/exchanges/alphapoint/alphapoint_wrapper.go @@ -1,6 +1,8 @@ package alphapoint import ( + "errors" + "github.com/thrasher-/gocryptotrader/currency/pair" "github.com/thrasher-/gocryptotrader/exchanges" "github.com/thrasher-/gocryptotrader/exchanges/orderbook" @@ -86,3 +88,10 @@ func (a *Alphapoint) GetOrderbookEx(p pair.CurrencyPair, assetType string) (orde } return ob, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (a *Alphapoint) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/anx/anx_wrapper.go b/exchanges/anx/anx_wrapper.go index 9ca3191c..edbc176f 100644 --- a/exchanges/anx/anx_wrapper.go +++ b/exchanges/anx/anx_wrapper.go @@ -1,6 +1,7 @@ package anx import ( + "errors" "log" "strconv" @@ -134,3 +135,10 @@ func (a *ANX) GetExchangeAccountInfo() (exchange.AccountInfo, error) { response.ExchangeName = a.GetName() return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (a *ANX) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/binance/binance_test.go b/exchanges/binance/binance_test.go index a02a02c7..d73f74c2 100644 --- a/exchanges/binance/binance_test.go +++ b/exchanges/binance/binance_test.go @@ -1,6 +1,7 @@ package binance import ( + "log" "testing" "github.com/thrasher-/gocryptotrader/config" @@ -59,10 +60,12 @@ func TestGetRecentTrades(t *testing.T) { func TestGetHistoricalTrades(t *testing.T) { t.Parallel() - _, err := b.GetHistoricalTrades("BTCUSDT", 5, 1337) + b.Verbose = true + v, err := b.GetHistoricalTrades("BTCUSDT", 5, 1337) if err == nil { t.Error("Test Failed - Binance GetHistoricalTrades() error", err) } + log.Println(v) } func TestGetAggregatedTrades(t *testing.T) { diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 8656d486..b7187f28 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -120,3 +120,10 @@ func (b *Binance) GetExchangeAccountInfo() (exchange.AccountInfo, error) { var response exchange.AccountInfo return response, errors.New("not implemented") } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (b *Binance) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go index d1c61f35..cdaf22ce 100644 --- a/exchanges/bitfinex/bitfinex_wrapper.go +++ b/exchanges/bitfinex/bitfinex_wrapper.go @@ -1,6 +1,7 @@ package bitfinex import ( + "errors" "log" "net/url" @@ -156,3 +157,10 @@ func (b *Bitfinex) GetExchangeAccountInfo() (exchange.AccountInfo, error) { return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (b *Bitfinex) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/bitflyer/bitflyer_wrapper.go b/exchanges/bitflyer/bitflyer_wrapper.go index b17515ef..c0f48703 100644 --- a/exchanges/bitflyer/bitflyer_wrapper.go +++ b/exchanges/bitflyer/bitflyer_wrapper.go @@ -132,3 +132,10 @@ func (b *Bitflyer) GetExchangeAccountInfo() (exchange.AccountInfo, error) { return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (b *Bitflyer) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/bithumb/bithumb_wrapper.go b/exchanges/bithumb/bithumb_wrapper.go index 31572dc1..38ea884a 100644 --- a/exchanges/bithumb/bithumb_wrapper.go +++ b/exchanges/bithumb/bithumb_wrapper.go @@ -92,3 +92,10 @@ func (b *Bithumb) GetExchangeAccountInfo() (exchange.AccountInfo, error) { var response exchange.AccountInfo return response, errors.New("not implemented") } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (b *Bithumb) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/bitstamp/bitstamp_wrapper.go b/exchanges/bitstamp/bitstamp_wrapper.go index 7949a41e..4798226d 100644 --- a/exchanges/bitstamp/bitstamp_wrapper.go +++ b/exchanges/bitstamp/bitstamp_wrapper.go @@ -1,6 +1,7 @@ package bitstamp import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -122,3 +123,10 @@ func (b *Bitstamp) GetExchangeAccountInfo() (exchange.AccountInfo, error) { }) return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (b *Bitstamp) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/bittrex/bittrex_wrapper.go b/exchanges/bittrex/bittrex_wrapper.go index 4d2c08a7..e010dd05 100644 --- a/exchanges/bittrex/bittrex_wrapper.go +++ b/exchanges/bittrex/bittrex_wrapper.go @@ -1,6 +1,7 @@ package bittrex import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -147,3 +148,10 @@ func (b *Bittrex) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderb orderbook.ProcessOrderbook(b.GetName(), p, orderBook, assetType) return orderbook.GetOrderbook(b.Name, p, assetType) } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (b *Bittrex) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/btcc/btcc_wrapper.go b/exchanges/btcc/btcc_wrapper.go index 2702c4ff..086effc2 100644 --- a/exchanges/btcc/btcc_wrapper.go +++ b/exchanges/btcc/btcc_wrapper.go @@ -1,6 +1,7 @@ package btcc import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -126,3 +127,10 @@ func (b *BTCC) GetExchangeAccountInfo() (exchange.AccountInfo, error) { response.ExchangeName = b.GetName() return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (b *BTCC) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/btcmarkets/btcmarkets_wrapper.go b/exchanges/btcmarkets/btcmarkets_wrapper.go index 289194e9..aa31bf55 100644 --- a/exchanges/btcmarkets/btcmarkets_wrapper.go +++ b/exchanges/btcmarkets/btcmarkets_wrapper.go @@ -1,6 +1,7 @@ package btcmarkets import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -126,3 +127,10 @@ func (b *BTCMarkets) GetExchangeAccountInfo() (exchange.AccountInfo, error) { } return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (b *BTCMarkets) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go index 9570ace4..feb64f97 100644 --- a/exchanges/coinut/coinut_wrapper.go +++ b/exchanges/coinut/coinut_wrapper.go @@ -1,6 +1,7 @@ package coinut import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -123,3 +124,10 @@ func (c *COINUT) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbo orderbook.ProcessOrderbook(c.GetName(), p, orderBook, assetType) return orderbook.GetOrderbook(c.Name, p, assetType) } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (c *COINUT) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/exchange.go b/exchanges/exchange.go index 7ca150c8..2dc502de 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -35,6 +35,16 @@ type AccountCurrencyInfo struct { Hold float64 } +// TradeHistory holds exchange history data +type TradeHistory struct { + Timestamp int64 + TID int64 + Price float64 + Amount float64 + Exchange string + Type string +} + // Base stores the individual exchange information type Base struct { Name string @@ -74,6 +84,7 @@ type IBotExchange interface { GetExchangeAccountInfo() (AccountInfo, error) GetAuthenticatedAPISupport() bool SetCurrencies(pairs []pair.CurrencyPair, enabledPairs bool) error + GetExchangeHistory(pair.CurrencyPair, string) ([]TradeHistory, error) } // SetAssetTypes checks the exchange asset types (whether it supports SPOT, diff --git a/exchanges/exmo/exmo_wrapper.go b/exchanges/exmo/exmo_wrapper.go index 0bfbe815..ca887ed4 100644 --- a/exchanges/exmo/exmo_wrapper.go +++ b/exchanges/exmo/exmo_wrapper.go @@ -1,6 +1,7 @@ package exmo import ( + "errors" "log" "strconv" @@ -154,3 +155,10 @@ func (e *EXMO) GetExchangeAccountInfo() (exchange.AccountInfo, error) { } return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (e *EXMO) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/gdax/gdax_wrapper.go b/exchanges/gdax/gdax_wrapper.go index 6487162a..dfde1c69 100644 --- a/exchanges/gdax/gdax_wrapper.go +++ b/exchanges/gdax/gdax_wrapper.go @@ -1,6 +1,7 @@ package gdax import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -126,3 +127,10 @@ func (g *GDAX) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook orderbook.ProcessOrderbook(g.GetName(), p, orderBook, assetType) return orderbook.GetOrderbook(g.Name, p, assetType) } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (g *GDAX) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/gemini/gemini_wrapper.go b/exchanges/gemini/gemini_wrapper.go index 93254df3..4730813b 100644 --- a/exchanges/gemini/gemini_wrapper.go +++ b/exchanges/gemini/gemini_wrapper.go @@ -1,6 +1,7 @@ package gemini import ( + "errors" "log" "net/url" @@ -105,3 +106,10 @@ func (g *Gemini) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbo orderbook.ProcessOrderbook(g.GetName(), p, orderBook, assetType) return orderbook.GetOrderbook(g.Name, p, assetType) } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (g *Gemini) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/hitbtc/hitbtc_wrapper.go b/exchanges/hitbtc/hitbtc_wrapper.go index cd4b4b02..2eb7d025 100644 --- a/exchanges/hitbtc/hitbtc_wrapper.go +++ b/exchanges/hitbtc/hitbtc_wrapper.go @@ -1,6 +1,7 @@ package hitbtc import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -137,3 +138,10 @@ func (p *HitBTC) GetExchangeAccountInfo() (exchange.AccountInfo, error) { } return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (h *HitBTC) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index f36257f1..47239f11 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -1,6 +1,7 @@ package huobi import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -142,3 +143,10 @@ func (h *HUOBI) GetExchangeAccountInfo() (exchange.AccountInfo, error) { response.ExchangeName = h.GetName() return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (h *HUOBI) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/itbit/itbit_wrapper.go b/exchanges/itbit/itbit_wrapper.go index 6c7ac68f..6d547e8d 100644 --- a/exchanges/itbit/itbit_wrapper.go +++ b/exchanges/itbit/itbit_wrapper.go @@ -1,6 +1,7 @@ package itbit import ( + "errors" "log" "strconv" @@ -107,3 +108,10 @@ func (i *ItBit) GetExchangeAccountInfo() (exchange.AccountInfo, error) { response.ExchangeName = i.GetName() return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (i *ItBit) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go index c67b5472..536fb1db 100644 --- a/exchanges/kraken/kraken_wrapper.go +++ b/exchanges/kraken/kraken_wrapper.go @@ -1,6 +1,7 @@ package kraken import ( + "errors" "fmt" "log" "net/url" @@ -178,3 +179,10 @@ func (k *Kraken) GetExchangeAccountInfo() (exchange.AccountInfo, error) { response.ExchangeName = k.GetName() return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (k *Kraken) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/lakebtc/lakebtc_wrapper.go b/exchanges/lakebtc/lakebtc_wrapper.go index ad598cc3..cda61565 100644 --- a/exchanges/lakebtc/lakebtc_wrapper.go +++ b/exchanges/lakebtc/lakebtc_wrapper.go @@ -1,6 +1,7 @@ package lakebtc import ( + "errors" "log" "strconv" @@ -107,3 +108,10 @@ func (l *LakeBTC) GetExchangeAccountInfo() (exchange.AccountInfo, error) { } return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (l *LakeBTC) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/liqui/liqui_wrapper.go b/exchanges/liqui/liqui_wrapper.go index 8ecb1402..ef750603 100644 --- a/exchanges/liqui/liqui_wrapper.go +++ b/exchanges/liqui/liqui_wrapper.go @@ -1,6 +1,7 @@ package liqui import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -125,3 +126,10 @@ func (l *Liqui) GetExchangeAccountInfo() (exchange.AccountInfo, error) { return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (l *Liqui) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/localbitcoins/localbitcoins_wrapper.go b/exchanges/localbitcoins/localbitcoins_wrapper.go index 034c296f..72d3c859 100644 --- a/exchanges/localbitcoins/localbitcoins_wrapper.go +++ b/exchanges/localbitcoins/localbitcoins_wrapper.go @@ -1,6 +1,7 @@ package localbitcoins import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/currency/pair" @@ -98,3 +99,10 @@ func (l *LocalBitcoins) GetExchangeAccountInfo() (exchange.AccountInfo, error) { response.Currencies = append(response.Currencies, exchangeCurrency) return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (l *LocalBitcoins) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/okcoin/okcoin_wrapper.go b/exchanges/okcoin/okcoin_wrapper.go index 547d9a15..4fff95be 100644 --- a/exchanges/okcoin/okcoin_wrapper.go +++ b/exchanges/okcoin/okcoin_wrapper.go @@ -1,6 +1,7 @@ package okcoin import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -140,3 +141,10 @@ func (o *OKCoin) GetExchangeAccountInfo() (exchange.AccountInfo, error) { return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (o *OKCoin) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/okex/okex_wrapper.go b/exchanges/okex/okex_wrapper.go index a2821fad..3ceeb607 100644 --- a/exchanges/okex/okex_wrapper.go +++ b/exchanges/okex/okex_wrapper.go @@ -146,3 +146,10 @@ func (o *OKEX) GetExchangeAccountInfo() (exchange.AccountInfo, error) { var response exchange.AccountInfo return response, errors.New("not implemented") } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (o *OKEX) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/poloniex/poloniex_wrapper.go b/exchanges/poloniex/poloniex_wrapper.go index e269562d..b27e2f8f 100644 --- a/exchanges/poloniex/poloniex_wrapper.go +++ b/exchanges/poloniex/poloniex_wrapper.go @@ -1,6 +1,7 @@ package poloniex import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -137,3 +138,10 @@ func (p *Poloniex) GetExchangeAccountInfo() (exchange.AccountInfo, error) { } return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (po *Poloniex) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/wex/wex_wrapper.go b/exchanges/wex/wex_wrapper.go index d66f182b..05b27c28 100644 --- a/exchanges/wex/wex_wrapper.go +++ b/exchanges/wex/wex_wrapper.go @@ -1,6 +1,7 @@ package wex import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -112,3 +113,10 @@ func (w *WEX) GetExchangeAccountInfo() (exchange.AccountInfo, error) { return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (w *WEX) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} diff --git a/exchanges/yobit/yobit_wrapper.go b/exchanges/yobit/yobit_wrapper.go index c2739cc0..3bb6fa63 100644 --- a/exchanges/yobit/yobit_wrapper.go +++ b/exchanges/yobit/yobit_wrapper.go @@ -1,6 +1,7 @@ package yobit import ( + "errors" "log" "github.com/thrasher-/gocryptotrader/common" @@ -118,3 +119,10 @@ func (y *Yobit) GetExchangeAccountInfo() (exchange.AccountInfo, error) { return response, nil } + +// GetExchangeHistory returns historic trade data since exchange opening. +func (y *Yobit) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} From 17df327c0fa93446a78bf1389b0cb64d9bb28c11 Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 10:03:15 +1100 Subject: [PATCH 02/12] Fixed linter issues for ANX --- exchanges/anx/anx.go | 94 +++++++++++++++++++++----------------- exchanges/anx/anx_types.go | 36 +++++++++------ 2 files changed, 74 insertions(+), 56 deletions(-) diff --git a/exchanges/anx/anx.go b/exchanges/anx/anx.go index da9c6202..2254121f 100644 --- a/exchanges/anx/anx.go +++ b/exchanges/anx/anx.go @@ -15,24 +15,26 @@ import ( ) const ( - ANX_API_URL = "https://anxpro.com/" - ANX_API_VERSION = "3" - ANX_APIKEY = "apiKey" - ANX_DATA_TOKEN = "dataToken" - ANX_ORDER_NEW = "order/new" - ANX_ORDER_INFO = "order/info" - ANX_SEND = "send" - ANX_SUBACCOUNT_NEW = "subaccount/new" - ANX_RECEIVE_ADDRESS = "receive" - ANX_CREATE_ADDRESS = "receive/create" - ANX_TICKER = "money/ticker" - ANX_DEPTH = "money/depth/full" + anxAPIURL = "https://anxpro.com/" + anxAPIVersion = "3" + anxAPIKey = "apiKey" + anxDataToken = "dataToken" + anxOrderNew = "order/new" + anxOrderInfo = "order/info" + anxSend = "send" + anxSubaccountNew = "subaccount/new" + anxReceieveAddress = "receive" + anxCreateAddress = "receive/create" + anxTicker = "money/ticker" + anxDepth = "money/depth/full" ) +// ANX is the overarching type across the alphapoint package type ANX struct { exchange.Base } +// SetDefaults sets current default settings func (a *ANX) SetDefaults() { a.Name = "ANX" a.Enabled = false @@ -75,6 +77,7 @@ func (a *ANX) Setup(exch config.ExchangeConfig) { } } +// GetFee returns maker or taker fees func (a *ANX) GetFee(maker bool) float64 { if maker { return a.MakerFee @@ -82,24 +85,23 @@ func (a *ANX) GetFee(maker bool) float64 { return a.TakerFee } -func (a *ANX) GetTicker(currency string) (ANXTicker, error) { - var ticker ANXTicker - err := common.SendHTTPGetRequest(fmt.Sprintf("%sapi/2/%s/%s", ANX_API_URL, currency, ANX_TICKER), true, a.Verbose, &ticker) - if err != nil { - return ANXTicker{}, err - } - return ticker, nil +// GetTicker returns the current ticker +func (a *ANX) GetTicker(currency string) (Ticker, error) { + var ticker Ticker + path := fmt.Sprintf("%sapi/2/%s/%s", anxAPIURL, currency, anxTicker) + + return ticker, common.SendHTTPGetRequest(path, true, a.Verbose, &ticker) } +// GetDepth returns current orderbook depth. func (a *ANX) GetDepth(currency string) (Depth, error) { var depth Depth - err := common.SendHTTPGetRequest(fmt.Sprintf("%sapi/2/%s/%s", ANX_API_URL, currency, ANX_DEPTH), true, a.Verbose, &depth) - if err != nil { - return depth, err - } - return depth, nil + path := fmt.Sprintf("%sapi/2/%s/%s", anxAPIURL, currency, anxDepth) + + return depth, common.SendHTTPGetRequest(path, true, a.Verbose, &depth) } +// GetAPIKey returns a new generated API key set. func (a *ANX) GetAPIKey(username, password, otp, deviceID string) (string, string, error) { request := make(map[string]interface{}) request["nonce"] = strconv.FormatInt(time.Now().UnixNano(), 10)[0:13] @@ -120,7 +122,7 @@ func (a *ANX) GetAPIKey(username, password, otp, deviceID string) (string, strin } var response APIKeyResponse - err := a.SendAuthenticatedHTTPRequest(ANX_APIKEY, request, &response) + err := a.SendAuthenticatedHTTPRequest(anxAPIKey, request, &response) if err != nil { return "", "", err } @@ -132,6 +134,7 @@ func (a *ANX) GetAPIKey(username, password, otp, deviceID string) (string, strin return response.APIKey, response.APISecret, nil } +// GetDataToken returns token data func (a *ANX) GetDataToken() (string, error) { request := make(map[string]interface{}) @@ -143,7 +146,7 @@ func (a *ANX) GetDataToken() (string, error) { } var response DataTokenResponse - err := a.SendAuthenticatedHTTPRequest(ANX_DATA_TOKEN, request, &response) + err := a.SendAuthenticatedHTTPRequest(anxDataToken, request, &response) if err != nil { return "", err } @@ -154,11 +157,12 @@ func (a *ANX) GetDataToken() (string, error) { return response.Token, nil } +// NewOrder sends a new order request to the exchange. func (a *ANX) NewOrder(orderType string, buy bool, tradedCurrency, tradedCurrencyAmount, settlementCurrency, settlementCurrencyAmount, limitPriceSettlement string, replace bool, replaceUUID string, replaceIfActive bool) error { request := make(map[string]interface{}) - var order ANXOrder + var order Order order.OrderType = orderType order.BuyTradedCurrency = buy @@ -186,7 +190,7 @@ func (a *ANX) NewOrder(orderType string, buy bool, tradedCurrency, tradedCurrenc } var response OrderResponse - err := a.SendAuthenticatedHTTPRequest(ANX_ORDER_NEW, request, &response) + err := a.SendAuthenticatedHTTPRequest(anxOrderNew, request, &response) if err != nil { return err } @@ -197,30 +201,32 @@ func (a *ANX) NewOrder(orderType string, buy bool, tradedCurrency, tradedCurrenc return nil } -func (a *ANX) OrderInfo(orderID string) (ANXOrderResponse, error) { +// OrderInfo returns information about a specific order +func (a *ANX) OrderInfo(orderID string) (OrderResponse, error) { request := make(map[string]interface{}) request["orderId"] = orderID type OrderInfoResponse struct { - Order ANXOrderResponse `json:"order"` - ResultCode string `json:"resultCode"` - Timestamp int64 `json:"timestamp"` + Order OrderResponse `json:"order"` + ResultCode string `json:"resultCode"` + Timestamp int64 `json:"timestamp"` } var response OrderInfoResponse - err := a.SendAuthenticatedHTTPRequest(ANX_ORDER_INFO, request, &response) + err := a.SendAuthenticatedHTTPRequest(anxOrderInfo, request, &response) if err != nil { - return ANXOrderResponse{}, err + return OrderResponse{}, err } if response.ResultCode != "OK" { log.Printf("Response code is not OK: %s\n", response.ResultCode) - return ANXOrderResponse{}, errors.New(response.ResultCode) + return OrderResponse{}, errors.New(response.ResultCode) } return response.Order, nil } +// Send withdraws a currency to an address func (a *ANX) Send(currency, address, otp, amount string) (string, error) { request := make(map[string]interface{}) request["ccy"] = currency @@ -238,7 +244,7 @@ func (a *ANX) Send(currency, address, otp, amount string) (string, error) { } var response SendResponse - err := a.SendAuthenticatedHTTPRequest(ANX_SEND, request, &response) + err := a.SendAuthenticatedHTTPRequest(anxSend, request, &response) if err != nil { return "", err @@ -251,6 +257,7 @@ func (a *ANX) Send(currency, address, otp, amount string) (string, error) { return response.TransactionID, nil } +// CreateNewSubAccount generates a new sub account func (a *ANX) CreateNewSubAccount(currency, name string) (string, error) { request := make(map[string]interface{}) request["ccy"] = currency @@ -263,7 +270,7 @@ func (a *ANX) CreateNewSubAccount(currency, name string) (string, error) { } var response SubaccountResponse - err := a.SendAuthenticatedHTTPRequest(ANX_SUBACCOUNT_NEW, request, &response) + err := a.SendAuthenticatedHTTPRequest(anxSubaccountNew, request, &response) if err != nil { return "", err @@ -276,6 +283,7 @@ func (a *ANX) CreateNewSubAccount(currency, name string) (string, error) { return response.SubAccount, nil } +// GetDepositAddress returns a deposit address for a specific currency func (a *ANX) GetDepositAddress(currency, name string, new bool) (string, error) { request := make(map[string]interface{}) request["ccy"] = currency @@ -292,9 +300,9 @@ func (a *ANX) GetDepositAddress(currency, name string, new bool) (string, error) } var response AddressResponse - path := ANX_RECEIVE_ADDRESS + path := anxReceieveAddress if new { - path = ANX_CREATE_ADDRESS + path = anxCreateAddress } err := a.SendAuthenticatedHTTPRequest(path, request, &response) @@ -311,6 +319,7 @@ func (a *ANX) GetDepositAddress(currency, name string, new bool) (string, error) return response.Address, nil } +// SendAuthenticatedHTTPRequest sends a authenticated HTTP request func (a *ANX) SendAuthenticatedHTTPRequest(path string, params map[string]interface{}, result interface{}) error { if !a.AuthenticatedAPISupport { return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, a.Name) @@ -324,7 +333,7 @@ func (a *ANX) SendAuthenticatedHTTPRequest(path string, params map[string]interf request := make(map[string]interface{}) request["nonce"] = a.Nonce.String()[0:13] - path = fmt.Sprintf("api/%s/%s", ANX_API_VERSION, path) + path = fmt.Sprintf("api/%s/%s", anxAPIVersion, path) if params != nil { for key, value := range params { @@ -348,7 +357,10 @@ func (a *ANX) SendAuthenticatedHTTPRequest(path string, params map[string]interf headers["Rest-Sign"] = common.Base64Encode([]byte(hmac)) headers["Content-Type"] = "application/json" - resp, err := common.SendHTTPRequest("POST", ANX_API_URL+path, headers, bytes.NewBuffer(PayloadJSON)) + resp, err := common.SendHTTPRequest("POST", anxAPIURL+path, headers, bytes.NewBuffer(PayloadJSON)) + if err != nil { + return err + } if a.Verbose { log.Printf("Received raw: \n%s\n", resp) diff --git a/exchanges/anx/anx_types.go b/exchanges/anx/anx_types.go index 2b141803..a8cfe1ae 100644 --- a/exchanges/anx/anx_types.go +++ b/exchanges/anx/anx_types.go @@ -1,6 +1,7 @@ package anx -type ANXOrder struct { +// Order holds order information +type Order struct { OrderType string `json:"orderType"` BuyTradedCurrency bool `json:"buyTradedCurrency"` TradedCurrency string `json:"tradedCurrency"` @@ -12,7 +13,8 @@ type ANXOrder struct { ReplaceOnlyIfActive bool `json:"replaceOnlyIfActive"` } -type ANXOrderResponse struct { +// OrderResponse holds order response data +type OrderResponse struct { BuyTradedCurrency bool `json:"buyTradedCurrency"` ExecutedAverageRate string `json:"executedAverageRate"` LimitPriceInSettlementCurrency string `json:"limitPriceInSettlementCurrency"` @@ -29,29 +31,32 @@ type ANXOrderResponse struct { TradedCurrencyOutstanding string `json:"tradedCurrencyOutstanding"` } -type ANXTickerComponent struct { +// TickerComponent is a sub-type for ticker +type TickerComponent struct { Currency string `json:"currency"` Display string `json:"display"` DisplayShort string `json:"display_short"` Value string `json:"value"` } -type ANXTicker struct { +// Ticker contains ticker data +type Ticker struct { Result string `json:"result"` Data struct { - High ANXTickerComponent `json:"high"` - Low ANXTickerComponent `json:"low"` - Avg ANXTickerComponent `json:"avg"` - Vwap ANXTickerComponent `json:"vwap"` - Vol ANXTickerComponent `json:"vol"` - Last ANXTickerComponent `json:"last"` - Buy ANXTickerComponent `json:"buy"` - Sell ANXTickerComponent `json:"sell"` - Now string `json:"now"` - UpdateTime string `json:"dataUpdateTime"` + High TickerComponent `json:"high"` + Low TickerComponent `json:"low"` + Avg TickerComponent `json:"avg"` + Vwap TickerComponent `json:"vwap"` + Vol TickerComponent `json:"vol"` + Last TickerComponent `json:"last"` + Buy TickerComponent `json:"buy"` + Sell TickerComponent `json:"sell"` + Now string `json:"now"` + UpdateTime string `json:"dataUpdateTime"` } `json:"data"` } +// DepthItem contains depth information type DepthItem struct { Price float64 `json:"price,string"` PriceInt float64 `json:"price_int,string"` @@ -59,12 +64,13 @@ type DepthItem struct { AmountInt int64 `json:"amount_int,string"` } +// Depth contains full depth information type Depth struct { Result string `json:"result"` Data struct { Now string `json:"now"` DataUpdateTime string `json:"dataUpdateTime"` - Asks []DepthItem `json:"asks` + Asks []DepthItem `json:"asks"` Bids []DepthItem `json:"bids"` } `json:"data"` } From 111c6784a4a7226be3f6319bfe5adc2b5c3178d9 Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 10:26:21 +1100 Subject: [PATCH 03/12] Fix linter issues for BTCC --- exchanges/btcc/btcc.go | 21 +++++++++++++++++++++ exchanges/btcc/btcc_websocket.go | 13 +++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/exchanges/btcc/btcc.go b/exchanges/btcc/btcc.go index 56db4f14..7123cdc4 100644 --- a/exchanges/btcc/btcc.go +++ b/exchanges/btcc/btcc.go @@ -139,6 +139,7 @@ func (b *BTCC) GetOrderBook(currencyPair string, limit int) (Orderbook, error) { return result, common.SendHTTPGetRequest(req, true, b.Verbose, &result) } +// GetAccountInfo returns account information func (b *BTCC) GetAccountInfo(infoType string) error { params := make([]interface{}, 0) @@ -149,6 +150,7 @@ func (b *BTCC) GetAccountInfo(infoType string) error { return b.SendAuthenticatedHTTPRequest(btccAccountInfo, params) } +// PlaceOrder places a new order func (b *BTCC) PlaceOrder(buyOrder bool, price, amount float64, symbol string) { params := make([]interface{}, 0) params = append(params, strconv.FormatFloat(price, 'f', -1, 64)) @@ -170,6 +172,7 @@ func (b *BTCC) PlaceOrder(buyOrder bool, price, amount float64, symbol string) { } } +// CancelOrder cancels an order func (b *BTCC) CancelOrder(orderID int64, symbol string) { params := make([]interface{}, 0) params = append(params, orderID) @@ -185,6 +188,7 @@ func (b *BTCC) CancelOrder(orderID int64, symbol string) { } } +// GetDeposits returns deposit information func (b *BTCC) GetDeposits(currency string, pending bool) { params := make([]interface{}, 0) params = append(params, currency) @@ -200,6 +204,7 @@ func (b *BTCC) GetDeposits(currency string, pending bool) { } } +// GetMarketDepth returns market depth at limit func (b *BTCC) GetMarketDepth(symbol string, limit int64) { params := make([]interface{}, 0) @@ -218,6 +223,7 @@ func (b *BTCC) GetMarketDepth(symbol string, limit int64) { } } +// GetOrder returns information about a specific order func (b *BTCC) GetOrder(orderID int64, symbol string, detailed bool) { params := make([]interface{}, 0) params = append(params, orderID) @@ -237,6 +243,7 @@ func (b *BTCC) GetOrder(orderID int64, symbol string, detailed bool) { } } +// GetOrders returns information of a range of orders func (b *BTCC) GetOrders(openonly bool, symbol string, limit, offset, since int64, detailed bool) { params := make([]interface{}, 0) @@ -271,6 +278,7 @@ func (b *BTCC) GetOrders(openonly bool, symbol string, limit, offset, since int6 } } +// GetTransactions returns transaction lists func (b *BTCC) GetTransactions(transType string, limit, offset, since int64, sinceType string) { params := make([]interface{}, 0) @@ -301,6 +309,7 @@ func (b *BTCC) GetTransactions(transType string, limit, offset, since int64, sin } } +// GetWithdrawal returns information about a withdrawal process func (b *BTCC) GetWithdrawal(withdrawalID int64, currency string) { params := make([]interface{}, 0) params = append(params, withdrawalID) @@ -316,6 +325,7 @@ func (b *BTCC) GetWithdrawal(withdrawalID int64, currency string) { } } +// GetWithdrawals gets information about all withdrawals func (b *BTCC) GetWithdrawals(currency string, pending bool) { params := make([]interface{}, 0) params = append(params, currency) @@ -331,6 +341,7 @@ func (b *BTCC) GetWithdrawals(currency string, pending bool) { } } +// RequestWithdrawal requests a new withdrawal func (b *BTCC) RequestWithdrawal(currency string, amount float64) { params := make([]interface{}, 0) params = append(params, currency) @@ -343,6 +354,8 @@ func (b *BTCC) RequestWithdrawal(currency string, amount float64) { } } +// IcebergOrder intiates a large order but at intervals to preserve orderbook +// integrity func (b *BTCC) IcebergOrder(buyOrder bool, price, amount, discAmount, variance float64, symbol string) { params := make([]interface{}, 0) params = append(params, strconv.FormatFloat(price, 'f', -1, 64)) @@ -366,6 +379,7 @@ func (b *BTCC) IcebergOrder(buyOrder bool, price, amount, discAmount, variance f } } +// GetIcebergOrder returns information on your iceberg order func (b *BTCC) GetIcebergOrder(orderID int64, symbol string) { params := make([]interface{}, 0) params = append(params, orderID) @@ -381,6 +395,7 @@ func (b *BTCC) GetIcebergOrder(orderID int64, symbol string) { } } +// GetIcebergOrders returns information on all iceberg orders func (b *BTCC) GetIcebergOrders(limit, offset int64, symbol string) { params := make([]interface{}, 0) @@ -403,6 +418,7 @@ func (b *BTCC) GetIcebergOrders(limit, offset int64, symbol string) { } } +// CancelIcebergOrder cancels iceberg order func (b *BTCC) CancelIcebergOrder(orderID int64, symbol string) { params := make([]interface{}, 0) params = append(params, orderID) @@ -418,6 +434,7 @@ func (b *BTCC) CancelIcebergOrder(orderID int64, symbol string) { } } +// PlaceStopOrder inserts a stop loss order func (b *BTCC) PlaceStopOrder(buyOder bool, stopPrice, price, amount, trailingAmt, trailingPct float64, symbol string) { params := make([]interface{}, 0) @@ -452,6 +469,7 @@ func (b *BTCC) PlaceStopOrder(buyOder bool, stopPrice, price, amount, trailingAm } } +// GetStopOrder returns a stop order func (b *BTCC) GetStopOrder(orderID int64, symbol string) { params := make([]interface{}, 0) params = append(params, orderID) @@ -467,6 +485,7 @@ func (b *BTCC) GetStopOrder(orderID int64, symbol string) { } } +// GetStopOrders returns all stop orders func (b *BTCC) GetStopOrders(status, orderType string, stopPrice float64, limit, offset int64, symbol string) { params := make([]interface{}, 0) @@ -501,6 +520,7 @@ func (b *BTCC) GetStopOrders(status, orderType string, stopPrice float64, limit, } } +// CancelStopOrder cancels a stop order func (b *BTCC) CancelStopOrder(orderID int64, symbol string) { params := make([]interface{}, 0) params = append(params, orderID) @@ -516,6 +536,7 @@ func (b *BTCC) CancelStopOrder(orderID int64, symbol string) { } } +// SendAuthenticatedHTTPRequest sends a valid authenticated HTTP request func (b *BTCC) SendAuthenticatedHTTPRequest(method string, params []interface{}) (err error) { if !b.AuthenticatedAPISupport { return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name) diff --git a/exchanges/btcc/btcc_websocket.go b/exchanges/btcc/btcc_websocket.go index c7414d53..bac59e5c 100644 --- a/exchanges/btcc/btcc_websocket.go +++ b/exchanges/btcc/btcc_websocket.go @@ -9,11 +9,13 @@ import ( ) const ( - BTCC_SOCKETIO_ADDRESS = "https://websocket.btcc.com" + btccSocketioAddress = "https://websocket.btcc.com" ) +// BTCCSocket is a pointer to a IO socket var BTCCSocket *socketio.SocketIO +// OnConnect gets information from the server when its connected func (b *BTCC) OnConnect(output chan socketio.Message) { if b.Verbose { log.Printf("%s Connected to Websocket.", b.GetName()) @@ -37,16 +39,19 @@ func (b *BTCC) OnConnect(output chan socketio.Message) { } } +// OnDisconnect alerts when disconnection occurs func (b *BTCC) OnDisconnect(output chan socketio.Message) { log.Printf("%s Disconnected from websocket server.. Reconnecting.\n", b.GetName()) b.WebsocketClient() } +// OnError alerts when error occurs func (b *BTCC) OnError() { log.Printf("%s Error with Websocket connection.. Reconnecting.\n", b.GetName()) b.WebsocketClient() } +// OnMessage if message received and verbose it is printed out func (b *BTCC) OnMessage(message []byte, output chan socketio.Message) { if b.Verbose { log.Printf("%s Websocket message received which isn't handled by default.\n", b.GetName()) @@ -54,6 +59,7 @@ func (b *BTCC) OnMessage(message []byte, output chan socketio.Message) { } } +// OnTicker handles ticker information func (b *BTCC) OnTicker(message []byte, output chan socketio.Message) { type Response struct { Ticker WebsocketTicker `json:"ticker"` @@ -67,6 +73,7 @@ func (b *BTCC) OnTicker(message []byte, output chan socketio.Message) { } } +// OnGroupOrder handles group order information func (b *BTCC) OnGroupOrder(message []byte, output chan socketio.Message) { type Response struct { GroupOrder WebsocketGroupOrder `json:"grouporder"` @@ -80,6 +87,7 @@ func (b *BTCC) OnGroupOrder(message []byte, output chan socketio.Message) { } } +// OnTrade handles group trade information func (b *BTCC) OnTrade(message []byte, output chan socketio.Message) { trade := WebsocketTrade{} err := common.JSONDecode(message, &trade) @@ -90,6 +98,7 @@ func (b *BTCC) OnTrade(message []byte, output chan socketio.Message) { } } +// WebsocketClient initiates a websocket client func (b *BTCC) WebsocketClient() { events := make(map[string]func(message []byte, output chan socketio.Message)) events["grouporder"] = b.OnGroupOrder @@ -106,7 +115,7 @@ func (b *BTCC) WebsocketClient() { } for b.Enabled && b.Websocket { - err := socketio.ConnectToSocket(BTCC_SOCKETIO_ADDRESS, BTCCSocket) + err := socketio.ConnectToSocket(btccSocketioAddress, BTCCSocket) if err != nil { log.Printf("%s Unable to connect to Websocket. Err: %s\n", b.GetName(), err) continue From 6962f84748edee120bfbfdd78f5d6be0af675cea Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 10:57:35 +1100 Subject: [PATCH 04/12] Fixed linter issues for Coinut exchange. --- exchanges/coinut/coinut.go | 75 ++++++++----- exchanges/coinut/coinut_test.go | 1 - exchanges/coinut/coinut_types.go | 157 ++++++++++++++++----------- exchanges/coinut/coinut_websocket.go | 3 +- exchanges/coinut/coinut_wrapper.go | 2 +- 5 files changed, 139 insertions(+), 99 deletions(-) diff --git a/exchanges/coinut/coinut.go b/exchanges/coinut/coinut.go index d9b0a35b..999de2b2 100644 --- a/exchanges/coinut/coinut.go +++ b/exchanges/coinut/coinut.go @@ -84,8 +84,8 @@ func (c *COINUT) Setup(exch config.ExchangeConfig) { } // GetInstruments returns instruments -func (c *COINUT) GetInstruments() (CoinutInstruments, error) { - var result CoinutInstruments +func (c *COINUT) GetInstruments() (Instruments, error) { + var result Instruments params := make(map[string]interface{}) params["sec_type"] = "SPOT" err := c.SendHTTPRequest(coinutInstruments, params, false, &result) @@ -95,8 +95,9 @@ func (c *COINUT) GetInstruments() (CoinutInstruments, error) { return result, nil } -func (c *COINUT) GetInstrumentTicker(instrumentID int) (CoinutTicker, error) { - var result CoinutTicker +// GetInstrumentTicker returns a ticker for a specific instrument +func (c *COINUT) GetInstrumentTicker(instrumentID int) (Ticker, error) { + var result Ticker params := make(map[string]interface{}) params["inst_id"] = instrumentID err := c.SendHTTPRequest(coinutTicker, params, false, &result) @@ -106,8 +107,9 @@ func (c *COINUT) GetInstrumentTicker(instrumentID int) (CoinutTicker, error) { return result, nil } -func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int) (CoinutOrderbook, error) { - var result CoinutOrderbook +// GetInstrumentOrderbook returns the orderbooks for a specific instrument +func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int) (Orderbook, error) { + var result Orderbook params := make(map[string]interface{}) params["inst_id"] = instrumentID if limit > 0 { @@ -120,8 +122,9 @@ func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int) (CoinutOrderboo return result, nil } -func (c *COINUT) GetTrades(instrumentID int) (CoinutTrades, error) { - var result CoinutTrades +// GetTrades returns trade information +func (c *COINUT) GetTrades(instrumentID int) (Trades, error) { + var result Trades params := make(map[string]interface{}) params["inst_id"] = instrumentID err := c.SendHTTPRequest(coinutTrades, params, false, &result) @@ -131,8 +134,9 @@ func (c *COINUT) GetTrades(instrumentID int) (CoinutTrades, error) { return result, nil } -func (c *COINUT) GetUserBalance() (CoinutUserBalance, error) { - result := CoinutUserBalance{} +// GetUserBalance returns the full user balance +func (c *COINUT) GetUserBalance() (UserBalance, error) { + result := UserBalance{} err := c.SendHTTPRequest(coinutBalance, nil, true, &result) if err != nil { return result, err @@ -140,6 +144,7 @@ func (c *COINUT) GetUserBalance() (CoinutUserBalance, error) { return result, nil } +// NewOrder places a new order on the exchange func (c *COINUT) NewOrder(instrumentID int, quantity, price float64, buy bool, orderID uint32) (interface{}, error) { var result interface{} params := make(map[string]interface{}) @@ -159,8 +164,9 @@ func (c *COINUT) NewOrder(instrumentID int, quantity, price float64, buy bool, o return result, nil } -func (c *COINUT) NewOrders(orders []CoinutOrder) ([]CoinutOrdersBase, error) { - var result CoinutOrdersResponse +// NewOrders places multiple orders on the exchange +func (c *COINUT) NewOrders(orders []Order) ([]OrdersBase, error) { + var result OrdersResponse params := make(map[string]interface{}) params["orders"] = orders err := c.SendHTTPRequest(coinutOrders, params, true, &result.Data) @@ -170,8 +176,9 @@ func (c *COINUT) NewOrders(orders []CoinutOrder) ([]CoinutOrdersBase, error) { return result.Data, nil } -func (c *COINUT) GetOpenOrders(instrumentID int) ([]CoinutOrdersResponse, error) { - var result []CoinutOrdersResponse +// GetOpenOrders returns a list of open order and relevant information +func (c *COINUT) GetOpenOrders(instrumentID int) ([]OrdersResponse, error) { + var result []OrdersResponse params := make(map[string]interface{}) params["inst_id"] = instrumentID err := c.SendHTTPRequest(coinutOrdersOpen, params, true, &result) @@ -181,8 +188,9 @@ func (c *COINUT) GetOpenOrders(instrumentID int) ([]CoinutOrdersResponse, error) return result, nil } +// CancelOrder cancels a specific order and returns if it was actioned func (c *COINUT) CancelOrder(instrumentID, orderID int) (bool, error) { - var result CoinutGenericResponse + var result GenericResponse params := make(map[string]interface{}) params["inst_id"] = instrumentID params["order_id"] = orderID @@ -193,8 +201,9 @@ func (c *COINUT) CancelOrder(instrumentID, orderID int) (bool, error) { return true, nil } -func (c *COINUT) CancelOrders(orders []CoinutCancelOrders) (CoinutCancelOrdersResponse, error) { - var result CoinutCancelOrdersResponse +// CancelOrders cancels multiple orders +func (c *COINUT) CancelOrders(orders []CancelOrders) (CancelOrdersResponse, error) { + var result CancelOrdersResponse params := make(map[string]interface{}) params["entries"] = orders err := c.SendHTTPRequest(coinutOrdersCancel, params, true, &result) @@ -204,8 +213,9 @@ func (c *COINUT) CancelOrders(orders []CoinutCancelOrders) (CoinutCancelOrdersRe return result, nil } -func (c *COINUT) GetTradeHistory(instrumentID, start, limit int) (CoinutTradeHistory, error) { - var result CoinutTradeHistory +// GetTradeHistory returns trade history for a specific instrument. +func (c *COINUT) GetTradeHistory(instrumentID, start, limit int) (TradeHistory, error) { + var result TradeHistory params := make(map[string]interface{}) params["inst_id"] = instrumentID if start >= 0 && start <= 100 { @@ -221,8 +231,9 @@ func (c *COINUT) GetTradeHistory(instrumentID, start, limit int) (CoinutTradeHis return result, nil } -func (c *COINUT) GetIndexTicker(asset string) (CoinutIndexTicker, error) { - var result CoinutIndexTicker +// GetIndexTicker returns the index ticker for an asset +func (c *COINUT) GetIndexTicker(asset string) (IndexTicker, error) { + var result IndexTicker params := make(map[string]interface{}) params["asset"] = asset err := c.SendHTTPRequest(coinutIndexTicker, params, false, &result) @@ -232,6 +243,7 @@ func (c *COINUT) GetIndexTicker(asset string) (CoinutIndexTicker, error) { return result, nil } +// GetDerivativeInstruments returns a list of derivative instruments func (c *COINUT) GetDerivativeInstruments(secType string) (interface{}, error) { var result interface{} //to-do params := make(map[string]interface{}) @@ -243,8 +255,9 @@ func (c *COINUT) GetDerivativeInstruments(secType string) (interface{}, error) { return result, nil } -func (c *COINUT) GetOptionChain(asset, secType string, expiry int64) (CoinutOptionChainResponse, error) { - var result CoinutOptionChainResponse +// GetOptionChain returns option chain +func (c *COINUT) GetOptionChain(asset, secType string, expiry int64) (OptionChainResponse, error) { + var result OptionChainResponse params := make(map[string]interface{}) params["asset"] = asset params["sec_type"] = secType @@ -255,8 +268,9 @@ func (c *COINUT) GetOptionChain(asset, secType string, expiry int64) (CoinutOpti return result, nil } -func (c *COINUT) GetPositionHistory(secType string, start, limit int) (CoinutPositionHistory, error) { - var result CoinutPositionHistory +// GetPositionHistory returns position history +func (c *COINUT) GetPositionHistory(secType string, start, limit int) (PositionHistory, error) { + var result PositionHistory params := make(map[string]interface{}) params["sec_type"] = secType if start >= 0 { @@ -272,9 +286,10 @@ func (c *COINUT) GetPositionHistory(secType string, start, limit int) (CoinutPos return result, nil } -func (c *COINUT) GetOpenPositions(instrumentID int) ([]CoinutOpenPosition, error) { +// GetOpenPositions returns all your current opened positions +func (c *COINUT) GetOpenPositions(instrumentID int) ([]OpenPosition, error) { type Response struct { - Positions []CoinutOpenPosition `json:"positions"` + Positions []OpenPosition `json:"positions"` } var result Response params := make(map[string]interface{}) @@ -289,6 +304,7 @@ func (c *COINUT) GetOpenPositions(instrumentID int) ([]CoinutOpenPosition, error //to-do: user position update via websocket +// SendHTTPRequest sends an authenticated HTTP request func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{}, authenticated bool, result interface{}) (err error) { if !c.AuthenticatedAPISupport && authenticated { return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, c.Name) @@ -299,7 +315,6 @@ func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{ } else { c.Nonce.Inc() } - payload := []byte("") if params == nil { params = map[string]interface{}{} @@ -307,7 +322,7 @@ func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{ params["nonce"] = c.Nonce.Get() params["request"] = apiRequest - payload, err = common.JSONEncode(params) + payload, err := common.JSONEncode(params) if err != nil { return errors.New("SenddHTTPRequest: Unable to JSON request") } @@ -333,7 +348,7 @@ func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{ log.Printf("Received raw: \n%s", resp) } - genResp := CoinutGenericResponse{} + genResp := GenericResponse{} err = common.JSONDecode([]byte(resp), &genResp) if err != nil { return errors.New("unable to JSON Unmarshal generic response") diff --git a/exchanges/coinut/coinut_test.go b/exchanges/coinut/coinut_test.go index ca8e0d5b..09c33b40 100644 --- a/exchanges/coinut/coinut_test.go +++ b/exchanges/coinut/coinut_test.go @@ -21,7 +21,6 @@ func TestSetDefaults(t *testing.T) { func TestSetup(t *testing.T) { t.Parallel() - c := COINUT{} c.Name = "Coinut" cfg := config.GetConfig() cfg.LoadConfig("../../testdata/configtest.json") diff --git a/exchanges/coinut/coinut_types.go b/exchanges/coinut/coinut_types.go index 10db1bf9..131eedba 100644 --- a/exchanges/coinut/coinut_types.go +++ b/exchanges/coinut/coinut_types.go @@ -1,6 +1,7 @@ package coinut -type CoinutGenericResponse struct { +// GenericResponse is the generic response you will get from coinut +type GenericResponse struct { Nonce int64 `json:"nonce"` Reply string `json:"reply"` Status []string `json:"status"` @@ -8,18 +9,21 @@ type CoinutGenericResponse struct { Timestamp int64 `json:"timestamp"` } -type CoinutInstrumentBase struct { +// InstrumentBase holds information on base currency +type InstrumentBase struct { Base string `json:"base"` DecimalPlaces int `json:"decimal_places"` InstID int `json:"inst_id"` Quote string `json:"quote"` } -type CoinutInstruments struct { - Instruments map[string][]CoinutInstrumentBase `json:"SPOT"` +// Instruments holds the full information on base currencies +type Instruments struct { + Instruments map[string][]InstrumentBase `json:"SPOT"` } -type CoinutTicker struct { +// Ticker holds ticker information +type Ticker struct { HighestBuy float64 `json:"highest_buy,string"` InstrumentID int `json:"inst_id"` Last float64 `json:"last,string"` @@ -31,22 +35,25 @@ type CoinutTicker struct { Volume24 float64 `json:"volume24,string"` } -type CoinutOrderbookBase struct { +// OrderbookBase is a sub-type holding price and quantity +type OrderbookBase struct { Count int `json:"count"` Price float64 `json:"price,string"` Quantity float64 `json:"qty,string"` } -type CoinutOrderbook struct { - Buy []CoinutOrderbookBase `json:"buy"` - Sell []CoinutOrderbookBase `json:"sell"` - InstrumentID int `json:"inst_id"` - TotalBuy float64 `json:"total_buy,string"` - TotalSell float64 `json:"total_sell,string"` - TransID int64 `json:"trans_id"` +// Orderbook is the full order book +type Orderbook struct { + Buy []OrderbookBase `json:"buy"` + Sell []OrderbookBase `json:"sell"` + InstrumentID int `json:"inst_id"` + TotalBuy float64 `json:"total_buy,string"` + TotalSell float64 `json:"total_sell,string"` + TransID int64 `json:"trans_id"` } -type CoinutTradeBase struct { +// TradeBase is a sub-type holding information on trades +type TradeBase struct { Price float64 `json:"price,string"` Quantity float64 `json:"quantity,string"` Side string `json:"side"` @@ -54,11 +61,13 @@ type CoinutTradeBase struct { TransID int64 `json:"trans_id"` } -type CoinutTrades struct { - Trades []CoinutTradeBase `json:"trades"` +// Trades holds the full amount of trades associated with API keys +type Trades struct { + Trades []TradeBase `json:"trades"` } -type CoinutUserBalance struct { +// UserBalance holds user balances on the exchange +type UserBalance struct { BTC float64 `json:"btc,string"` ETC float64 `json:"etc,string"` ETH float64 `json:"eth,string"` @@ -71,7 +80,8 @@ type CoinutUserBalance struct { UnrealizedPL float64 `json:"unrealized_pl,string"` } -type CoinutOrder struct { +// Order holds order information +type Order struct { InstrumentID int64 `json:"inst_id"` Price float64 `json:"price,string"` Quantity float64 `json:"qty,string"` @@ -79,7 +89,8 @@ type CoinutOrder struct { Side string `json:"side,string"` } -type CoinutOrderResponse struct { +// OrderResponse is a response for orders +type OrderResponse struct { OrderID int64 `json:"order_id"` OpenQuantity float64 `json:"open_qty,string"` Price float64 `json:"price,string"` @@ -91,40 +102,47 @@ type CoinutOrderResponse struct { Side string `json:"side"` } -type CoinutCommission struct { +// Commission holds trade commision structure +type Commission struct { Currency string `json:"currency"` Amount float64 `json:"amount,string"` } -type CoinutOrderFilledResponse struct { - CoinutGenericResponse - Commission CoinutCommission `json:"commission"` - FillPrice float64 `json:"fill_price,string"` - FillQuantity float64 `json:"fill_qty,string"` - Order CoinutOrderResponse `json:"order"` +// OrderFilledResponse contains order filled response +type OrderFilledResponse struct { + GenericResponse + Commission Commission `json:"commission"` + FillPrice float64 `json:"fill_price,string"` + FillQuantity float64 `json:"fill_qty,string"` + Order OrderResponse `json:"order"` } -type CoinutOrderRejectResponse struct { - CoinutOrderResponse +// OrderRejectResponse holds information on a rejected order +type OrderRejectResponse struct { + OrderResponse Reasons []string `json:"reasons"` } -type CoinutOrdersBase struct { - CoinutGenericResponse - CoinutOrderResponse +// OrdersBase contains generic response and order responses +type OrdersBase struct { + GenericResponse + OrderResponse } -type CoinutOrdersResponse struct { - Data []CoinutOrdersBase +// OrdersResponse holds the full data range on orders +type OrdersResponse struct { + Data []OrdersBase } -type CoinutCancelOrders struct { +// CancelOrders holds information about a cancelled order +type CancelOrders struct { InstrumentID int `json:"int"` OrderID int64 `json:"order_id"` } -type CoinutCancelOrdersResponse struct { - CoinutGenericResponse +// CancelOrdersResponse is response for a cancelled order +type CancelOrdersResponse struct { + GenericResponse Results []struct { OrderID int64 `json:"order_id"` Status string `json:"status"` @@ -132,17 +150,20 @@ type CoinutCancelOrdersResponse struct { } `json:"results"` } -type CoinutTradeHistory struct { - TotalNumber int64 `json:"total_number"` - Trades []CoinutOrderFilledResponse `json:"trades"` +// TradeHistory holds trade history information +type TradeHistory struct { + TotalNumber int64 `json:"total_number"` + Trades []OrderFilledResponse `json:"trades"` } -type CoinutIndexTicker struct { +// IndexTicker holds indexed ticker inforamtion +type IndexTicker struct { Asset string `json:"asset"` Price float64 `json:"price,string"` } -type CoinutOption struct { +// Option holds options information +type Option struct { HighestBuy float64 `json:"highest_buy,string"` InstrumentID int `json:"inst_id"` Last float64 `json:"last,string"` @@ -150,40 +171,43 @@ type CoinutOption struct { OpenInterest float64 `json:"open_interest,string"` } -type CoinutOptionChainResponse struct { +// OptionChainResponse is the response type for options +type OptionChainResponse struct { ExpiryTime int64 `json:"expiry_time"` SecurityType string `json:"sec_type"` Asset string `json:"asset"` Entries []struct { - Call CoinutOption `json:"call"` - Put CoinutOption `json:"put"` - Strike float64 `json:"strike,string"` + Call Option `json:"call"` + Put Option `json:"put"` + Strike float64 `json:"strike,string"` } } -type CoinutOptionChainUpdate struct { - CoinutOption - CoinutGenericResponse +// OptionChainUpdate contains information on the chain update options +type OptionChainUpdate struct { + Option + GenericResponse Asset string `json:"asset"` ExpiryTime int64 `json:"expiry_time"` SecurityType string `json:"sec_type"` Volume float64 `json:"volume,string"` } -type CoinutPositionHistory struct { +// PositionHistory holds the complete position history +type PositionHistory struct { Positions []struct { PositionID int `json:"position_id"` Records []struct { - Commission CoinutCommission `json:"commission"` - FillPrice float64 `json:"fill_price,string,omitempty"` - TransactionID int `json:"trans_id"` - FillQuantity float64 `json:"fill_qty,omitempty"` + Commission Commission `json:"commission"` + FillPrice float64 `json:"fill_price,string,omitempty"` + TransactionID int `json:"trans_id"` + FillQuantity float64 `json:"fill_qty,omitempty"` Position struct { - Commission CoinutCommission `json:"commission"` - Timestamp int64 `json:"timestamp"` - OpenPrice float64 `json:"open_price,string"` - RealizedPL float64 `json:"realized_pl,string"` - Quantity float64 `json:"qty,string"` + Commission Commission `json:"commission"` + Timestamp int64 `json:"timestamp"` + OpenPrice float64 `json:"open_price,string"` + RealizedPL float64 `json:"realized_pl,string"` + Quantity float64 `json:"qty,string"` } `json:"position"` AssetAtExpiry float64 `json:"asset_at_expiry,string,omitempty"` } `json:"records"` @@ -202,12 +226,13 @@ type CoinutPositionHistory struct { TotalNumber int `json:"total_number"` } -type CoinutOpenPosition struct { - PositionID int `json:"position_id"` - Commission CoinutCommission `json:"commission"` - OpenPrice float64 `json:"open_price,string"` - RealizedPL float64 `json:"realized_pl,string"` - Quantity float64 `json:"qty,string"` - OpenTimestamp int64 `json:"open_timestamp"` - InstrumentID int `json:"inst_id"` +// OpenPosition holds information on an open position +type OpenPosition struct { + PositionID int `json:"position_id"` + Commission Commission `json:"commission"` + OpenPrice float64 `json:"open_price,string"` + RealizedPL float64 `json:"realized_pl,string"` + Quantity float64 `json:"qty,string"` + OpenTimestamp int64 `json:"open_timestamp"` + InstrumentID int `json:"inst_id"` } diff --git a/exchanges/coinut/coinut_websocket.go b/exchanges/coinut/coinut_websocket.go index 53e8c9a1..b1d350eb 100644 --- a/exchanges/coinut/coinut_websocket.go +++ b/exchanges/coinut/coinut_websocket.go @@ -8,8 +8,9 @@ import ( "github.com/thrasher-/gocryptotrader/common" ) -const COINUT_WEBSOCKET_URL = "wss://wsapi.coinut.com" +const coinutWebsocketURL = "wss://wsapi.coinut.com" +// WebsocketClient initiates a websocket client func (c *COINUT) WebsocketClient() { for c.Enabled && c.Websocket { var Dialer websocket.Dialer diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go index feb64f97..74bd87fb 100644 --- a/exchanges/coinut/coinut_wrapper.go +++ b/exchanges/coinut/coinut_wrapper.go @@ -19,7 +19,7 @@ func (c *COINUT) Start() { // Run implements the COINUT wrapper func (c *COINUT) Run() { if c.Verbose { - log.Printf("%s Websocket: %s. (url: %s).\n", c.GetName(), common.IsEnabled(c.Websocket), COINUT_WEBSOCKET_URL) + log.Printf("%s Websocket: %s. (url: %s).\n", c.GetName(), common.IsEnabled(c.Websocket), coinutWebsocketURL) log.Printf("%s polling delay: %ds.\n", c.GetName(), c.RESTPollingDelay) log.Printf("%s %d currencies enabled: %s.\n", c.GetName(), len(c.EnabledPairs), c.EnabledPairs) } From aef0b5a47416fb4341b7e23374e8b36a7382c796 Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 11:13:15 +1100 Subject: [PATCH 05/12] Fixed linter issues and 429 request error due to test procedures on GDAX exchange --- exchanges/gdax/gdax_test.go | 332 ++++++++++++------------------- exchanges/gdax/gdax_websocket.go | 6 +- exchanges/gdax/gdax_wrapper.go | 2 +- 3 files changed, 137 insertions(+), 203 deletions(-) diff --git a/exchanges/gdax/gdax_test.go b/exchanges/gdax/gdax_test.go index e4ec5d58..266458f4 100644 --- a/exchanges/gdax/gdax_test.go +++ b/exchanges/gdax/gdax_test.go @@ -96,205 +96,137 @@ func TestGetServerTime(t *testing.T) { } } -func TestGetAccounts(t *testing.T) { - t.Parallel() - _, err := g.GetAccounts() - if err == nil { - t.Error("Test failed - GetAccounts() error", err) - } -} - -func TestGetAccount(t *testing.T) { - t.Parallel() - _, err := g.GetAccount("234cb213-ac6f-4ed8-b7b6-e62512930945") - if err == nil { - t.Error("Test failed - GetAccount() error", err) - } -} - -func TestGetAccountHistory(t *testing.T) { - t.Parallel() - _, err := g.GetAccountHistory("234cb213-ac6f-4ed8-b7b6-e62512930945") - if err == nil { - t.Error("Test failed - GetAccountHistory() error", err) - } -} - -func TestGetHolds(t *testing.T) { - t.Parallel() - _, err := g.GetHolds("234cb213-ac6f-4ed8-b7b6-e62512930945") - if err == nil { - t.Error("Test failed - GetHolds() error", err) - } -} - -func TestPlaceLimitOrder(t *testing.T) { - t.Parallel() - _, err := g.PlaceLimitOrder("", 0, 0, "buy", "", "", "BTC-USD", "", false) - if err == nil { - t.Error("Test failed - PlaceLimitOrder() error", err) - } -} - -func TestPlaceMarketOrder(t *testing.T) { - t.Parallel() - _, err := g.PlaceMarketOrder("", 1, 0, "buy", "BTC-USD", "") - if err == nil { - t.Error("Test failed - PlaceMarketOrder() error", err) - } -} - -func TestCancelOrder(t *testing.T) { - t.Parallel() - err := g.CancelOrder("1337") - if err == nil { - t.Error("Test failed - CancelOrder() error", err) - } -} - -func TestCancelAllOrders(t *testing.T) { - t.Parallel() - _, err := g.CancelAllOrders("BTC-USD") - if err == nil { - t.Error("Test failed - CancelAllOrders() error", err) - } -} - -func TestGetOrders(t *testing.T) { - t.Parallel() - _, err := g.GetOrders([]string{"open", "done"}, "BTC-USD") - if err == nil { - t.Error("Test failed - GetOrders() error", err) - } -} - -func TestGetOrder(t *testing.T) { - t.Parallel() - _, err := g.GetOrder("1337") - if err == nil { - t.Error("Test failed - GetOrders() error", err) - } -} - -func TestGetFills(t *testing.T) { - t.Parallel() - _, err := g.GetFills("1337", "BTC-USD") - if err == nil { - t.Error("Test failed - GetFills() error", err) - } - _, err = g.GetFills("", "") - if err == nil { - t.Error("Test failed - GetFills() error", err) - } -} - -func TestGetFundingRecords(t *testing.T) { - t.Parallel() - _, err := g.GetFundingRecords("rejected") - if err == nil { - t.Error("Test failed - GetFundingRecords() error", err) - } -} - -// func TestRepayFunding(t *testing.T) { -// g.Verbose = true -// _, err := g.RepayFunding("1", "BTC") -// if err != nil { -// t.Error("Test failed - RepayFunding() error", err) -// } -// } - -func TestMarginTransfer(t *testing.T) { //invalid sig issue - t.Parallel() - _, err := g.MarginTransfer(1, "withdraw", "45fa9e3b-00ba-4631-b907-8a98cbdf21be", "BTC") - if err == nil { - t.Error("Test failed - MarginTransfer() error", err) - } -} - -func TestGetPosition(t *testing.T) { - t.Parallel() - _, err := g.GetPosition() - if err == nil { - t.Error("Test failed - GetPosition() error", err) - } -} - -func TestClosePosition(t *testing.T) { - t.Parallel() - _, err := g.ClosePosition(false) - if err == nil { - t.Error("Test failed - ClosePosition() error", err) - } -} - -func TestGetPayMethods(t *testing.T) { - t.Parallel() - _, err := g.GetPayMethods() - if err == nil { - t.Error("Test failed - GetPayMethods() error", err) - } -} - -func TestDepositViaPaymentMethod(t *testing.T) { - t.Parallel() - _, err := g.DepositViaPaymentMethod(1, "BTC", "1337") - if err == nil { - t.Error("Test failed - DepositViaPaymentMethod() error", err) - } -} - -func TestDepositViaCoinbase(t *testing.T) { - t.Parallel() - _, err := g.DepositViaCoinbase(1, "BTC", "1337") - if err == nil { - t.Error("Test failed - DepositViaCoinbase() error", err) - } -} - -func TestWithdrawViaPaymentMethod(t *testing.T) { - t.Parallel() - _, err := g.WithdrawViaPaymentMethod(1, "BTC", "1337") - if err == nil { - t.Error("Test failed - WithdrawViaPaymentMethod() error", err) - } -} - -// func TestWithdrawViaCoinbase(t *testing.T) { // No Route found error -// _, err := g.WithdrawViaCoinbase(1, "BTC", "c13cd0fc-72ca-55e9-843b-b84ef628c198") -// if err != nil { -// t.Error("Test failed - WithdrawViaCoinbase() error", err) -// } -// } - -func TestWithdrawCrypto(t *testing.T) { - t.Parallel() - _, err := g.WithdrawCrypto(1, "BTC", "1337") - if err == nil { - t.Error("Test failed - WithdrawViaCoinbase() error", err) - } -} - -func TestGetCoinbaseAccounts(t *testing.T) { - t.Parallel() - _, err := g.GetCoinbaseAccounts() - if err == nil { - t.Error("Test failed - GetCoinbaseAccounts() error", err) - } -} - -func TestGetReportStatus(t *testing.T) { - t.Parallel() - _, err := g.GetReportStatus("1337") - if err == nil { - t.Error("Test failed - GetReportStatus() error", err) - } -} - -func TestGetTrailingVolume(t *testing.T) { - t.Parallel() - _, err := g.GetTrailingVolume() - if err == nil { - t.Error("Test failed - GetTrailingVolume() error", err) +func TestAuthRequests(t *testing.T) { + + if g.APIKey != "" && g.APISecret != "" && g.ClientID != "" { + + _, err := g.GetAccounts() + if err == nil { + t.Error("Test failed - GetAccounts() error", err) + } + + _, err = g.GetAccount("234cb213-ac6f-4ed8-b7b6-e62512930945") + if err == nil { + t.Error("Test failed - GetAccount() error", err) + } + + _, err = g.GetAccountHistory("234cb213-ac6f-4ed8-b7b6-e62512930945") + if err == nil { + t.Error("Test failed - GetAccountHistory() error", err) + } + + _, err = g.GetHolds("234cb213-ac6f-4ed8-b7b6-e62512930945") + if err == nil { + t.Error("Test failed - GetHolds() error", err) + } + + _, err = g.PlaceLimitOrder("", 0, 0, "buy", "", "", "BTC-USD", "", false) + if err == nil { + t.Error("Test failed - PlaceLimitOrder() error", err) + } + + _, err = g.PlaceMarketOrder("", 1, 0, "buy", "BTC-USD", "") + if err == nil { + t.Error("Test failed - PlaceMarketOrder() error", err) + } + + err = g.CancelOrder("1337") + if err == nil { + t.Error("Test failed - CancelOrder() error", err) + } + + _, err = g.CancelAllOrders("BTC-USD") + if err == nil { + t.Error("Test failed - CancelAllOrders() error", err) + } + + _, err = g.GetOrders([]string{"open", "done"}, "BTC-USD") + if err == nil { + t.Error("Test failed - GetOrders() error", err) + } + + _, err = g.GetOrder("1337") + if err == nil { + t.Error("Test failed - GetOrders() error", err) + } + + _, err = g.GetFills("1337", "BTC-USD") + if err == nil { + t.Error("Test failed - GetFills() error", err) + } + _, err = g.GetFills("", "") + if err == nil { + t.Error("Test failed - GetFills() error", err) + } + + _, err = g.GetFundingRecords("rejected") + if err == nil { + t.Error("Test failed - GetFundingRecords() error", err) + } + + // _, err := g.RepayFunding("1", "BTC") + // if err != nil { + // t.Error("Test failed - RepayFunding() error", err) + // } + + _, err = g.MarginTransfer(1, "withdraw", "45fa9e3b-00ba-4631-b907-8a98cbdf21be", "BTC") + if err == nil { + t.Error("Test failed - MarginTransfer() error", err) + } + + _, err = g.GetPosition() + if err == nil { + t.Error("Test failed - GetPosition() error", err) + } + + _, err = g.ClosePosition(false) + if err == nil { + t.Error("Test failed - ClosePosition() error", err) + } + + _, err = g.GetPayMethods() + if err == nil { + t.Error("Test failed - GetPayMethods() error", err) + } + + _, err = g.DepositViaPaymentMethod(1, "BTC", "1337") + if err == nil { + t.Error("Test failed - DepositViaPaymentMethod() error", err) + } + + _, err = g.DepositViaCoinbase(1, "BTC", "1337") + if err == nil { + t.Error("Test failed - DepositViaCoinbase() error", err) + } + + _, err = g.WithdrawViaPaymentMethod(1, "BTC", "1337") + if err == nil { + t.Error("Test failed - WithdrawViaPaymentMethod() error", err) + } + + // _, err := g.WithdrawViaCoinbase(1, "BTC", "c13cd0fc-72ca-55e9-843b-b84ef628c198") + // if err != nil { + // t.Error("Test failed - WithdrawViaCoinbase() error", err) + // } + + _, err = g.WithdrawCrypto(1, "BTC", "1337") + if err == nil { + t.Error("Test failed - WithdrawViaCoinbase() error", err) + } + + _, err = g.GetCoinbaseAccounts() + if err == nil { + t.Error("Test failed - GetCoinbaseAccounts() error", err) + } + + _, err = g.GetReportStatus("1337") + if err == nil { + t.Error("Test failed - GetReportStatus() error", err) + } + + _, err = g.GetTrailingVolume() + if err == nil { + t.Error("Test failed - GetTrailingVolume() error", err) + } } } diff --git a/exchanges/gdax/gdax_websocket.go b/exchanges/gdax/gdax_websocket.go index 423b2dcb..12507895 100644 --- a/exchanges/gdax/gdax_websocket.go +++ b/exchanges/gdax/gdax_websocket.go @@ -9,9 +9,10 @@ import ( ) const ( - GDAX_WEBSOCKET_URL = "wss://ws-feed.gdax.com" + gdaxWebsocketURL = "wss://ws-feed.gdax.com" ) +// WebsocketSubscribe subscribes to a websocket connection func (g *GDAX) WebsocketSubscribe(product string, conn *websocket.Conn) error { subscribe := WebsocketSubscribe{"subscribe", product} json, err := common.JSONEncode(subscribe) @@ -27,10 +28,11 @@ func (g *GDAX) WebsocketSubscribe(product string, conn *websocket.Conn) error { return nil } +// WebsocketClient initiates a websocket client func (g *GDAX) WebsocketClient() { for g.Enabled && g.Websocket { var Dialer websocket.Dialer - conn, _, err := Dialer.Dial(GDAX_WEBSOCKET_URL, http.Header{}) + conn, _, err := Dialer.Dial(gdaxWebsocketURL, http.Header{}) if err != nil { log.Printf("%s Unable to connect to Websocket. Error: %s\n", g.GetName(), err) diff --git a/exchanges/gdax/gdax_wrapper.go b/exchanges/gdax/gdax_wrapper.go index dfde1c69..2edbc563 100644 --- a/exchanges/gdax/gdax_wrapper.go +++ b/exchanges/gdax/gdax_wrapper.go @@ -19,7 +19,7 @@ func (g *GDAX) Start() { // Run implements the GDAX wrapper func (g *GDAX) Run() { if g.Verbose { - log.Printf("%s Websocket: %s. (url: %s).\n", g.GetName(), common.IsEnabled(g.Websocket), GDAX_WEBSOCKET_URL) + log.Printf("%s Websocket: %s. (url: %s).\n", g.GetName(), common.IsEnabled(g.Websocket), gdaxWebsocketURL) log.Printf("%s polling delay: %ds.\n", g.GetName(), g.RESTPollingDelay) log.Printf("%s %d currencies enabled: %s.\n", g.GetName(), len(g.EnabledPairs), g.EnabledPairs) } From 9a04d06890233e9dfc4ee05c1943379ab4245aee Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 11:59:57 +1100 Subject: [PATCH 06/12] Fixed linter issues for HitBTC exchange. --- exchanges/hitbtc/hitbtc.go | 164 +++++++++++++-------------- exchanges/hitbtc/hitbtc_types.go | 46 ++++++-- exchanges/hitbtc/hitbtc_websocket.go | 38 ++++--- exchanges/hitbtc/hitbtc_wrapper.go | 70 ++++++------ 4 files changed, 171 insertions(+), 147 deletions(-) diff --git a/exchanges/hitbtc/hitbtc.go b/exchanges/hitbtc/hitbtc.go index 96cba28b..716690d8 100644 --- a/exchanges/hitbtc/hitbtc.go +++ b/exchanges/hitbtc/hitbtc.go @@ -16,29 +16,29 @@ import ( const ( // API - APIURL = "https://api.hitbtc.com" + apiURL = "https://api.hitbtc.com" // Public - APIv2Trades = "api/2/public/trades" - APIv2Currency = "api/2/public/currency" - APIv2Symbol = "api/2/public/symbol" - APIv2Ticker = "api/2/public/ticker" - APIv2OrderBook = "api/2/public/orderbook" - APIv2Candles = "api/2/public/candles" + apiV2Trades = "api/2/public/trades" + apiV2Currency = "api/2/public/currency" + apiV2Symbol = "api/2/public/symbol" + apiV2Ticker = "api/2/public/ticker" + apiV2Orderbook = "api/2/public/orderbook" + apiV2Candles = "api/2/public/candles" // Authenticated - APIv2Balance = "api/2/trading/balance" - APIv2CryptoAddress = "api/2/account/crypto/address" - APIv2CryptoWithdraw = "api/2/account/crypto/withdraw" - APIv2TradeHistory = "api/2/history/trades" - APIv2FeeInfo = "api/2/trading/fee" - Orders = "order" - OrderBuy = "buy" - OrderSell = "sell" - OrderCancel = "cancelOrder" - OrderMove = "moveOrder" - TradableBalances = "returnTradableBalances" - TransferBalance = "transferBalance" + apiV2Balance = "api/2/trading/balance" + apiV2CryptoAddress = "api/2/account/crypto/address" + apiV2CryptoWithdraw = "api/2/account/crypto/withdraw" + apiV2TradeHistory = "api/2/history/trades" + apiV2FeeInfo = "api/2/trading/fee" + orders = "order" + orderBuy = "buy" + orderSell = "sell" + orderCancel = "cancelOrder" + orderMove = "moveOrder" + tradableBalances = "returnTradableBalances" + transferBalance = "transferBalance" ) // HitBTC is the overarching type across the hitbtc package @@ -94,36 +94,35 @@ func (p *HitBTC) GetFee() float64 { // Public Market Data // https://api.hitbtc.com/?python#market-data -// GetCurrencies -// Return the actual list of available currencies, tokens, ICO etc. +// GetCurrencies returns the actual list of available currencies, tokens, ICO +// etc. func (p *HitBTC) GetCurrencies(currency string) (map[string]Currencies, error) { type Response struct { Data []Currencies } resp := Response{} - path := fmt.Sprintf("%s/%s/%s", APIURL, APIv2Currency, currency) + path := fmt.Sprintf("%s/%s/%s", apiURL, apiV2Currency, currency) err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp.Data) ret := make(map[string]Currencies) for _, id := range resp.Data { - ret[id.Id] = id + ret[id.ID] = id } return ret, err } -// GetSymbols -// Return the actual list of currency symbols (currency pairs) traded on HitBTC exchange. -// The first listed currency of a symbol is called the base currency, and the second currency -// is called the quote currency. The currency pair indicates how much of the quote currency -// is needed to purchase one unit of the base currency. +// GetSymbols Return the actual list of currency symbols (currency pairs) traded +// on HitBTC exchange. The first listed currency of a symbol is called the base +// currency, and the second currency is called the quote currency. The currency +// pair indicates how much of the quote currency is needed to purchase one unit +// of the base currency. func (p *HitBTC) GetSymbols(symbol string) ([]string, error) { - resp := []Symbol{} - path := fmt.Sprintf("%s/%s/%s", APIURL, APIv2Symbol, symbol) + path := fmt.Sprintf("%s/%s/%s", apiURL, apiV2Symbol, symbol) err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp) ret := make([]string, 0, len(resp)) for _, x := range resp { - ret = append(ret, x.Id) + ret = append(ret, x.ID) } return ret, err @@ -133,19 +132,17 @@ func (p *HitBTC) GetSymbols(symbol string) ([]string, error) { // all ther details. func (p *HitBTC) GetSymbolsDetailed() ([]Symbol, error) { resp := []Symbol{} - path := fmt.Sprintf("%s/%s", APIURL, APIv2Symbol) + path := fmt.Sprintf("%s/%s", apiURL, apiV2Symbol) return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp) } -// GetTicker -// Return ticker information +// GetTicker returns ticker information func (p *HitBTC) GetTicker(symbol string) (map[string]Ticker, error) { - resp1 := []TickerResponse{} resp2 := TickerResponse{} ret := make(map[string]TickerResponse) result := make(map[string]Ticker) - path := fmt.Sprintf("%s/%s/%s", APIURL, APIv2Ticker, symbol) + path := fmt.Sprintf("%s/%s/%s", apiURL, apiV2Ticker, symbol) var err error if symbol == "" { @@ -236,14 +233,13 @@ func (p *HitBTC) GetTrades(currencyPair, from, till, limit, offset, by, sort str } resp := []TradeHistory{} - path := fmt.Sprintf("%s/%s/%s?%s", APIURL, APIv2Trades, currencyPair, vals.Encode()) + path := fmt.Sprintf("%s/%s/%s?%s", apiURL, apiV2Trades, currencyPair, vals.Encode()) return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp) } -// GetOrderbook -// An order book is an electronic list of buy and sell orders for a specific -// symbol, organized by price level. +// GetOrderbook an order book is an electronic list of buy and sell orders for a +// specific symbol, organized by price level. func (p *HitBTC) GetOrderbook(currencyPair string, limit int) (Orderbook, error) { // limit Limit of orderbook levels, default 100. Set 0 to view full orderbook levels vals := url.Values{} @@ -253,7 +249,7 @@ func (p *HitBTC) GetOrderbook(currencyPair string, limit int) (Orderbook, error) } resp := OrderbookResponse{} - path := fmt.Sprintf("%s/%s/%s?%s", APIURL, APIv2OrderBook, currencyPair, vals.Encode()) + path := fmt.Sprintf("%s/%s/%s?%s", apiURL, apiV2Orderbook, currencyPair, vals.Encode()) err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp) if err != nil { @@ -271,8 +267,7 @@ func (p *HitBTC) GetOrderbook(currencyPair string, limit int) (Orderbook, error) return ob, nil } -// GetCandles -// A candles used for OHLC a specific symbol. +// GetCandles returns candles which is used for OHLC a specific symbol. // Note: Result contain candles only with non zero volume. func (p *HitBTC) GetCandles(currencyPair, limit, period string) ([]ChartData, error) { // limit Limit of candles, default 100. @@ -288,24 +283,18 @@ func (p *HitBTC) GetCandles(currencyPair, limit, period string) ([]ChartData, er } resp := []ChartData{} - path := fmt.Sprintf("%s/%s/%s?%s", APIURL, APIv2Candles, currencyPair, vals.Encode()) + path := fmt.Sprintf("%s/%s/%s?%s", apiURL, apiV2Candles, currencyPair, vals.Encode()) - err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp) - if err != nil { - return nil, err - } - - return resp, nil + return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp) } // Authenticated Market Data // https://api.hitbtc.com/?python#market-data -// GetBalances +// GetBalances returns full balance for your account func (p *HitBTC) GetBalances() (map[string]Balance, error) { - result := []Balance{} - err := p.SendAuthenticatedHTTPRequest("GET", APIv2Balance, url.Values{}, &result) + err := p.SendAuthenticatedHTTPRequest("GET", apiV2Balance, url.Values{}, &result) ret := make(map[string]Balance) if err != nil { @@ -319,30 +308,31 @@ func (p *HitBTC) GetBalances() (map[string]Balance, error) { return ret, nil } +// GetDepositAddresses returns a deposit address for a specific currency func (p *HitBTC) GetDepositAddresses(currency string) (DepositCryptoAddresses, error) { resp := DepositCryptoAddresses{} - err := p.SendAuthenticatedHTTPRequest("GET", APIv2CryptoAddress+"/"+currency, url.Values{}, &resp) + err := p.SendAuthenticatedHTTPRequest("GET", apiV2CryptoAddress+"/"+currency, url.Values{}, &resp) return resp, err } +// GenerateNewAddress generates a new deposit address for a currency func (p *HitBTC) GenerateNewAddress(currency string) (DepositCryptoAddresses, error) { - resp := DepositCryptoAddresses{} - err := p.SendAuthenticatedHTTPRequest("POST", APIv2CryptoAddress+"/"+currency, url.Values{}, &resp) + err := p.SendAuthenticatedHTTPRequest("POST", apiV2CryptoAddress+"/"+currency, url.Values{}, &resp) return resp, err } -// Get Active orders -func (p *HitBTC) GetActiveOrders(currency string) ([]Order, error) { - +// GetActiveorders returns all your active orders +func (p *HitBTC) GetActiveorders(currency string) ([]Order, error) { resp := []Order{} - err := p.SendAuthenticatedHTTPRequest("GET", Orders+"?symbol="+currency, url.Values{}, &resp) + err := p.SendAuthenticatedHTTPRequest("GET", orders+"?symbol="+currency, url.Values{}, &resp) return resp, err } +// GetAuthenticatedTradeHistory returns your trade history func (p *HitBTC) GetAuthenticatedTradeHistory(currency, start, end string) (interface{}, error) { values := url.Values{} @@ -357,35 +347,26 @@ func (p *HitBTC) GetAuthenticatedTradeHistory(currency, start, end string) (inte if currency != "" && currency != "all" { values.Set("currencyPair", currency) result := AuthenticatedTradeHistoryResponse{} - err := p.SendAuthenticatedHTTPRequest("POST", APIv2TradeHistory, values, &result.Data) - if err != nil { - return result, err - } - - return result, nil - } else { - values.Set("currencyPair", "all") - result := AuthenticatedTradeHistoryAll{} - err := p.SendAuthenticatedHTTPRequest("POST", APIv2TradeHistory, values, &result.Data) - - if err != nil { - return result, err - } - - return result, nil + return result, p.SendAuthenticatedHTTPRequest("POST", apiV2TradeHistory, values, &result.Data) } + + values.Set("currencyPair", "all") + result := AuthenticatedTradeHistoryAll{} + + return result, p.SendAuthenticatedHTTPRequest("POST", apiV2TradeHistory, values, &result.Data) } +// PlaceOrder places an order on the exchange func (p *HitBTC) PlaceOrder(currency string, rate, amount float64, immediate, fillOrKill, buy bool) (OrderResponse, error) { result := OrderResponse{} values := url.Values{} var orderType string if buy { - orderType = OrderBuy + orderType = orderBuy } else { - orderType = OrderSell + orderType = orderSell } values.Set("currencyPair", currency) @@ -409,12 +390,13 @@ func (p *HitBTC) PlaceOrder(currency string, rate, amount float64, immediate, fi return result, nil } +// CancelOrder cancels a specific order by OrderID func (p *HitBTC) CancelOrder(orderID int64) (bool, error) { result := GenericResponse{} values := url.Values{} values.Set("orderNumber", strconv.FormatInt(orderID, 10)) - err := p.SendAuthenticatedHTTPRequest("POST", OrderCancel, values, &result) + err := p.SendAuthenticatedHTTPRequest("POST", orderCancel, values, &result) if err != nil { return false, err @@ -427,6 +409,7 @@ func (p *HitBTC) CancelOrder(orderID int64) (bool, error) { return true, nil } +// MoveOrder generates a new move order func (p *HitBTC) MoveOrder(orderID int64, rate, amount float64) (MoveOrderResponse, error) { result := MoveOrderResponse{} values := url.Values{} @@ -437,7 +420,7 @@ func (p *HitBTC) MoveOrder(orderID int64, rate, amount float64) (MoveOrderRespon values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) } - err := p.SendAuthenticatedHTTPRequest("POST", OrderMove, values, &result) + err := p.SendAuthenticatedHTTPRequest("POST", orderMove, values, &result) if err != nil { return result, err @@ -450,6 +433,7 @@ func (p *HitBTC) MoveOrder(orderID int64, rate, amount float64) (MoveOrderRespon return result, nil } +// Withdraw allows for the withdrawal to a specific address func (p *HitBTC) Withdraw(currency, address string, amount float64) (bool, error) { result := Withdraw{} values := url.Values{} @@ -458,7 +442,7 @@ func (p *HitBTC) Withdraw(currency, address string, amount float64) (bool, error values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) values.Set("address", address) - err := p.SendAuthenticatedHTTPRequest("POST", APIv2CryptoWithdraw, values, &result) + err := p.SendAuthenticatedHTTPRequest("POST", apiV2CryptoWithdraw, values, &result) if err != nil { return false, err @@ -471,20 +455,22 @@ func (p *HitBTC) Withdraw(currency, address string, amount float64) (bool, error return true, nil } +// GetFeeInfo returns current fee information func (p *HitBTC) GetFeeInfo(currencyPair string) (Fee, error) { result := Fee{} - err := p.SendAuthenticatedHTTPRequest("GET", APIv2FeeInfo+"/"+currencyPair, url.Values{}, &result) + err := p.SendAuthenticatedHTTPRequest("GET", apiV2FeeInfo+"/"+currencyPair, url.Values{}, &result) return result, err } +// GetTradableBalances returns current tradable balances func (p *HitBTC) GetTradableBalances() (map[string]map[string]float64, error) { type Response struct { Data map[string]map[string]interface{} } result := Response{} - err := p.SendAuthenticatedHTTPRequest("POST", TradableBalances, url.Values{}, &result.Data) + err := p.SendAuthenticatedHTTPRequest("POST", tradableBalances, url.Values{}, &result.Data) if err != nil { return nil, err @@ -502,6 +488,7 @@ func (p *HitBTC) GetTradableBalances() (map[string]map[string]float64, error) { return balances, nil } +// TransferBalance transfers a balance func (p *HitBTC) TransferBalance(currency, from, to string, amount float64) (bool, error) { values := url.Values{} result := GenericResponse{} @@ -511,7 +498,7 @@ func (p *HitBTC) TransferBalance(currency, from, to string, amount float64) (boo values.Set("fromAccount", from) values.Set("toAccount", to) - err := p.SendAuthenticatedHTTPRequest("POST", TransferBalance, values, &result) + err := p.SendAuthenticatedHTTPRequest("POST", transferBalance, values, &result) if err != nil { return false, err @@ -524,6 +511,7 @@ func (p *HitBTC) TransferBalance(currency, from, to string, amount float64) (boo return true, nil } +// SendAuthenticatedHTTPRequest sends an authenticated http request func (p *HitBTC) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error { if !p.AuthenticatedAPISupport { return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, p.Name) @@ -531,17 +519,17 @@ func (p *HitBTC) SendAuthenticatedHTTPRequest(method, endpoint string, values ur headers := make(map[string]string) headers["Authorization"] = "Basic " + common.Base64Encode([]byte(p.APIKey+":"+p.APISecret)) - path := fmt.Sprintf("%s/%s", APIURL, endpoint) - resp, err := common.SendHTTPRequest(method, path, headers, bytes.NewBufferString(values.Encode())) + path := fmt.Sprintf("%s/%s", apiURL, endpoint) + resp, err := common.SendHTTPRequest(method, path, headers, bytes.NewBufferString(values.Encode())) if err != nil { return err } err = common.JSONDecode([]byte(resp), &result) - if err != nil { - return errors.New("Unable to JSON Unmarshal response.") + return err } + return nil } diff --git a/exchanges/hitbtc/hitbtc_types.go b/exchanges/hitbtc/hitbtc_types.go index 2a7d3ccb..7a357b05 100644 --- a/exchanges/hitbtc/hitbtc_types.go +++ b/exchanges/hitbtc/hitbtc_types.go @@ -2,6 +2,7 @@ package hitbtc import "time" +// Ticker holds ticker information type Ticker struct { Last float64 Ask float64 @@ -15,6 +16,7 @@ type Ticker struct { Open float64 } +// TickerResponse is the response type type TickerResponse struct { Last string `json:"last"` // Last trade price Ask string `json:"ask"` // Best ask price @@ -28,8 +30,9 @@ type TickerResponse struct { Open string `json:"open"` // Last trade price 24 hours ago } +// Symbol holds symbol data type Symbol struct { - Id string `json:"id"` // Symbol identifier. In the future, the description will simply use the symbol + ID string `json:"id"` // Symbol identifier. In the future, the description will simply use the symbol BaseCurrency string `json:"baseCurrency"` QuoteCurrency string `json:"quoteCurrency"` QuantityIncrement float64 `json:"quantityIncrement,string"` @@ -39,29 +42,34 @@ type Symbol struct { FeeCurrency string `json:"feeCurrency"` // Default fee rate for market making trades } +// OrderbookResponse is the full orderbook response type OrderbookResponse struct { Asks []OrderbookItem `json:"ask"` // Ask side array of levels Bids []OrderbookItem `json:"bid"` // Bid side array of levels } +// OrderbookItem is a sub type for orderbook response type OrderbookItem struct { Price float64 `json:"price,string"` // Price level Amount float64 `json:"size,string"` // Total volume of orders with the specified price } +// Orderbook contains orderbook data type Orderbook struct { Asks []OrderbookItem `json:"asks"` Bids []OrderbookItem `json:"bids"` } +// TradeHistory contains trade history data type TradeHistory struct { - Id int64 `json:"id"` // Trade id + ID int64 `json:"id"` // Trade id Timestamp string `json:"timestamp"` // Trade timestamp Side string `json:"side"` // Trade side sell or buy Price float64 `json:"price,string"` // Trade price Quantity float64 `json:"quantity,string"` // Trade quantity } +// ChartData contains chart data type ChartData struct { Timestamp time.Time `json:"timestamp,string"` Max float64 `json:"max,string"` // Max price @@ -72,18 +80,20 @@ type ChartData struct { VolumeQuote float64 `json:"volumeQuote,string"` // Volume in quote currency } +// Currencies hold the full range of data for a specified currency type Currencies struct { - Id string `json:"id"` // Currency identifier. + ID string `json:"id"` // Currency identifier. FullName string `json:"fullName"` // Currency full name Crypto bool `json:"crypto,boolean"` // Is currency belongs to blockchain (false for ICO and fiat, like EUR) PayinEnabled bool `json:"payinEnabled"` // Is allowed for deposit (false for ICO) - PayinPaymentId bool `json:"payinPaymentId"` // Is required to provide additional information other than the address for deposit + PayinPaymentID bool `json:"payinPaymentId"` // Is required to provide additional information other than the address for deposit PayinConfirmations int64 `json:"payinConfirmations"` // Blocks confirmations count for deposit PayoutEnabled bool `json:"payoutEnabled"` // Is allowed for withdraw (false for ICO) - PayoutIsPaymentId bool `json:"payoutIsPaymentId"` // Is allowed to provide additional information for withdraw + PayoutIsPaymentID bool `json:"payoutIsPaymentId"` // Is allowed to provide additional information for withdraw TransferEnabled bool `json:"transferEnabled"` // Is allowed to transfer between trading and account (may be disabled on maintain) } +// LoanOrder contains information about your loans type LoanOrder struct { Rate float64 `json:"rate,string"` Amount float64 `json:"amount,string"` @@ -91,11 +101,13 @@ type LoanOrder struct { RangeMax int `json:"rangeMax"` } +// LoanOrders holds information on the full range of loan orders type LoanOrders struct { Offers []LoanOrder `json:"offers"` Demands []LoanOrder `json:"demands"` } +// Balance is a simple balance type type Balance struct { Currency string `json:"currency"` Available float64 `json:"available,string"` // Amount available for trading or transfer to main account @@ -103,14 +115,16 @@ type Balance struct { } +// DepositCryptoAddresses contains address information type DepositCryptoAddresses struct { Address string `json:"address"` // Address for deposit - PaymentId string `json:"paymentId"` // Optional additional parameter. Required for deposit if persist + PaymentID string `json:"paymentId"` // Optional additional parameter. Required for deposit if persist } +// Order contains information about an order type Order struct { - Id int64 `json:"id,string"` // Unique identifier for Order as assigned by exchange - ClientOrderId string `json:"clientOrderId"` // Unique identifier for Order as assigned by trader. Uniqueness must be + ID int64 `json:"id,string"` // Unique identifier for Order as assigned by exchange + ClientOrderID string `json:"clientOrderId"` // Unique identifier for Order as assigned by trader. Uniqueness must be // guaranteed within a single trading day, including all active orders. Symbol string `json:"symbol"` // Trading symbol Side string `json:"side"` // sell buy @@ -134,14 +148,17 @@ type Order struct { ExpireTime time.Time `json:"expireTime,string"` } +// OpenOrdersResponseAll holds the full open order response type OpenOrdersResponseAll struct { Data map[string][]Order } +// OpenOrdersResponse contains open order information type OpenOrdersResponse struct { Data []Order } +// AuthentictedTradeHistory contains trade history data type AuthentictedTradeHistory struct { GlobalTradeID int64 `json:"globalTradeID"` TradeID int64 `json:"tradeID,string"` @@ -155,14 +172,17 @@ type AuthentictedTradeHistory struct { Category string `json:"category"` } +// AuthenticatedTradeHistoryAll contains the full trade history type AuthenticatedTradeHistoryAll struct { Data map[string][]AuthentictedTradeHistory } +// AuthenticatedTradeHistoryResponse is the resp type for trade history type AuthenticatedTradeHistoryResponse struct { Data []AuthentictedTradeHistory } +// ResultingTrades holds resulting trade information type ResultingTrades struct { Amount float64 `json:"amount,string"` Date string `json:"date"` @@ -172,16 +192,19 @@ type ResultingTrades struct { Type string `json:"type"` } +// OrderResponse holds the order response information type OrderResponse struct { OrderNumber int64 `json:"orderNumber,string"` Trades []ResultingTrades `json:"resultingTrades"` } +// GenericResponse is the common response from HitBTC type GenericResponse struct { Success int `json:"success"` Error string `json:"error"` } +// MoveOrderResponse holds information about a move order type MoveOrderResponse struct { Success int `json:"success"` Error string `json:"error"` @@ -189,16 +212,19 @@ type MoveOrderResponse struct { Trades map[string][]ResultingTrades `json:"resultingTrades"` } +// Withdraw holds response for a withdrawel process type Withdraw struct { Response string `json:"response"` Error string `json:"error"` } +// Fee holds fee structure type Fee struct { TakeLiquidityRate float64 `json:"takeLiquidityRate,string"` // Taker ProvideLiquidityRate float64 `json:"provideLiquidityRate,string"` // Maker } +// Margin holds full margin information type Margin struct { TotalValue float64 `json:"totalValue,string"` ProfitLoss float64 `json:"pl,string"` @@ -208,6 +234,7 @@ type Margin struct { CurrentMargin float64 `json:"currentMargin,string"` } +// MarginPosition holds information about your current margin position type MarginPosition struct { Amount float64 `json:"amount,string"` Total float64 `json:"total,string"` @@ -218,6 +245,7 @@ type MarginPosition struct { Type string `json:"type"` } +// LoanOffer holds information about your loan offers type LoanOffer struct { ID int64 `json:"id"` Rate float64 `json:"rate,string"` @@ -227,11 +255,13 @@ type LoanOffer struct { Date string `json:"date"` } +// ActiveLoans holds information about your active loans type ActiveLoans struct { Provided []LoanOffer `json:"provided"` Used []LoanOffer `json:"used"` } +// LendingHistory contains lending history data type LendingHistory struct { ID int64 `json:"id"` Currency string `json:"currency"` diff --git a/exchanges/hitbtc/hitbtc_websocket.go b/exchanges/hitbtc/hitbtc_websocket.go index 5552f8dd..623429fb 100644 --- a/exchanges/hitbtc/hitbtc_websocket.go +++ b/exchanges/hitbtc/hitbtc_websocket.go @@ -8,13 +8,14 @@ import ( ) const ( - HITBTC_WEBSOCKET_ADDRESS = "wss://api.hitbtc.com" - HITBTC_WEBSOCKET_REALM = "realm1" - HITBTC_WEBSOCKET_TICKER = "ticker" - HITBTC_WEBSOCKET_TROLLBOX = "trollbox" + hitbtcWebsocketAddress = "wss://api.hitbtc.com" + hitbtcWebsocketRealm = "realm1" + hitbtcWebsocketTicker = "ticker" + hitbtcWebsocketTrollbox = "trollbox" ) -type HitBTCWebsocketTicker struct { +// WebsocketTicker holds ticker data +type WebsocketTicker struct { CurrencyPair string Last float64 LowestAsk float64 @@ -27,8 +28,9 @@ type HitBTCWebsocketTicker struct { Low float64 } -func HitBTCOnTicker(args []interface{}, kwargs map[string]interface{}) { - ticker := HitBTCWebsocketTicker{} +// OnTicker converts ticker to websocket ticker +func OnTicker(args []interface{}, kwargs map[string]interface{}) { + ticker := WebsocketTicker{} ticker.CurrencyPair = args[0].(string) ticker.Last, _ = strconv.ParseFloat(args[1].(string), 64) ticker.LowestAsk, _ = strconv.ParseFloat(args[2].(string), 64) @@ -47,15 +49,17 @@ func HitBTCOnTicker(args []interface{}, kwargs map[string]interface{}) { ticker.Low, _ = strconv.ParseFloat(args[9].(string), 64) } -type HitBTCWebsocketTrollboxMessage struct { +// WebsocketTrollboxMessage contains trollbox message information +type WebsocketTrollboxMessage struct { MessageNumber float64 Username string Message string Reputation float64 } -func HitBTCOnTrollbox(args []interface{}, kwargs map[string]interface{}) { - message := HitBTCWebsocketTrollboxMessage{} +// OnTrollbox converts trollbox messages +func OnTrollbox(args []interface{}, kwargs map[string]interface{}) { + message := WebsocketTrollboxMessage{} message.MessageNumber, _ = args[1].(float64) message.Username = args[2].(string) message.Message = args[3].(string) @@ -64,7 +68,8 @@ func HitBTCOnTrollbox(args []interface{}, kwargs map[string]interface{}) { } } -func HitBTCOnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) { +// OnDepthOrTrade converts depth and trade data +func OnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) { for x := range args { data := args[x].(map[string]interface{}) msgData := data["data"].(map[string]interface{}) @@ -133,9 +138,10 @@ func HitBTCOnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) { } } +// WebsocketClient initiates a websocket client func (p *HitBTC) WebsocketClient() { for p.Enabled && p.Websocket { - c, err := turnpike.NewWebsocketClient(turnpike.JSON, HITBTC_WEBSOCKET_ADDRESS, nil) + c, err := turnpike.NewWebsocketClient(turnpike.JSON, hitbtcWebsocketAddress, nil) if err != nil { log.Printf("%s Unable to connect to Websocket. Error: %s\n", p.GetName(), err) continue @@ -145,7 +151,7 @@ func (p *HitBTC) WebsocketClient() { log.Printf("%s Connected to Websocket.\n", p.GetName()) } - _, err = c.JoinRealm(HITBTC_WEBSOCKET_REALM, nil) + _, err = c.JoinRealm(hitbtcWebsocketRealm, nil) if err != nil { log.Printf("%s Unable to join realm. Error: %s\n", p.GetName(), err) continue @@ -157,17 +163,17 @@ func (p *HitBTC) WebsocketClient() { c.ReceiveDone = make(chan bool) - if err := c.Subscribe(HITBTC_WEBSOCKET_TICKER, HitBTCOnTicker); err != nil { + if err := c.Subscribe(hitbtcWebsocketTicker, OnTicker); err != nil { log.Printf("%s Error subscribing to ticker channel: %s\n", p.GetName(), err) } - if err := c.Subscribe(HITBTC_WEBSOCKET_TROLLBOX, HitBTCOnTrollbox); err != nil { + if err := c.Subscribe(hitbtcWebsocketTrollbox, OnTrollbox); err != nil { log.Printf("%s Error subscribing to trollbox channel: %s\n", p.GetName(), err) } for x := range p.EnabledPairs { currency := p.EnabledPairs[x] - if err := c.Subscribe(currency, HitBTCOnDepthOrTrade); err != nil { + if err := c.Subscribe(currency, OnDepthOrTrade); err != nil { log.Printf("%s Error subscribing to %s channel: %s\n", p.GetName(), currency, err) } } diff --git a/exchanges/hitbtc/hitbtc_wrapper.go b/exchanges/hitbtc/hitbtc_wrapper.go index 2eb7d025..d5489cd7 100644 --- a/exchanges/hitbtc/hitbtc_wrapper.go +++ b/exchanges/hitbtc/hitbtc_wrapper.go @@ -12,28 +12,28 @@ import ( ) // Start starts the HitBTC go routine -func (p *HitBTC) Start() { - go p.Run() +func (h *HitBTC) Start() { + go h.Run() } // Run implements the HitBTC wrapper -func (p *HitBTC) Run() { - if p.Verbose { - log.Printf("%s Websocket: %s (url: %s).\n", p.GetName(), common.IsEnabled(p.Websocket), HITBTC_WEBSOCKET_ADDRESS) - log.Printf("%s polling delay: %ds.\n", p.GetName(), p.RESTPollingDelay) - log.Printf("%s %d currencies enabled: %s.\n", p.GetName(), len(p.EnabledPairs), p.EnabledPairs) +func (h *HitBTC) Run() { + if h.Verbose { + log.Printf("%s Websocket: %s (url: %s).\n", h.GetName(), common.IsEnabled(h.Websocket), hitbtcWebsocketAddress) + log.Printf("%s polling delay: %ds.\n", h.GetName(), h.RESTPollingDelay) + log.Printf("%s %d currencies enabled: %s.\n", h.GetName(), len(h.EnabledPairs), h.EnabledPairs) } - if p.Websocket { - go p.WebsocketClient() + if h.Websocket { + go h.WebsocketClient() } - exchangeProducts, err := p.GetSymbolsDetailed() + exchangeProducts, err := h.GetSymbolsDetailed() if err != nil { - log.Printf("%s Failed to get available symbols.\n", p.GetName()) + log.Printf("%s Failed to get available symbols.\n", h.GetName()) } else { forceUpgrade := false - if !common.StringDataContains(p.EnabledPairs, "-") || !common.StringDataContains(p.AvailablePairs, "-") { + if !common.StringDataContains(h.EnabledPairs, "-") || !common.StringDataContains(h.AvailablePairs, "-") { forceUpgrade = true } var currencies []string @@ -45,28 +45,28 @@ func (p *HitBTC) Run() { enabledPairs := []string{"BTC-USD"} log.Println("WARNING: Available pairs for HitBTC reset due to config upgrade, please enable the ones you would like again.") - err = p.UpdateEnabledCurrencies(enabledPairs, true) + err = h.UpdateEnabledCurrencies(enabledPairs, true) if err != nil { - log.Printf("%s Failed to update enabled currencies.\n", p.GetName()) + log.Printf("%s Failed to update enabled currencies.\n", h.GetName()) } } - err = p.UpdateAvailableCurrencies(currencies, forceUpgrade) + err = h.UpdateAvailableCurrencies(currencies, forceUpgrade) if err != nil { - log.Printf("%s Failed to update available currencies.\n", p.GetName()) + log.Printf("%s Failed to update available currencies.\n", h.GetName()) } } } // UpdateTicker updates and returns the ticker for a currency pair -func (p *HitBTC) UpdateTicker(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) { - tick, err := p.GetTicker("") +func (h *HitBTC) UpdateTicker(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) { + tick, err := h.GetTicker("") if err != nil { return ticker.Price{}, err } - for _, x := range p.GetEnabledCurrencies() { + for _, x := range h.GetEnabledCurrencies() { var tp ticker.Price - curr := exchange.FormatExchangeCurrency(p.GetName(), x).String() + curr := exchange.FormatExchangeCurrency(h.GetName(), x).String() tp.Pair = x tp.Ask = tick[curr].Ask tp.Bid = tick[curr].Bid @@ -74,33 +74,33 @@ func (p *HitBTC) UpdateTicker(currencyPair pair.CurrencyPair, assetType string) tp.Last = tick[curr].Last tp.Low = tick[curr].Low tp.Volume = tick[curr].Volume - ticker.ProcessTicker(p.GetName(), x, tp, assetType) + ticker.ProcessTicker(h.GetName(), x, tp, assetType) } - return ticker.GetTicker(p.Name, currencyPair, assetType) + return ticker.GetTicker(h.Name, currencyPair, assetType) } // GetTickerPrice returns the ticker for a currency pair -func (p *HitBTC) GetTickerPrice(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) { - tickerNew, err := ticker.GetTicker(p.GetName(), currencyPair, assetType) +func (h *HitBTC) GetTickerPrice(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) { + tickerNew, err := ticker.GetTicker(h.GetName(), currencyPair, assetType) if err != nil { - return p.UpdateTicker(currencyPair, assetType) + return h.UpdateTicker(currencyPair, assetType) } return tickerNew, nil } // GetOrderbookEx returns orderbook base on the currency pair -func (p *HitBTC) GetOrderbookEx(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) { - ob, err := orderbook.GetOrderbook(p.GetName(), currencyPair, assetType) +func (h *HitBTC) GetOrderbookEx(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) { + ob, err := orderbook.GetOrderbook(h.GetName(), currencyPair, assetType) if err != nil { - return p.UpdateOrderbook(currencyPair, assetType) + return h.UpdateOrderbook(currencyPair, assetType) } return ob, nil } // UpdateOrderbook updates and returns the orderbook for a currency pair -func (p *HitBTC) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) { +func (h *HitBTC) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) { var orderBook orderbook.Base - orderbookNew, err := p.GetOrderbook(exchange.FormatExchangeCurrency(p.GetName(), currencyPair).String(), 1000) + orderbookNew, err := h.GetOrderbook(exchange.FormatExchangeCurrency(h.GetName(), currencyPair).String(), 1000) if err != nil { return orderBook, err } @@ -115,16 +115,16 @@ func (p *HitBTC) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType strin orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data.Amount, Price: data.Price}) } - orderbook.ProcessOrderbook(p.GetName(), currencyPair, orderBook, assetType) - return orderbook.GetOrderbook(p.Name, currencyPair, assetType) + orderbook.ProcessOrderbook(h.GetName(), currencyPair, orderBook, assetType) + return orderbook.GetOrderbook(h.Name, currencyPair, assetType) } // GetExchangeAccountInfo retrieves balances for all enabled currencies for the // HitBTC exchange -func (p *HitBTC) GetExchangeAccountInfo() (exchange.AccountInfo, error) { +func (h *HitBTC) GetExchangeAccountInfo() (exchange.AccountInfo, error) { var response exchange.AccountInfo - response.ExchangeName = p.GetName() - accountBalance, err := p.GetBalances() + response.ExchangeName = h.GetName() + accountBalance, err := h.GetBalances() if err != nil { return response, err } From bfdb6ba3076bdcfef8f02bd9f71258a0d1d70246 Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 13:26:40 +1100 Subject: [PATCH 07/12] Fixed go vet and linter issues for Huobi exchange. --- exchanges/huobi/huobi.go | 10 ++-- exchanges/huobi/huobi_websocket.go | 96 +++++++++++++++++------------- exchanges/huobi/huobi_wrapper.go | 12 ++-- 3 files changed, 67 insertions(+), 51 deletions(-) diff --git a/exchanges/huobi/huobi.go b/exchanges/huobi/huobi.go index 18dcd1aa..e57699e2 100644 --- a/exchanges/huobi/huobi.go +++ b/exchanges/huobi/huobi.go @@ -176,7 +176,7 @@ func (h *HUOBI) GetTrades(symbol string) ([]Trade, error) { type response struct { Response - tick struct { + Tick struct { Data []Trade `json:"data"` } `json:"tick"` } @@ -188,7 +188,7 @@ func (h *HUOBI) GetTrades(symbol string) ([]Trade, error) { if result.ErrorMessage != "" { return nil, errors.New(result.ErrorMessage) } - return result.tick.Data, err + return result.Tick.Data, err } // GetTradeHistory returns the trades for the specified symbol @@ -222,7 +222,7 @@ func (h *HUOBI) GetMarketDetail(symbol string) (Detail, error) { type response struct { Response - tick Detail `json:"tick"` + Tick Detail `json:"tick"` } var result response @@ -230,9 +230,9 @@ func (h *HUOBI) GetMarketDetail(symbol string) (Detail, error) { err := common.SendHTTPGetRequest(common.EncodeURLValues(url, vals), true, h.Verbose, &result) if result.ErrorMessage != "" { - return result.tick, errors.New(result.ErrorMessage) + return result.Tick, errors.New(result.ErrorMessage) } - return result.tick, err + return result.Tick, err } // GetSymbols returns an array of symbols supported by Huobi diff --git a/exchanges/huobi/huobi_websocket.go b/exchanges/huobi/huobi_websocket.go index 1120afc8..affe3825 100644 --- a/exchanges/huobi/huobi_websocket.go +++ b/exchanges/huobi/huobi_websocket.go @@ -8,39 +8,41 @@ import ( ) const ( - HUOBI_SOCKETIO_ADDRESS = "https://hq.huobi.com:443" + huobiSocketIOAddress = "https://hq.huobi.com:443" //Service API - HUOBI_SOCKET_REQ_SYMBOL_LIST = "reqSymbolList" - HUOBI_SOCKET_REQ_SYMBOL_DETAIL = "reqSymbolDetail" - HUOBI_SOCKET_REQ_SUBSCRIBE = "reqMsgSubscribe" - HUOBI_SOCKET_REQ_UNSUBSCRIBE = "reqMsgUnsubscribe" + huobiSocketReqSymbolList = "reqSymbolList" + huobiSocketReqSymbolDetail = "reqSymbolDetail" + huobiSocketReqSubscribe = "reqMsgSubscribe" + huobiSocketReqUnsubscribe = "reqMsgUnsubscribe" // Market data API - HUOBI_SOCKET_MARKET_DETAIL = "marketDetail" - HUOBI_SOCKET_TRADE_DETAIL = "tradeDetail" - HUOBI_SOCKET_MARKET_DEPTH_TOP = "marketDepthTop" - HUOBI_SOCKET_MARKET_DEPTH_TOP_SHORT = "marketDepthTopShort" - HUOBI_SOCKET_MARKET_DEPTH = "marketDepth" - HUOBI_SOCKET_MARKET_DEPTH_TOP_DIFF = "marketDepthTopDiff" - HUOBI_SOCKET_MARKET_DEPTH_DIFF = "marketDepthDiff" - HUOBI_SOCKET_MARKET_LAST_KLINE = "lastKLine" - HUOBI_SOCKET_MARKET_LAST_TIMELINE = "lastTimeLine" - HUOBI_SOCKET_MARKET_OVERVIEW = "marketOverview" - HUOBI_SOCKET_MARKET_STATIC = "marketStatic" + huobiSocketMarketDetail = "marketDetail" + huobiSocketTradeDetail = "tradeDetail" + huobiSocketMarketDepthTop = "marketDepthTop" + huobiSocketMarketDepthTopShort = "marketDepthTopShort" + huobiSocketMarketDepth = "marketDepth" + huobiSocketMarketDepthTopDiff = "marketDepthTopDiff" + huobiSocketMarketDepthDiff = "marketDepthDiff" + huobiSocketMarketLastKline = "lastKLine" + huobiSocketMarketLastTimeline = "lastTimeLine" + huobiSocketMarketOverview = "marketOverview" + huobiSocketMarketStatic = "marketStatic" // History data API - HUOBI_SOCKET_REQ_TIMELINE = "reqTimeLine" - HUOBI_SOCKET_REQ_KLINE = "reqKLine" - HUOBI_SOCKET_REQ_DEPTH_TOP = "reqMarketDepthTop" - HUOBI_SOCKET_REQ_DEPTH = "reqMarketDepth" - HUOBI_SOCKET_REQ_TRADE_DETAIL_TOP = "reqTradeDetailTop" - HUOBI_SOCKET_REQ_MARKET_DETAIL = "reqMarketDetail" + huobiSocketReqTimeline = "reqTimeLine" + huobiSocketReqKline = "reqKLine" + huobiSocketReqDepthTop = "reqMarketDepthTop" + huobiSocketReqDepth = "reqMarketDepth" + huobiSocketReqTradeDetailTop = "reqTradeDetailTop" + huobiSocketReqMarketDetail = "reqMarketDetail" ) +// HuobiSocket is a pointer to a IO Socket var HuobiSocket *socketio.SocketIO -type HuobiDepth struct { +// Depth holds depth information +type Depth struct { SymbolID string `json:"symbolId"` Time float64 `json:"time"` Version float64 `json:"version"` @@ -54,24 +56,27 @@ type HuobiDepth struct { AskAmount []float64 `json:"askAmount"` } -type HuobiWebsocketTrade struct { +// WebsocketTrade holds full trade data +type WebsocketTrade struct { Price []float64 `json:"price"` Level []float64 `json:"level"` Amount []float64 `json:"amount"` AccuAmount []float64 `json:"accuAmount"` } -type HuobiWebsocketTradeDetail struct { - SymbolID string `json:"symbolId"` - TradeID []int64 `json:"tradeId"` - Price []float64 `json:"price"` - Time []int64 `json:"time"` - Amount []float64 `json:"amount"` - TopBids []HuobiWebsocketTrade `json:"topBids"` - TopAsks []HuobiWebsocketTrade `json:"topAsks"` +// WebsocketTradeDetail holds specific trade details +type WebsocketTradeDetail struct { + SymbolID string `json:"symbolId"` + TradeID []int64 `json:"tradeId"` + Price []float64 `json:"price"` + Time []int64 `json:"time"` + Amount []float64 `json:"amount"` + TopBids []WebsocketTrade `json:"topBids"` + TopAsks []WebsocketTrade `json:"topAsks"` } -type HuobiWebsocketMarketOverview struct { +// WebsocketMarketOverview holds market overview data +type WebsocketMarketOverview struct { SymbolID string `json:"symbolId"` Last float64 `json:"priceNew"` Open float64 `json:"priceOpen"` @@ -83,7 +88,8 @@ type HuobiWebsocketMarketOverview struct { TotalAmount float64 `json:"totalAmount"` } -type HuobiWebsocketLastTimeline struct { +// WebsocketLastTimeline holds timeline data +type WebsocketLastTimeline struct { ID int64 `json:"_id"` SymbolID string `json:"symbolId"` Time int64 `json:"time"` @@ -93,7 +99,8 @@ type HuobiWebsocketLastTimeline struct { Count int64 `json:"count"` } -type HuobiResponse struct { +// WebsocketResponse is a general response type for websocket +type WebsocketResponse struct { Version int `json:"version"` MsgType string `json:"msgType"` RequestIndex int64 `json:"requestIndex"` @@ -102,6 +109,7 @@ type HuobiResponse struct { Payload map[string]interface{} `json:"payload"` } +// BuildHuobiWebsocketRequest packages a new request func (h *HUOBI) BuildHuobiWebsocketRequest(msgType string, requestIndex int64, symbolRequest []string) map[string]interface{} { request := map[string]interface{}{} request["version"] = 1 @@ -118,7 +126,8 @@ func (h *HUOBI) BuildHuobiWebsocketRequest(msgType string, requestIndex int64, s return request } -func (h *HUOBI) BuildHuobiWebsocketRequestExtra(msgType string, requestIndex int64, symbolIdList interface{}) interface{} { +// BuildHuobiWebsocketRequestExtra packages an extra request +func (h *HUOBI) BuildHuobiWebsocketRequestExtra(msgType string, requestIndex int64, symbolIDList interface{}) interface{} { request := map[string]interface{}{} request["version"] = 1 request["msgType"] = msgType @@ -127,10 +136,11 @@ func (h *HUOBI) BuildHuobiWebsocketRequestExtra(msgType string, requestIndex int request["requestIndex"] = requestIndex } - request["symbolList"] = symbolIdList + request["symbolList"] = symbolIDList return request } +// BuildHuobiWebsocketParamsList packages a parameter list func (h *HUOBI) BuildHuobiWebsocketParamsList(objectName, currency, pushType, period, count, from, to, percentage string) interface{} { list := map[string]interface{}{} list["symbolId"] = currency @@ -160,6 +170,7 @@ func (h *HUOBI) BuildHuobiWebsocketParamsList(objectName, currency, pushType, pe return listCompleted } +// OnConnect handles connection establishment func (h *HUOBI) OnConnect(output chan socketio.Message) { if h.Verbose { log.Printf("%s Connected to Websocket.", h.GetName()) @@ -167,7 +178,7 @@ func (h *HUOBI) OnConnect(output chan socketio.Message) { for _, x := range h.EnabledPairs { currency := common.StringToLower(x) - msg := h.BuildHuobiWebsocketRequestExtra(HUOBI_SOCKET_REQ_SUBSCRIBE, 100, h.BuildHuobiWebsocketParamsList(HUOBI_SOCKET_MARKET_OVERVIEW, currency, "pushLong", "", "", "", "", "")) + msg := h.BuildHuobiWebsocketRequestExtra(huobiSocketReqSubscribe, 100, h.BuildHuobiWebsocketParamsList(huobiSocketMarketOverview, currency, "pushLong", "", "", "", "", "")) result, err := common.JSONEncode(msg) if err != nil { log.Println(err) @@ -176,27 +187,32 @@ func (h *HUOBI) OnConnect(output chan socketio.Message) { } } +// OnDisconnect handles disconnection func (h *HUOBI) OnDisconnect(output chan socketio.Message) { log.Printf("%s Disconnected from websocket server.. Reconnecting.\n", h.GetName()) h.WebsocketClient() } +// OnError handles error issues func (h *HUOBI) OnError() { log.Printf("%s Error with Websocket connection.. Reconnecting.\n", h.GetName()) h.WebsocketClient() } +// OnMessage handles messages from the exchange func (h *HUOBI) OnMessage(message []byte, output chan socketio.Message) { } +// OnRequest handles requests func (h *HUOBI) OnRequest(message []byte, output chan socketio.Message) { - response := HuobiResponse{} + response := WebsocketResponse{} err := common.JSONDecode(message, &response) if err != nil { log.Println(err) } } +// WebsocketClient creates a new websocket client func (h *HUOBI) WebsocketClient() { events := make(map[string]func(message []byte, output chan socketio.Message)) events["request"] = h.OnRequest @@ -211,7 +227,7 @@ func (h *HUOBI) WebsocketClient() { } for h.Enabled && h.Websocket { - err := socketio.ConnectToSocket(HUOBI_SOCKETIO_ADDRESS, HuobiSocket) + err := socketio.ConnectToSocket(huobiSocketIOAddress, HuobiSocket) if err != nil { log.Printf("%s Unable to connect to Websocket. Err: %s\n", h.GetName(), err) continue diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index 47239f11..f70623fb 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -20,7 +20,7 @@ func (h *HUOBI) Start() { // Run implements the HUOBI wrapper func (h *HUOBI) Run() { if h.Verbose { - log.Printf("%s Websocket: %s (url: %s).\n", h.GetName(), common.IsEnabled(h.Websocket), HUOBI_SOCKETIO_ADDRESS) + log.Printf("%s Websocket: %s (url: %s).\n", h.GetName(), common.IsEnabled(h.Websocket), huobiSocketIOAddress) log.Printf("%s polling delay: %ds.\n", h.GetName(), h.RESTPollingDelay) log.Printf("%s %d currencies enabled: %s.\n", h.GetName(), len(h.EnabledPairs), h.EnabledPairs) } @@ -40,17 +40,17 @@ func (h *HUOBI) Run() { if common.StringDataContains(h.BaseCurrencies, "CNY") { cfg := config.GetConfig() - exchCfg, err := cfg.GetExchangeConfig(h.Name) + exchCfg, errCNY := cfg.GetExchangeConfig(h.Name) if err != nil { - log.Printf("%s failed to get exchange config. %s\n", h.Name, err) + log.Printf("%s failed to get exchange config. %s\n", h.Name, errCNY) return } exchCfg.BaseCurrencies = "USD" h.BaseCurrencies = []string{"USD"} - err = cfg.UpdateExchangeConfig(exchCfg) - if err != nil { - log.Printf("%s failed to update config. %s\n", h.Name, err) + errCNY = cfg.UpdateExchangeConfig(exchCfg) + if errCNY != nil { + log.Printf("%s failed to update config. %s\n", h.Name, errCNY) return } } From 5dc8ddf404fb70084d3e1e6c792396079b32ee66 Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 13:59:12 +1100 Subject: [PATCH 08/12] Fixed linter issues, fixed test deployment for auth request, added data types for error returns for Liqui Exchange. --- exchanges/liqui/liqui.go | 28 +++++++---- exchanges/liqui/liqui_test.go | 80 ++++++++++++++++---------------- exchanges/liqui/liqui_types.go | 34 ++++++++++---- exchanges/liqui/liqui_wrapper.go | 2 +- 4 files changed, 83 insertions(+), 61 deletions(-) diff --git a/exchanges/liqui/liqui.go b/exchanges/liqui/liqui.go index c9f8cc2f..573465a5 100644 --- a/exchanges/liqui/liqui.go +++ b/exchanges/liqui/liqui.go @@ -84,7 +84,6 @@ func (l *Liqui) Setup(exch config.ExchangeConfig) { // GetFee returns a fee for a specific currency func (l *Liqui) GetFee(currency string) (float64, error) { - log.Println(l.Info.Pairs) val, ok := l.Info.Pairs[common.StringToLower(currency)] if !ok { return 0, errors.New("currency does not exist") @@ -124,10 +123,12 @@ func (l *Liqui) GetInfo() (Info, error) { // currencyPair - example "eth_btc" func (l *Liqui) GetTicker(currencyPair string) (map[string]Ticker, error) { type Response struct { - Data map[string]Ticker + Data map[string]Ticker + Success int `json:"success"` + Error string `json:"error"` } - response := Response{} + response := Response{Data: make(map[string]Ticker)} req := fmt.Sprintf("%s/%s/%s/%s", liquiAPIPublicURL, liquiAPIPublicVersion, liquiTicker, currencyPair) return response.Data, @@ -139,10 +140,12 @@ func (l *Liqui) GetTicker(currencyPair string) (map[string]Ticker, error) { // displayed (150 by default). Is set to less than 2000. func (l *Liqui) GetDepth(currencyPair string) (Orderbook, error) { type Response struct { - Data map[string]Orderbook + Data map[string]Orderbook + Success int `json:"success"` + Error string `json:"error"` } - response := Response{} + response := Response{Data: make(map[string]Orderbook)} req := fmt.Sprintf("%s/%s/%s/%s", liquiAPIPublicURL, liquiAPIPublicVersion, liquiDepth, currencyPair) return response.Data[currencyPair], @@ -154,10 +157,12 @@ func (l *Liqui) GetDepth(currencyPair string) (Orderbook, error) { // displayed (150 by default). The maximum allowable value is 2000. func (l *Liqui) GetTrades(currencyPair string) ([]Trades, error) { type Response struct { - Data map[string][]Trades + Data map[string][]Trades + Success int `json:"success"` + Error string `json:"error"` } - response := Response{} + response := Response{Data: make(map[string][]Trades)} req := fmt.Sprintf("%s/%s/%s/%s", liquiAPIPublicURL, liquiAPIPublicVersion, liquiTrades, currencyPair) return response.Data[currencyPair], @@ -190,19 +195,21 @@ func (l *Liqui) Trade(pair, orderType string, amount, price float64) (float64, e // GetActiveOrders returns the list of your active orders. func (l *Liqui) GetActiveOrders(pair string) (map[string]ActiveOrders, error) { + result := make(map[string]ActiveOrders) + req := url.Values{} req.Add("pair", pair) - var result map[string]ActiveOrders return result, l.SendAuthenticatedHTTPRequest(liquiActiveOrders, req, &result) } // GetOrderInfo returns the information on particular order. func (l *Liqui) GetOrderInfo(OrderID int64) (map[string]OrderInfo, error) { + result := make(map[string]OrderInfo) + req := url.Values{} req.Add("order_id", strconv.FormatInt(OrderID, 10)) - var result map[string]OrderInfo return result, l.SendAuthenticatedHTTPRequest(liquiOrderInfo, req, &result) } @@ -223,11 +230,12 @@ func (l *Liqui) CancelOrder(OrderID int64) (bool, error) { // GetTradeHistory returns trade history func (l *Liqui) GetTradeHistory(vals url.Values, pair string) (map[string]TradeHistory, error) { + result := make(map[string]TradeHistory) + if pair != "" { vals.Add("pair", pair) } - var result map[string]TradeHistory return result, l.SendAuthenticatedHTTPRequest(liquiTradeHistory, vals, &result) } diff --git a/exchanges/liqui/liqui_test.go b/exchanges/liqui/liqui_test.go index dcb28cbd..ebb91d01 100644 --- a/exchanges/liqui/liqui_test.go +++ b/exchanges/liqui/liqui_test.go @@ -1,6 +1,7 @@ package liqui import ( + "log" "net/url" "testing" @@ -34,6 +35,7 @@ func TestSetup(t *testing.T) { } func TestGetFee(t *testing.T) { + t.Parallel() _, err := l.GetFee("usd") if err == nil { t.Error("Test Failed - liqui GetFee() error", err) @@ -41,6 +43,7 @@ func TestGetFee(t *testing.T) { } func TestGetAvailablePairs(t *testing.T) { + t.Parallel() v := l.GetAvailablePairs(false) if len(v) != 0 { t.Error("Test Failed - liqui GetFee() error") @@ -48,6 +51,7 @@ func TestGetAvailablePairs(t *testing.T) { } func TestGetInfo(t *testing.T) { + t.Parallel() _, err := l.GetInfo() if err != nil { t.Error("Test Failed - liqui GetInfo() error", err) @@ -55,6 +59,7 @@ func TestGetInfo(t *testing.T) { } func TestGetTicker(t *testing.T) { + t.Parallel() _, err := l.GetTicker("eth_btc") if err != nil { t.Error("Test Failed - liqui GetTicker() error", err) @@ -62,64 +67,57 @@ func TestGetTicker(t *testing.T) { } func TestGetDepth(t *testing.T) { - _, err := l.GetDepth("eth_btc") + t.Parallel() + v, err := l.GetDepth("eth_btc") if err != nil { t.Error("Test Failed - liqui GetDepth() error", err) } + log.Println(v) } func TestGetTrades(t *testing.T) { + t.Parallel() _, err := l.GetTrades("eth_btc") if err != nil { t.Error("Test Failed - liqui GetTrades() error", err) } } -func TestGetAccountInfo(t *testing.T) { - _, err := l.GetAccountInfo() - if err == nil { - t.Error("Test Failed - liqui GetAccountInfo() error", err) - } -} +func TestAuthRequests(t *testing.T) { + if l.APIKey != "" && l.APISecret != "" { + _, err := l.GetAccountInfo() + if err == nil { + t.Error("Test Failed - liqui GetAccountInfo() error", err) + } -func TestTrade(t *testing.T) { - _, err := l.Trade("", "", 0, 1) - if err == nil { - t.Error("Test Failed - liqui Trade() error", err) - } -} + _, err = l.Trade("", "", 0, 1) + if err == nil { + t.Error("Test Failed - liqui Trade() error", err) + } -func TestGetActiveOrders(t *testing.T) { - _, err := l.GetActiveOrders("eth_btc") - if err == nil { - t.Error("Test Failed - liqui GetActiveOrders() error", err) - } -} + _, err = l.GetActiveOrders("eth_btc") + if err == nil { + t.Error("Test Failed - liqui GetActiveOrders() error", err) + } -func TestGetOrderInfo(t *testing.T) { - _, err := l.GetOrderInfo(1337) - if err == nil { - t.Error("Test Failed - liqui GetOrderInfo() error", err) - } -} + _, err = l.GetOrderInfo(1337) + if err == nil { + t.Error("Test Failed - liqui GetOrderInfo() error", err) + } -func TestCancelOrder(t *testing.T) { - _, err := l.CancelOrder(1337) - if err == nil { - t.Error("Test Failed - liqui CancelOrder() error", err) - } -} + _, err = l.CancelOrder(1337) + if err == nil { + t.Error("Test Failed - liqui CancelOrder() error", err) + } -func TestGetTradeHistory(t *testing.T) { - _, err := l.GetTradeHistory(url.Values{}, "") - if err == nil { - t.Error("Test Failed - liqui GetTradeHistory() error", err) - } -} + _, err = l.GetTradeHistory(url.Values{}, "") + if err == nil { + t.Error("Test Failed - liqui GetTradeHistory() error", err) + } -func TestWithdrawCoins(t *testing.T) { - _, err := l.WithdrawCoins("btc", 1337, "someaddr") - if err == nil { - t.Error("Test Failed - liqui WithdrawCoins() error", err) + _, err = l.WithdrawCoins("btc", 1337, "someaddr") + if err == nil { + t.Error("Test Failed - liqui WithdrawCoins() error", err) + } } } diff --git a/exchanges/liqui/liqui_types.go b/exchanges/liqui/liqui_types.go index 52a8167d..4adbd0c5 100644 --- a/exchanges/liqui/liqui_types.go +++ b/exchanges/liqui/liqui_types.go @@ -4,6 +4,8 @@ package liqui type Info struct { ServerTime int64 `json:"server_time"` Pairs map[string]PairData `json:"pairs"` + Success int `json:"success"` + Error string `json:"error"` } // PairData is a sub-type for Info @@ -18,15 +20,15 @@ type PairData struct { // Ticker contains ticker information type Ticker struct { - High float64 - Low float64 - Avg float64 - Vol float64 - Vol_cur float64 - Last float64 - Buy float64 - Sell float64 - Updated int64 + High float64 + Low float64 + Avg float64 + Vol float64 + VolumeCurrency float64 + Last float64 + Buy float64 + Sell float64 + Updated int64 } // Orderbook references both ask and bid sides @@ -55,6 +57,8 @@ type AccountInfo struct { ServerTime float64 `json:"server_time"` TransactionCount int `json:"transaction_count"` OpenOrders int `json:"open_orders"` + Success int `json:"success"` + Error string `json:"error"` } // ActiveOrders holds active order information @@ -65,6 +69,8 @@ type ActiveOrders struct { Rate float64 `json:"rate"` TimestampCreated float64 `json:"time_created"` Status int `json:"status"` + Success int `json:"success"` + Error string `json:"error"` } // OrderInfo holds specific order information @@ -76,12 +82,16 @@ type OrderInfo struct { Rate float64 `json:"rate"` TimestampCreated float64 `json:"time_created"` Status int `json:"status"` + Success int `json:"success"` + Error string `json:"error"` } // CancelOrder holds cancelled order information type CancelOrder struct { OrderID float64 `json:"order_id"` Funds map[string]float64 `json:"funds"` + Success int `json:"success"` + Error string `json:"error"` } // Trade holds trading information @@ -90,6 +100,8 @@ type Trade struct { Remains float64 `json:"remains"` OrderID float64 `json:"order_id"` Funds map[string]float64 `json:"funds"` + Success int `json:"success"` + Error string `json:"error"` } // TradeHistory contains trade history data @@ -101,6 +113,8 @@ type TradeHistory struct { OrderID float64 `json:"order_id"` MyOrder int `json:"is_your_order"` Timestamp float64 `json:"timestamp"` + Success int `json:"success"` + Error string `json:"error"` } // Response is a generalized return type @@ -115,4 +129,6 @@ type WithdrawCoins struct { TID int64 `json:"tId"` AmountSent float64 `json:"amountSent"` Funds map[string]float64 `json:"funds"` + Success int `json:"success"` + Error string `json:"error"` } diff --git a/exchanges/liqui/liqui_wrapper.go b/exchanges/liqui/liqui_wrapper.go index ef750603..01325504 100644 --- a/exchanges/liqui/liqui_wrapper.go +++ b/exchanges/liqui/liqui_wrapper.go @@ -59,7 +59,7 @@ func (l *Liqui) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Pric tp.Bid = result[currency].Buy tp.Last = result[currency].Last tp.Low = result[currency].Low - tp.Volume = result[currency].Vol_cur + tp.Volume = result[currency].VolumeCurrency ticker.ProcessTicker(l.Name, x, tp, assetType) } From dfaea0125d758676f06f92a8f511ba5ee6fabb70 Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 15:36:27 +1100 Subject: [PATCH 09/12] Fixed linter issues on Okcoin exchange. --- exchanges/okcoin/okcoin.go | 395 +++++++++++++++------------ exchanges/okcoin/okcoin_types.go | 169 +++++++----- exchanges/okcoin/okcoin_websocket.go | 159 ++++++----- exchanges/okcoin/okcoin_wrapper.go | 2 +- 4 files changed, 410 insertions(+), 315 deletions(-) diff --git a/exchanges/okcoin/okcoin.go b/exchanges/okcoin/okcoin.go index a366640b..5e22f5b2 100644 --- a/exchanges/okcoin/okcoin.go +++ b/exchanges/okcoin/okcoin.go @@ -16,61 +16,62 @@ import ( ) const ( - OKCOIN_API_URL = "https://www.okcoin.com/api/v1/" - OKCOIN_API_URL_CHINA = "https://www.okcoin.cn/api/v1/" - OKCOIN_API_VERSION = "1" - OKCOIN_WEBSOCKET_URL = "wss://real.okcoin.com:10440/websocket/okcoinapi" - OKCOIN_WEBSOCKET_URL_CHINA = "wss://real.okcoin.cn:10440/websocket/okcoinapi" - OKCOIN_TICKER = "ticker.do" - OKCOIN_DEPTH = "depth.do" - OKCOIN_TRADES = "trades.do" - OKCOIN_KLINE = "kline.do" - OKCOIN_USERINFO = "userinfo.do" - OKCOIN_TRADE = "trade.do" - OKCOIN_TRADE_HISTORY = "trade_history.do" - OKCOIN_TRADE_BATCH = "batch_trade.do" - OKCOIN_ORDER_CANCEL = "cancel_order.do" - OKCOIN_ORDER_INFO = "order_info.do" - OKCOIN_ORDERS_INFO = "orders_info.do" - OKCOIN_ORDER_HISTORY = "order_history.do" - OKCOIN_WITHDRAW = "withdraw.do" - OKCOIN_WITHDRAW_CANCEL = "cancel_withdraw.do" - OKCOIN_WITHDRAW_INFO = "withdraw_info.do" - OKCOIN_ORDER_FEE = "order_fee.do" - OKCOIN_LEND_DEPTH = "lend_depth.do" - OKCOIN_BORROWS_INFO = "borrows_info.do" - OKCOIN_BORROW_MONEY = "borrow_money.do" - OKCOIN_BORROW_CANCEL = "cancel_borrow.do" - OKCOIN_BORROW_ORDER_INFO = "borrow_order_info.do" - OKCOIN_REPAYMENT = "repayment.do" - OKCOIN_UNREPAYMENTS_INFO = "unrepayments_info.do" - OKCOIN_ACCOUNT_RECORDS = "account_records.do" - OKCOIN_FUTURES_TICKER = "future_ticker.do" - OKCOIN_FUTURES_DEPTH = "future_depth.do" - OKCOIN_FUTURES_TRADES = "future_trades.do" - OKCOIN_FUTURES_INDEX = "future_index.do" - OKCOIN_EXCHANGE_RATE = "exchange_rate.do" - OKCOIN_FUTURES_ESTIMATED_PRICE = "future_estimated_price.do" - OKCOIN_FUTURES_KLINE = "future_kline.do" - OKCOIN_FUTURES_HOLD_AMOUNT = "future_hold_amount.do" - OKCOIN_FUTURES_USERINFO = "future_userinfo.do" - OKCOIN_FUTURES_POSITION = "future_position.do" - OKCOIN_FUTURES_TRADE = "future_trade.do" - OKCOIN_FUTURES_TRADE_HISTORY = "future_trades_history.do" - OKCOIN_FUTURES_TRADE_BATCH = "future_batch_trade.do" - OKCOIN_FUTURES_CANCEL = "future_cancel.do" - OKCOIN_FUTURES_ORDER_INFO = "future_order_info.do" - OKCOIN_FUTURES_ORDERS_INFO = "future_orders_info.do" - OKCOIN_FUTURES_USERINFO_4FIX = "future_userinfo_4fix.do" - OKCOIN_FUTURES_POSITION_4FIX = "future_position_4fix.do" - OKCOIN_FUTURES_EXPLOSIVE = "future_explosive.do" - OKCOIN_FUTURES_DEVOLVE = "future_devolve.do" + okcoinAPIURL = "https://www.okcoin.com/api/v1/" + okcoinAPIURLChina = "https://www.okcoin.cn/api/v1/" + okcoinAPIVersion = "1" + okcoinWebsocketURL = "wss://real.okcoin.com:10440/websocket/okcoinapi" + okcoinWebsocketURLChina = "wss://real.okcoin.cn:10440/websocket/okcoinapi" + okcoinTicker = "ticker.do" + okcoinDepth = "depth.do" + okcoinTrades = "trades.do" + okcoinKline = "kline.do" + okcoinUserInfo = "userinfo.do" + okcoinTrade = "trade.do" + okcoinTradeHistory = "trade_history.do" + okcoinTradeBatch = "batch_trade.do" + okcoinOrderCancel = "cancel_order.do" + okcoinOrderInfo = "order_info.do" + okcoinOrdersInfo = "orders_info.do" + okcoinOrderHistory = "order_history.do" + okcoinWithdraw = "withdraw.do" + okcoinWithdrawCancel = "cancel_withdraw.do" + okcoinWithdrawInfo = "withdraw_info.do" + okcoinOrderFee = "order_fee.do" + okcoinLendDepth = "lend_depth.do" + okcoinBorrowsInfo = "borrows_info.do" + okcoinBorrowMoney = "borrow_money.do" + okcoinBorrowCancel = "cancel_borrow.do" + okcoinBorrowOrderInfo = "borrow_order_info.do" + okcoinRepayment = "repayment.do" + okcoinUnrepaymentsInfo = "unrepayments_info.do" + okcoinAccountRecords = "account_records.do" + okcoinFuturesTicker = "future_ticker.do" + okcoinFuturesDepth = "future_depth.do" + okcoinFuturesTrades = "future_trades.do" + okcoinFuturesIndex = "future_index.do" + okcoinExchangeRate = "exchange_rate.do" + okcoinFuturesEstimatedPrice = "future_estimated_price.do" + okcoinFuturesKline = "future_kline.do" + okcoinFuturesHoldAmount = "future_hold_amount.do" + okcoinFuturesUserInfo = "future_userinfo.do" + okcoinFuturesPosition = "future_position.do" + okcoinFuturesTrade = "future_trade.do" + okcoinFuturesTradeHistory = "future_trades_history.do" + okcoinFuturesTradeBatch = "future_batch_trade.do" + okcoinFuturesCancel = "future_cancel.do" + okcoinFuturesOrderInfo = "future_order_info.do" + okcoinFuturesOrdersInfo = "future_orders_info.do" + okcoinFuturesUserInfo4Fix = "future_userinfo_4fix.do" + okcoinFuturesposition4Fix = "future_position_4fix.do" + okcoinFuturesExplosive = "future_explosive.do" + okcoinFuturesDevolve = "future_devolve.do" ) var ( okcoinDefaultsSet = false ) +// OKCoin is the overarching type across this package type OKCoin struct { exchange.Base RESTErrors map[string]string @@ -79,6 +80,7 @@ type OKCoin struct { WebsocketConn *websocket.Conn } +// setCurrencyPairFormats sets currency pair formatting for this package func (o *OKCoin) setCurrencyPairFormats() { o.RequestCurrencyPairFormat.Delimiter = "_" o.RequestCurrencyPairFormat.Uppercase = false @@ -86,6 +88,7 @@ func (o *OKCoin) setCurrencyPairFormats() { o.ConfigCurrencyPairFormat.Uppercase = true } +// SetDefaults sets current default values for this package func (o *OKCoin) SetDefaults() { o.SetErrorDefaults() o.SetWebsocketErrorDefaults() @@ -98,19 +101,20 @@ func (o *OKCoin) SetDefaults() { if okcoinDefaultsSet { o.AssetTypes = append(o.AssetTypes, o.FuturesValues...) - o.APIUrl = OKCOIN_API_URL + o.APIUrl = okcoinAPIURL o.Name = "OKCOIN International" - o.WebsocketURL = OKCOIN_WEBSOCKET_URL + o.WebsocketURL = okcoinWebsocketURL o.setCurrencyPairFormats() } else { - o.APIUrl = OKCOIN_API_URL_CHINA + o.APIUrl = okcoinAPIURLChina o.Name = "OKCOIN China" - o.WebsocketURL = OKCOIN_WEBSOCKET_URL_CHINA + o.WebsocketURL = okcoinWebsocketURLChina okcoinDefaultsSet = true o.setCurrencyPairFormats() } } +// Setup sets exchange configuration parameters func (o *OKCoin) Setup(exch config.ExchangeConfig) { if !exch.Enabled { o.SetEnabled(false) @@ -135,32 +139,34 @@ func (o *OKCoin) Setup(exch config.ExchangeConfig) { } } +// GetFee returns current fees for the exchange func (o *OKCoin) GetFee(maker bool) float64 { - if o.APIUrl == OKCOIN_API_URL { + if o.APIUrl == okcoinAPIURL { if maker { return o.MakerFee - } else { - return o.TakerFee } + return o.TakerFee } // Chinese exchange does not have any trading fees return 0 } -func (o *OKCoin) GetTicker(symbol string) (OKCoinTicker, error) { - resp := OKCoinTickerResponse{} +// GetTicker returns the current ticker +func (o *OKCoin) GetTicker(symbol string) (Ticker, error) { + resp := TickerResponse{} vals := url.Values{} vals.Set("symbol", symbol) - path := common.EncodeURLValues(o.APIUrl+OKCOIN_TICKER, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinTicker, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp) if err != nil { - return OKCoinTicker{}, err + return Ticker{}, err } return resp.Ticker, nil } -func (o *OKCoin) GetOrderBook(symbol string, size int64, merge bool) (OKCoinOrderbook, error) { - resp := OKCoinOrderbook{} +// GetOrderBook returns the current order book by size +func (o *OKCoin) GetOrderBook(symbol string, size int64, merge bool) (Orderbook, error) { + resp := Orderbook{} vals := url.Values{} vals.Set("symbol", symbol) if size != 0 { @@ -170,7 +176,7 @@ func (o *OKCoin) GetOrderBook(symbol string, size int64, merge bool) (OKCoinOrde vals.Set("merge", "1") } - path := common.EncodeURLValues(o.APIUrl+OKCOIN_DEPTH, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinDepth, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp) if err != nil { return resp, err @@ -178,15 +184,16 @@ func (o *OKCoin) GetOrderBook(symbol string, size int64, merge bool) (OKCoinOrde return resp, nil } -func (o *OKCoin) GetTrades(symbol string, since int64) ([]OKCoinTrades, error) { - result := []OKCoinTrades{} +// GetTrades returns historic trades since a timestamp +func (o *OKCoin) GetTrades(symbol string, since int64) ([]Trades, error) { + result := []Trades{} vals := url.Values{} vals.Set("symbol", symbol) if since != 0 { vals.Set("since", strconv.FormatInt(since, 10)) } - path := common.EncodeURLValues(o.APIUrl+OKCOIN_TRADES, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinTrades, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &result) if err != nil { return nil, err @@ -194,6 +201,7 @@ func (o *OKCoin) GetTrades(symbol string, since int64) ([]OKCoinTrades, error) { return result, nil } +// GetKline returns kline data func (o *OKCoin) GetKline(symbol, klineType string, size, since int64) ([]interface{}, error) { resp := []interface{}{} vals := url.Values{} @@ -208,7 +216,7 @@ func (o *OKCoin) GetKline(symbol, klineType string, size, since int64) ([]interf vals.Set("since", strconv.FormatInt(since, 10)) } - path := common.EncodeURLValues(o.APIUrl+OKCOIN_KLINE, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinKline, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp) if err != nil { return nil, err @@ -217,21 +225,23 @@ func (o *OKCoin) GetKline(symbol, klineType string, size, since int64) ([]interf return resp, nil } -func (o *OKCoin) GetFuturesTicker(symbol, contractType string) (OKCoinFuturesTicker, error) { - resp := OKCoinFuturesTickerResponse{} +// GetFuturesTicker returns a current ticker for the futures market +func (o *OKCoin) GetFuturesTicker(symbol, contractType string) (FuturesTicker, error) { + resp := FuturesTickerResponse{} vals := url.Values{} vals.Set("symbol", symbol) vals.Set("contract_type", contractType) - path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_TICKER, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinFuturesTicker, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp) if err != nil { - return OKCoinFuturesTicker{}, err + return FuturesTicker{}, err } return resp.Ticker, nil } -func (o *OKCoin) GetFuturesDepth(symbol, contractType string, size int64, merge bool) (OKCoinOrderbook, error) { - result := OKCoinOrderbook{} +// GetFuturesDepth returns current depth for the futures market +func (o *OKCoin) GetFuturesDepth(symbol, contractType string, size int64, merge bool) (Orderbook, error) { + result := Orderbook{} vals := url.Values{} vals.Set("symbol", symbol) vals.Set("contract_type", contractType) @@ -243,7 +253,7 @@ func (o *OKCoin) GetFuturesDepth(symbol, contractType string, size int64, merge vals.Set("merge", "1") } - path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_DEPTH, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinFuturesDepth, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &result) if err != nil { return result, err @@ -251,13 +261,14 @@ func (o *OKCoin) GetFuturesDepth(symbol, contractType string, size int64, merge return result, nil } -func (o *OKCoin) GetFuturesTrades(symbol, contractType string) ([]OKCoinFuturesTrades, error) { - result := []OKCoinFuturesTrades{} +// GetFuturesTrades returns historic trades for the futures market +func (o *OKCoin) GetFuturesTrades(symbol, contractType string) ([]FuturesTrades, error) { + result := []FuturesTrades{} vals := url.Values{} vals.Set("symbol", symbol) vals.Set("contract_type", contractType) - path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_TRADES, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinFuturesTrades, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &result) if err != nil { return nil, err @@ -265,6 +276,7 @@ func (o *OKCoin) GetFuturesTrades(symbol, contractType string) ([]OKCoinFuturesT return result, nil } +// GetFuturesIndex returns an index for the futures market func (o *OKCoin) GetFuturesIndex(symbol string) (float64, error) { type Response struct { Index float64 `json:"future_index"` @@ -274,7 +286,7 @@ func (o *OKCoin) GetFuturesIndex(symbol string) (float64, error) { vals := url.Values{} vals.Set("symbol", symbol) - path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_INDEX, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinFuturesIndex, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &result) if err != nil { return 0, err @@ -282,19 +294,22 @@ func (o *OKCoin) GetFuturesIndex(symbol string) (float64, error) { return result.Index, nil } +// GetFuturesExchangeRate returns the exchange rate for the futures market func (o *OKCoin) GetFuturesExchangeRate() (float64, error) { type Response struct { Rate float64 `json:"rate"` } result := Response{} - err := common.SendHTTPGetRequest(o.APIUrl+OKCOIN_EXCHANGE_RATE, true, o.Verbose, &result) + err := common.SendHTTPGetRequest(o.APIUrl+okcoinExchangeRate, true, o.Verbose, &result) if err != nil { return result.Rate, err } return result.Rate, nil } +// GetFuturesEstimatedPrice returns a current estimated futures price for a +// currency func (o *OKCoin) GetFuturesEstimatedPrice(symbol string) (float64, error) { type Response struct { Price float64 `json:"forecast_price"` @@ -303,7 +318,7 @@ func (o *OKCoin) GetFuturesEstimatedPrice(symbol string) (float64, error) { result := Response{} vals := url.Values{} vals.Set("symbol", symbol) - path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_ESTIMATED_PRICE, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinFuturesEstimatedPrice, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &result) if err != nil { return result.Price, err @@ -311,6 +326,8 @@ func (o *OKCoin) GetFuturesEstimatedPrice(symbol string) (float64, error) { return result.Price, nil } +// GetFuturesKline returns kline data for a specific currency on the futures +// market func (o *OKCoin) GetFuturesKline(symbol, klineType, contractType string, size, since int64) ([]interface{}, error) { resp := []interface{}{} vals := url.Values{} @@ -325,7 +342,7 @@ func (o *OKCoin) GetFuturesKline(symbol, klineType, contractType string, size, s vals.Set("since", strconv.FormatInt(since, 10)) } - path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_KLINE, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinFuturesKline, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp) if err != nil { @@ -334,13 +351,14 @@ func (o *OKCoin) GetFuturesKline(symbol, klineType, contractType string, size, s return resp, nil } -func (o *OKCoin) GetFuturesHoldAmount(symbol, contractType string) ([]OKCoinFuturesHoldAmount, error) { - resp := []OKCoinFuturesHoldAmount{} +// GetFuturesHoldAmount returns the hold amount for a futures trade +func (o *OKCoin) GetFuturesHoldAmount(symbol, contractType string) ([]FuturesHoldAmount, error) { + resp := []FuturesHoldAmount{} vals := url.Values{} vals.Set("symbol", symbol) vals.Set("contract_type", contractType) - path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_HOLD_AMOUNT, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinFuturesHoldAmount, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp) if err != nil { @@ -349,9 +367,10 @@ func (o *OKCoin) GetFuturesHoldAmount(symbol, contractType string) ([]OKCoinFutu return resp, nil } -func (o *OKCoin) GetFuturesExplosive(symbol, contractType string, status, currentPage, pageLength int64) ([]OKCoinFuturesExplosive, error) { +// GetFuturesExplosive returns the explosive for a futures contract +func (o *OKCoin) GetFuturesExplosive(symbol, contractType string, status, currentPage, pageLength int64) ([]FuturesExplosive, error) { type Response struct { - Data []OKCoinFuturesExplosive `json:"data"` + Data []FuturesExplosive `json:"data"` } resp := Response{} vals := url.Values{} @@ -361,7 +380,7 @@ func (o *OKCoin) GetFuturesExplosive(symbol, contractType string, status, curren vals.Set("current_page", strconv.FormatInt(currentPage, 10)) vals.Set("page_length", strconv.FormatInt(pageLength, 10)) - path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_EXPLOSIVE, vals) + path := common.EncodeURLValues(o.APIUrl+okcoinFuturesExplosive, vals) err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp) if err != nil { @@ -371,9 +390,10 @@ func (o *OKCoin) GetFuturesExplosive(symbol, contractType string, status, curren return resp.Data, nil } -func (o *OKCoin) GetUserInfo() (OKCoinUserInfo, error) { - result := OKCoinUserInfo{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_USERINFO, url.Values{}, &result) +// GetUserInfo returns user information associated with the calling APIkeys +func (o *OKCoin) GetUserInfo() (UserInfo, error) { + result := UserInfo{} + err := o.SendAuthenticatedHTTPRequest(okcoinUserInfo, url.Values{}, &result) if err != nil { return result, err @@ -382,6 +402,7 @@ func (o *OKCoin) GetUserInfo() (OKCoinUserInfo, error) { return result, nil } +// Trade initiates a new trade func (o *OKCoin) Trade(amount, price float64, symbol, orderType string) (int64, error) { type Response struct { Result bool `json:"result"` @@ -395,26 +416,27 @@ func (o *OKCoin) Trade(amount, price float64, symbol, orderType string) (int64, result := Response{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_TRADE, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinTrade, v, &result) if err != nil { return 0, err } if !result.Result { - return 0, errors.New("Unable to place order.") + return 0, errors.New("unable to place order") } return result.OrderID, nil } -func (o *OKCoin) GetTradeHistory(symbol string, TradeID int64) ([]OKCoinTrades, error) { - result := []OKCoinTrades{} +// GetTradeHistory returns client trade history +func (o *OKCoin) GetTradeHistory(symbol string, TradeID int64) ([]Trades, error) { + result := []Trades{} v := url.Values{} v.Set("symbol", symbol) v.Set("since", strconv.FormatInt(TradeID, 10)) - err := o.SendAuthenticatedHTTPRequest(OKCOIN_TRADE_HISTORY, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinTradeHistory, v, &result) if err != nil { return nil, err @@ -423,14 +445,15 @@ func (o *OKCoin) GetTradeHistory(symbol string, TradeID int64) ([]OKCoinTrades, return result, nil } -func (o *OKCoin) BatchTrade(orderData string, symbol, orderType string) (OKCoinBatchTrade, error) { +// BatchTrade initiates a trade by batch order +func (o *OKCoin) BatchTrade(orderData string, symbol, orderType string) (BatchTrade, error) { v := url.Values{} v.Set("orders_data", orderData) v.Set("symbol", symbol) v.Set("type", orderType) - result := OKCoinBatchTrade{} + result := BatchTrade{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_TRADE_BATCH, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinTradeBatch, v, &result) if err != nil { return result, err @@ -439,60 +462,56 @@ func (o *OKCoin) BatchTrade(orderData string, symbol, orderType string) (OKCoinB return result, nil } -func (o *OKCoin) CancelOrder(orderID []int64, symbol string) (OKCoinCancelOrderResponse, error) { +// CancelOrder cancels a specific order or list of orders by orderID +func (o *OKCoin) CancelOrder(orderID []int64, symbol string) (CancelOrderResponse, error) { v := url.Values{} orders := []string{} - orderStr := "" - result := OKCoinCancelOrderResponse{} + result := CancelOrderResponse{} + + orderStr := strconv.FormatInt(orderID[0], 10) if len(orderID) > 1 { for x := range orderID { orders = append(orders, strconv.FormatInt(orderID[x], 10)) } orderStr = common.JoinStrings(orders, ",") - } else { - orderStr = strconv.FormatInt(orderID[0], 10) } v.Set("order_id", orderStr) v.Set("symbol", symbol) - err := o.SendAuthenticatedHTTPRequest(OKCOIN_ORDER_CANCEL, v, &result) - - if err != nil { - return result, err - } - - return result, nil + return result, o.SendAuthenticatedHTTPRequest(okcoinOrderCancel, v, &result) } -func (o *OKCoin) GetOrderInfo(orderID int64, symbol string) ([]OKCoinOrderInfo, error) { +// GetOrderInfo returns order information by orderID +func (o *OKCoin) GetOrderInfo(orderID int64, symbol string) ([]OrderInfo, error) { type Response struct { - Result bool `json:"result"` - Orders []OKCoinOrderInfo `json:"orders"` + Result bool `json:"result"` + Orders []OrderInfo `json:"orders"` } v := url.Values{} v.Set("symbol", symbol) v.Set("order_id", strconv.FormatInt(orderID, 10)) result := Response{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_ORDER_INFO, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinOrderInfo, v, &result) if err != nil { return nil, err } if result.Result != true { - return nil, errors.New("Unable to retrieve order info.") + return nil, errors.New("unable to retrieve order info") } return result.Orders, nil } -func (o *OKCoin) GetOrderInfoBatch(orderID []int64, symbol string) ([]OKCoinOrderInfo, error) { +// GetOrderInfoBatch returns order info on a batch of orders +func (o *OKCoin) GetOrderInfoBatch(orderID []int64, symbol string) ([]OrderInfo, error) { type Response struct { - Result bool `json:"result"` - Orders []OKCoinOrderInfo `json:"orders"` + Result bool `json:"result"` + Orders []OrderInfo `json:"orders"` } orders := []string{} @@ -505,28 +524,29 @@ func (o *OKCoin) GetOrderInfoBatch(orderID []int64, symbol string) ([]OKCoinOrde v.Set("order_id", common.JoinStrings(orders, ",")) result := Response{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_ORDER_INFO, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinOrderInfo, v, &result) if err != nil { return nil, err } if result.Result != true { - return nil, errors.New("Unable to retrieve order info.") + return nil, errors.New("unable to retrieve order info") } return result.Orders, nil } -func (o *OKCoin) GetOrderHistory(pageLength, currentPage int64, status, symbol string) (OKCoinOrderHistory, error) { +// GetOrderHistory returns a history of orders +func (o *OKCoin) GetOrderHistory(pageLength, currentPage int64, status, symbol string) (OrderHistory, error) { v := url.Values{} v.Set("symbol", symbol) v.Set("status", status) v.Set("current_page", strconv.FormatInt(currentPage, 10)) v.Set("page_length", strconv.FormatInt(pageLength, 10)) - result := OKCoinOrderHistory{} + result := OrderHistory{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_ORDER_HISTORY, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinOrderHistory, v, &result) if err != nil { return result, err @@ -535,6 +555,7 @@ func (o *OKCoin) GetOrderHistory(pageLength, currentPage int64, status, symbol s return result, nil } +// Withdrawal withdraws a cryptocurrency to a supplied address func (o *OKCoin) Withdrawal(symbol string, fee float64, tradePWD, address string, amount float64) (int, error) { v := url.Values{} v.Set("symbol", symbol) @@ -545,67 +566,70 @@ func (o *OKCoin) Withdrawal(symbol string, fee float64, tradePWD, address string v.Set("trade_pwd", tradePWD) v.Set("withdraw_address", address) v.Set("withdraw_amount", strconv.FormatFloat(amount, 'f', -1, 64)) - result := OKCoinWithdrawalResponse{} + result := WithdrawalResponse{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_WITHDRAW, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinWithdraw, v, &result) if err != nil { return 0, err } if !result.Result { - return 0, errors.New("Unable to process withdrawal request.") + return 0, errors.New("unable to process withdrawal request") } return result.WithdrawID, nil } +// CancelWithdrawal cancels a withdrawal func (o *OKCoin) CancelWithdrawal(symbol string, withdrawalID int64) (int, error) { v := url.Values{} v.Set("symbol", symbol) v.Set("withdrawal_id", strconv.FormatInt(withdrawalID, 10)) - result := OKCoinWithdrawalResponse{} + result := WithdrawalResponse{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_WITHDRAW_CANCEL, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinWithdrawCancel, v, &result) if err != nil { return 0, err } if !result.Result { - return 0, errors.New("Unable to process withdrawal cancel request.") + return 0, errors.New("unable to process withdrawal cancel request") } return result.WithdrawID, nil } -func (o *OKCoin) GetWithdrawalInfo(symbol string, withdrawalID int64) ([]OKCoinWithdrawInfo, error) { +// GetWithdrawalInfo returns withdrawal information +func (o *OKCoin) GetWithdrawalInfo(symbol string, withdrawalID int64) ([]WithdrawInfo, error) { type Response struct { Result bool - Withdraw []OKCoinWithdrawInfo `json:"withdraw"` + Withdraw []WithdrawInfo `json:"withdraw"` } v := url.Values{} v.Set("symbol", symbol) v.Set("withdrawal_id", strconv.FormatInt(withdrawalID, 10)) result := Response{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_WITHDRAW_INFO, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinWithdrawInfo, v, &result) if err != nil { return nil, err } if !result.Result { - return nil, errors.New("Unable to process withdrawal cancel request.") + return nil, errors.New("unable to process withdrawal cancel request") } return result.Withdraw, nil } -func (o *OKCoin) GetOrderFeeInfo(symbol string, orderID int64) (OKCoinOrderFeeInfo, error) { +// GetOrderFeeInfo returns order fee information +func (o *OKCoin) GetOrderFeeInfo(symbol string, orderID int64) (OrderFeeInfo, error) { type Response struct { - Data OKCoinOrderFeeInfo `json:"data"` - Result bool `json:"result"` + Data OrderFeeInfo `json:"data"` + Result bool `json:"result"` } v := url.Values{} @@ -613,29 +637,30 @@ func (o *OKCoin) GetOrderFeeInfo(symbol string, orderID int64) (OKCoinOrderFeeIn v.Set("order_id", strconv.FormatInt(orderID, 10)) result := Response{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_ORDER_FEE, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinOrderFee, v, &result) if err != nil { return result.Data, err } if !result.Result { - return result.Data, errors.New("Unable to get order fee info.") + return result.Data, errors.New("unable to get order fee info") } return result.Data, nil } -func (o *OKCoin) GetLendDepth(symbol string) ([]OKCoinLendDepth, error) { +// GetLendDepth returns the depth of lends +func (o *OKCoin) GetLendDepth(symbol string) ([]LendDepth, error) { type Response struct { - LendDepth []OKCoinLendDepth `json:"lend_depth"` + LendDepth []LendDepth `json:"lend_depth"` } v := url.Values{} v.Set("symbol", symbol) result := Response{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_LEND_DEPTH, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinLendDepth, v, &result) if err != nil { return nil, err @@ -644,12 +669,13 @@ func (o *OKCoin) GetLendDepth(symbol string) ([]OKCoinLendDepth, error) { return result.LendDepth, nil } -func (o *OKCoin) GetBorrowInfo(symbol string) (OKCoinBorrowInfo, error) { +// GetBorrowInfo returns borrow information +func (o *OKCoin) GetBorrowInfo(symbol string) (BorrowInfo, error) { v := url.Values{} v.Set("symbol", symbol) - result := OKCoinBorrowInfo{} + result := BorrowInfo{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_BORROWS_INFO, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinBorrowsInfo, v, &result) if err != nil { return result, nil @@ -658,113 +684,119 @@ func (o *OKCoin) GetBorrowInfo(symbol string) (OKCoinBorrowInfo, error) { return result, nil } +// Borrow initiates a borrow request func (o *OKCoin) Borrow(symbol, days string, amount, rate float64) (int, error) { v := url.Values{} v.Set("symbol", symbol) v.Set("days", days) v.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) v.Set("rate", strconv.FormatFloat(rate, 'f', -1, 64)) - result := OKCoinBorrowResponse{} + result := BorrowResponse{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_BORROW_MONEY, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinBorrowMoney, v, &result) if err != nil { return 0, err } if !result.Result { - return 0, errors.New("Unable to borrow.") + return 0, errors.New("unable to borrow") } return result.BorrowID, nil } +// CancelBorrow cancels a borrow request func (o *OKCoin) CancelBorrow(symbol string, borrowID int64) (bool, error) { v := url.Values{} v.Set("symbol", symbol) v.Set("borrow_id", strconv.FormatInt(borrowID, 10)) - result := OKCoinBorrowResponse{} + result := BorrowResponse{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_BORROW_CANCEL, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinBorrowCancel, v, &result) if err != nil { return false, err } if !result.Result { - return false, errors.New("Unable to cancel borrow.") + return false, errors.New("unable to cancel borrow") } return true, nil } -func (o *OKCoin) GetBorrowOrderInfo(borrowID int64) (OKCoinBorrowInfo, error) { +// GetBorrowOrderInfo returns information about a borrow order +func (o *OKCoin) GetBorrowOrderInfo(borrowID int64) (BorrowInfo, error) { type Response struct { - Result bool `json:"result"` - BorrowOrder OKCoinBorrowInfo `json:"borrow_order"` + Result bool `json:"result"` + BorrowOrder BorrowInfo `json:"borrow_order"` } v := url.Values{} v.Set("borrow_id", strconv.FormatInt(borrowID, 10)) result := Response{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_BORROW_ORDER_INFO, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinBorrowOrderInfo, v, &result) if err != nil { return result.BorrowOrder, err } if !result.Result { - return result.BorrowOrder, errors.New("Unable to get borrow info.") + return result.BorrowOrder, errors.New("unable to get borrow info") } return result.BorrowOrder, nil } +// GetRepaymentInfo returns information on a repayment func (o *OKCoin) GetRepaymentInfo(borrowID int64) (bool, error) { v := url.Values{} v.Set("borrow_id", strconv.FormatInt(borrowID, 10)) - result := OKCoinBorrowResponse{} + result := BorrowResponse{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_REPAYMENT, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinRepayment, v, &result) if err != nil { return false, err } if !result.Result { - return false, errors.New("Unable to get repayment info.") + return false, errors.New("unable to get repayment info") } return true, nil } -func (o *OKCoin) GetUnrepaymentsInfo(symbol string, currentPage, pageLength int) ([]OKCoinBorrowOrder, error) { +// GetUnrepaymentsInfo returns information on an unrepayment +func (o *OKCoin) GetUnrepaymentsInfo(symbol string, currentPage, pageLength int) ([]BorrowOrder, error) { type Response struct { - Unrepayments []OKCoinBorrowOrder `json:"unrepayments"` - Result bool `json:"result"` + Unrepayments []BorrowOrder `json:"unrepayments"` + Result bool `json:"result"` } v := url.Values{} v.Set("symbol", symbol) v.Set("current_page", strconv.Itoa(currentPage)) v.Set("page_length", strconv.Itoa(pageLength)) result := Response{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_UNREPAYMENTS_INFO, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinUnrepaymentsInfo, v, &result) if err != nil { return nil, err } if !result.Result { - return nil, errors.New("Unable to get unrepayments info.") + return nil, errors.New("unable to get unrepayments info") } return result.Unrepayments, nil } -func (o *OKCoin) GetAccountRecords(symbol string, recType, currentPage, pageLength int) ([]OKCoinAccountRecords, error) { +// GetAccountRecords returns account records +func (o *OKCoin) GetAccountRecords(symbol string, recType, currentPage, pageLength int) ([]AccountRecords, error) { type Response struct { - Records []OKCoinAccountRecords `json:"records"` - Symbol string `json:"symbol"` + Records []AccountRecords `json:"records"` + Symbol string `json:"symbol"` } v := url.Values{} v.Set("symbol", symbol) @@ -773,7 +805,7 @@ func (o *OKCoin) GetAccountRecords(symbol string, recType, currentPage, pageLeng v.Set("page_length", strconv.Itoa(pageLength)) result := Response{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_ACCOUNT_RECORDS, v, &result) + err := o.SendAuthenticatedHTTPRequest(okcoinAccountRecords, v, &result) if err != nil { return nil, err @@ -782,25 +814,28 @@ func (o *OKCoin) GetAccountRecords(symbol string, recType, currentPage, pageLeng return result.Records, nil } +// GetFuturesUserInfo returns information on a users futures func (o *OKCoin) GetFuturesUserInfo() { - err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_USERINFO, url.Values{}, nil) + err := o.SendAuthenticatedHTTPRequest(okcoinFuturesUserInfo, url.Values{}, nil) if err != nil { log.Println(err) } } +// GetFuturesPosition returns position on a futures contract func (o *OKCoin) GetFuturesPosition(symbol, contractType string) { v := url.Values{} v.Set("symbol", symbol) v.Set("contract_type", contractType) - err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_POSITION, v, nil) + err := o.SendAuthenticatedHTTPRequest(okcoinFuturesPosition, v, nil) if err != nil { log.Println(err) } } +// FuturesTrade initiates a new futures trade func (o *OKCoin) FuturesTrade(amount, price float64, matchPrice, leverage int64, symbol, contractType, orderType string) { v := url.Values{} v.Set("symbol", symbol) @@ -811,13 +846,14 @@ func (o *OKCoin) FuturesTrade(amount, price float64, matchPrice, leverage int64, v.Set("match_price", strconv.FormatInt(matchPrice, 10)) v.Set("lever_rate", strconv.FormatInt(leverage, 10)) - err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_TRADE, v, nil) + err := o.SendAuthenticatedHTTPRequest(okcoinFuturesTrade, v, nil) if err != nil { log.Println(err) } } +// FuturesBatchTrade initiates a batch of futures contract trades func (o *OKCoin) FuturesBatchTrade(orderData, symbol, contractType string, leverage int64, orderType string) { v := url.Values{} //to-do batch trade support for orders_data) v.Set("symbol", symbol) @@ -825,26 +861,28 @@ func (o *OKCoin) FuturesBatchTrade(orderData, symbol, contractType string, lever v.Set("orders_data", orderData) v.Set("lever_rate", strconv.FormatInt(leverage, 10)) - err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_TRADE_BATCH, v, nil) + err := o.SendAuthenticatedHTTPRequest(okcoinFuturesTradeBatch, v, nil) if err != nil { log.Println(err) } } +// CancelFuturesOrder cancels a futures contract order func (o *OKCoin) CancelFuturesOrder(orderID int64, symbol, contractType string) { v := url.Values{} v.Set("symbol", symbol) v.Set("contract_type", contractType) v.Set("order_id", strconv.FormatInt(orderID, 10)) - err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_CANCEL, v, nil) + err := o.SendAuthenticatedHTTPRequest(okcoinFuturesCancel, v, nil) if err != nil { log.Println(err) } } +// GetFuturesOrderInfo returns information on a specfic futures contract order func (o *OKCoin) GetFuturesOrderInfo(orderID, status, currentPage, pageLength int64, symbol, contractType string) { v := url.Values{} v.Set("symbol", symbol) @@ -854,49 +892,53 @@ func (o *OKCoin) GetFuturesOrderInfo(orderID, status, currentPage, pageLength in v.Set("current_page", strconv.FormatInt(currentPage, 10)) v.Set("page_length", strconv.FormatInt(pageLength, 10)) - err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_ORDER_INFO, v, nil) + err := o.SendAuthenticatedHTTPRequest(okcoinFuturesOrderInfo, v, nil) if err != nil { log.Println(err) } } +// GetFutureOrdersInfo returns information on a range of futures orders func (o *OKCoin) GetFutureOrdersInfo(orderID int64, contractType, symbol string) { v := url.Values{} v.Set("order_id", strconv.FormatInt(orderID, 10)) v.Set("contract_type", contractType) v.Set("symbol", symbol) - err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_ORDERS_INFO, v, nil) + err := o.SendAuthenticatedHTTPRequest(okcoinFuturesOrdersInfo, v, nil) if err != nil { log.Println(err) } } +// GetFuturesUserInfo4Fix returns futures user info fix rate func (o *OKCoin) GetFuturesUserInfo4Fix() { v := url.Values{} - err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_USERINFO_4FIX, v, nil) + err := o.SendAuthenticatedHTTPRequest(okcoinFuturesUserInfo4Fix, v, nil) if err != nil { log.Println(err) } } +// GetFuturesUserPosition4Fix returns futures user info on a fixed position func (o *OKCoin) GetFuturesUserPosition4Fix(symbol, contractType string) { v := url.Values{} v.Set("symbol", symbol) v.Set("contract_type", contractType) v.Set("type", strconv.FormatInt(1, 10)) - err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_POSITION_4FIX, v, nil) + err := o.SendAuthenticatedHTTPRequest(okcoinFuturesUserInfo4Fix, v, nil) if err != nil { log.Println(err) } } +// SendAuthenticatedHTTPRequest sends an authenticated HTTP request func (o *OKCoin) SendAuthenticatedHTTPRequest(method string, v url.Values, result interface{}) (err error) { if !o.AuthenticatedAPISupport { return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, o.Name) @@ -935,6 +977,7 @@ func (o *OKCoin) SendAuthenticatedHTTPRequest(method string, v url.Values, resul return nil } +// SetErrorDefaults sets default error map func (o *OKCoin) SetErrorDefaults() { o.RESTErrors = map[string]string{ "10000": "Required field, can not be null", diff --git a/exchanges/okcoin/okcoin_types.go b/exchanges/okcoin/okcoin_types.go index b099e53b..d78e79f4 100644 --- a/exchanges/okcoin/okcoin_types.go +++ b/exchanges/okcoin/okcoin_types.go @@ -1,6 +1,7 @@ package okcoin -type OKCoinTicker struct { +// Ticker holds ticker data +type Ticker struct { Buy float64 `json:",string"` High float64 `json:",string"` Last float64 `json:",string"` @@ -9,32 +10,38 @@ type OKCoinTicker struct { Vol float64 `json:",string"` } -type OKCoinTickerResponse struct { +// TickerResponse is the response type for ticker +type TickerResponse struct { Date string - Ticker OKCoinTicker -} -type OKCoinFuturesTicker struct { - Last float64 - Buy float64 - Sell float64 - High float64 - Low float64 - Vol float64 - Contract_ID int64 - Unit_Amount float64 + Ticker Ticker } -type OKCoinOrderbook struct { +// FuturesTicker holds futures ticker data +type FuturesTicker struct { + Last float64 + Buy float64 + Sell float64 + High float64 + Low float64 + Vol float64 + ContractID int64 + UnitAmount float64 +} + +// Orderbook holds orderbook data +type Orderbook struct { Asks [][]float64 `json:"asks"` Bids [][]float64 `json:"bids"` } -type OKCoinFuturesTickerResponse struct { +// FuturesTickerResponse is a response type +type FuturesTickerResponse struct { Date string - Ticker OKCoinFuturesTicker + Ticker FuturesTicker } -type OKCoinBorrowInfo struct { +// BorrowInfo holds borrowing amount data +type BorrowInfo struct { BorrowBTC float64 `json:"borrow_btc"` BorrowLTC float64 `json:"borrow_ltc"` BorrowCNY float64 `json:"borrow_cny"` @@ -47,7 +54,8 @@ type OKCoinBorrowInfo struct { DailyInterestCNY float64 `json:"today_interest_cny"` } -type OKCoinBorrowOrder struct { +// BorrowOrder holds order data +type BorrowOrder struct { Amount float64 `json:"amount"` BorrowDate int64 `json:"borrow_date"` BorrowID int64 `json:"borrow_id"` @@ -58,7 +66,8 @@ type OKCoinBorrowOrder struct { Symbol string `json:"symbol"` } -type OKCoinRecord struct { +// Record hold record data +type Record struct { Address string `json:"addr"` Account int64 `json:"account,string"` Amount float64 `json:"amount"` @@ -69,12 +78,14 @@ type OKCoinRecord struct { Date float64 `json:"date"` } -type OKCoinAccountRecords struct { - Records []OKCoinRecord `json:"records"` - Symbol string `json:"symbol"` +// AccountRecords holds account record data +type AccountRecords struct { + Records []Record `json:"records"` + Symbol string `json:"symbol"` } -type OKCoinFuturesOrder struct { +// FuturesOrder holds information about a futures order +type FuturesOrder struct { Amount float64 `json:"amount"` ContractName string `json:"contract_name"` DateCreated float64 `json:"create_date"` @@ -90,19 +101,22 @@ type OKCoinFuturesOrder struct { UnitAmount int64 `json:"unit_amount"` } -type OKCoinFuturesHoldAmount struct { +// FuturesHoldAmount contains futures hold amount data +type FuturesHoldAmount struct { Amount float64 `json:"amount"` ContractName string `json:"contract_name"` } -type OKCoinFuturesExplosive struct { +// FuturesExplosive holds inforamtion about explosive futures +type FuturesExplosive struct { Amount float64 `json:"amount,string"` DateCreated string `json:"create_date"` Loss float64 `json:"loss,string"` Type int64 `json:"type"` } -type OKCoinTrades struct { +// Trades holds trade data +type Trades struct { Amount float64 `json:"amount,string"` Date int64 `json:"date"` DateMS int64 `json:"date_ms"` @@ -111,7 +125,8 @@ type OKCoinTrades struct { Type string `json:"type"` } -type OKCoinFuturesTrades struct { +// FuturesTrades holds trade data for the futures market +type FuturesTrades struct { Amount float64 `json:"amount"` Date int64 `json:"date"` DateMS int64 `json:"date_ms"` @@ -120,7 +135,8 @@ type OKCoinFuturesTrades struct { Type string `json:"type"` } -type OKCoinUserInfo struct { +// UserInfo holds user account details +type UserInfo struct { Info struct { Funds struct { Asset struct { @@ -154,7 +170,8 @@ type OKCoinUserInfo struct { Result bool `json:"result"` } -type OKCoinBatchTrade struct { +// BatchTrade holds data on a batch of trades +type BatchTrade struct { OrderInfo []struct { OrderID int64 `json:"order_id"` ErrorCode int64 `json:"error_code"` @@ -162,12 +179,14 @@ type OKCoinBatchTrade struct { Result bool `json:"result"` } -type OKCoinCancelOrderResponse struct { +// CancelOrderResponse is a response type for a cancelled order +type CancelOrderResponse struct { Success string Error string } -type OKCoinOrderInfo struct { +// OrderInfo holds data on an order +type OrderInfo struct { Amount float64 `json:"amount"` AvgPrice float64 `json:"avg_price"` Created int64 `json:"create_date"` @@ -180,20 +199,23 @@ type OKCoinOrderInfo struct { Type string `json:"type"` } -type OKCoinOrderHistory struct { - CurrentPage int `json:"current_page"` - Orders []OKCoinOrderInfo `json:"orders"` - PageLength int `json:"page_length"` - Result bool `json:"result"` - Total int `json:"total"` +// OrderHistory holds information on order history +type OrderHistory struct { + CurrentPage int `json:"current_page"` + Orders []OrderInfo `json:"orders"` + PageLength int `json:"page_length"` + Result bool `json:"result"` + Total int `json:"total"` } -type OKCoinWithdrawalResponse struct { +// WithdrawalResponse is a response type for withdrawal +type WithdrawalResponse struct { WithdrawID int `json:"withdraw_id"` Result bool `json:"result"` } -type OKCoinWithdrawInfo struct { +// WithdrawInfo holds data on a withdraw +type WithdrawInfo struct { Address string `json:"address"` Amount float64 `json:"amount"` Created int64 `json:"created_date"` @@ -202,30 +224,35 @@ type OKCoinWithdrawInfo struct { WithdrawID int64 `json:"withdraw_id"` } -type OKCoinOrderFeeInfo struct { +// OrderFeeInfo holds data on order fees +type OrderFeeInfo struct { Fee float64 `json:"fee,string"` OrderID int64 `json:"order_id"` Type string `json:"type"` } -type OKCoinLendDepth struct { +// LendDepth hold lend depths +type LendDepth struct { Amount float64 `json:"amount"` Days string `json:"days"` Num int64 `json:"num"` Rate float64 `json:"rate,string"` } -type OKCoinBorrowResponse struct { +// BorrowResponse is a response type for borrow +type BorrowResponse struct { Result bool `json:"result"` BorrowID int `json:"borrow_id"` } -type OKCoinWebsocketFutureIndex struct { +// WebsocketFutureIndex holds future index data for websocket +type WebsocketFutureIndex struct { FutureIndex float64 `json:"futureIndex"` Timestamp int64 `json:"timestamp,string"` } -type OKCoinWebsocketTicker struct { +// WebsocketTicker holds ticker data for websocket +type WebsocketTicker struct { Timestamp float64 Vol string Buy float64 @@ -235,7 +262,8 @@ type OKCoinWebsocketTicker struct { Sell float64 } -type OKCoinWebsocketFuturesTicker struct { +// WebsocketFuturesTicker holds futures ticker data for websocket +type WebsocketFuturesTicker struct { Buy float64 `json:"buy"` ContractID string `json:"contractId"` High float64 `json:"high"` @@ -247,13 +275,15 @@ type OKCoinWebsocketFuturesTicker struct { Volume float64 `json:"vol,string"` } -type OKCoinWebsocketOrderbook struct { +// WebsocketOrderbook holds orderbook data for websocket +type WebsocketOrderbook struct { Asks [][]float64 `json:"asks"` Bids [][]float64 `json:"bids"` Timestamp int64 `json:"timestamp,string"` } -type OKCoinWebsocketUserinfo struct { +// WebsocketUserinfo holds user info for websocket +type WebsocketUserinfo struct { Info struct { Funds struct { Asset struct { @@ -277,7 +307,8 @@ type OKCoinWebsocketUserinfo struct { Result bool `json:"result"` } -type OKCoinWebsocketFuturesContract struct { +// WebsocketFuturesContract holds futures contract information for websocket +type WebsocketFuturesContract struct { Available float64 `json:"available"` Balance float64 `json:"balance"` Bond float64 `json:"bond"` @@ -288,23 +319,25 @@ type OKCoinWebsocketFuturesContract struct { Loss float64 `json:"unprofit"` } -type OKCoinWebsocketFuturesUserInfo struct { +// WebsocketFuturesUserInfo holds futures user information for websocket +type WebsocketFuturesUserInfo struct { Info struct { BTC struct { - Balance float64 `json:"balance"` - Contracts []OKCoinWebsocketFuturesContract `json:"contracts"` - Rights float64 `json:"rights"` + Balance float64 `json:"balance"` + Contracts []WebsocketFuturesContract `json:"contracts"` + Rights float64 `json:"rights"` } `json:"btc"` LTC struct { - Balance float64 `json:"balance"` - Contracts []OKCoinWebsocketFuturesContract `json:"contracts"` - Rights float64 `json:"rights"` + Balance float64 `json:"balance"` + Contracts []WebsocketFuturesContract `json:"contracts"` + Rights float64 `json:"rights"` } `json:"ltc"` } `json:"info"` Result bool `json:"result"` } -type OKCoinWebsocketOrder struct { +// WebsocketOrder holds order data for websocket +type WebsocketOrder struct { Amount float64 `json:"amount"` AvgPrice float64 `json:"avg_price"` DateCreated float64 `json:"create_date"` @@ -317,7 +350,8 @@ type OKCoinWebsocketOrder struct { OrderType string `json:"type"` } -type OKCoinWebsocketFuturesOrder struct { +// WebsocketFuturesOrder holds futures order data for websocket +type WebsocketFuturesOrder struct { Amount float64 `json:"amount"` ContractName string `json:"contract_name"` DateCreated float64 `json:"createdDate"` @@ -333,7 +367,8 @@ type OKCoinWebsocketFuturesOrder struct { UnitAmount float64 `json:"unit_amount"` } -type OKCoinWebsocketRealtrades struct { +// WebsocketRealtrades holds real trade data for WebSocket +type WebsocketRealtrades struct { AveragePrice float64 `json:"averagePrice,string"` CompletedTradeAmount float64 `json:"completedTradeAmount,string"` DateCreated float64 `json:"createdDate"` @@ -350,7 +385,8 @@ type OKCoinWebsocketRealtrades struct { UnTrade float64 `json:"unTrade,string"` } -type OKCoinWebsocketFuturesRealtrades struct { +// WebsocketFuturesRealtrades holds futures real trade data for websocket +type WebsocketFuturesRealtrades struct { Amount float64 `json:"amount,string"` ContractID float64 `json:"contract_id,string"` ContractName string `json:"contract_name"` @@ -366,29 +402,34 @@ type OKCoinWebsocketFuturesRealtrades struct { LeverageAmount int `json:"lever_rate,string"` } -type OKCoinWebsocketEvent struct { +// WebsocketEvent holds websocket events +type WebsocketEvent struct { Event string `json:"event"` Channel string `json:"channel"` } -type OKCoinWebsocketResponse struct { +// WebsocketResponse holds websocket responses +type WebsocketResponse struct { Channel string `json:"channel"` Data interface{} `json:"data"` } -type OKCoinWebsocketEventAuth struct { +// WebsocketEventAuth holds websocket authenticated events +type WebsocketEventAuth struct { Event string `json:"event"` Channel string `json:"channel"` Parameters map[string]string `json:"parameters"` } -type OKCoinWebsocketEventAuthRemove struct { +// WebsocketEventAuthRemove holds websocket remove authenticated events +type WebsocketEventAuthRemove struct { Event string `json:"event"` Channel string `json:"channel"` Parameters map[string]string `json:"parameters"` } -type OKCoinWebsocketTradeOrderResponse struct { +// WebsocketTradeOrderResponse holds trade order responses for websocket +type WebsocketTradeOrderResponse struct { OrderID int64 `json:"order_id,string"` Result bool `json:"result,string"` } diff --git a/exchanges/okcoin/okcoin_websocket.go b/exchanges/okcoin/okcoin_websocket.go index 3a81a2f4..0d63b89d 100644 --- a/exchanges/okcoin/okcoin_websocket.go +++ b/exchanges/okcoin/okcoin_websocket.go @@ -15,23 +15,24 @@ import ( ) const ( - OKCOIN_WEBSOCKET_USD_REALTRADES = "ok_usd_realtrades" - OKCOIN_WEBSOCKET_CNY_REALTRADES = "ok_cny_realtrades" - OKCOIN_WEBSOCKET_SPOTUSD_TRADE = "ok_spotusd_trade" - OKCOIN_WEBSOCKET_SPOTCNY_TRADE = "ok_spotcny_trade" - OKCOIN_WEBSOCKET_SPOTUSD_CANCEL_ORDER = "ok_spotusd_cancel_order" - OKCOIN_WEBSOCKET_SPOTCNY_CANCEL_ORDER = "ok_spotcny_cancel_order" - OKCOIN_WEBSOCKET_SPOTUSD_USERINFO = "ok_spotusd_userinfo" - OKCOIN_WEBSOCKET_SPOTCNY_USERINFO = "ok_spotcny_userinfo" - OKCOIN_WEBSOCKET_SPOTUSD_ORDER_INFO = "ok_spotusd_order_info" - OKCOIN_WEBSOCKET_SPOTCNY_ORDER_INFO = "ok_spotcny_order_info" - OKCOIN_WEBSOCKET_FUTURES_TRADE = "ok_futuresusd_trade" - OKCOIN_WEBSOCKET_FUTURES_CANCEL_ORDER = "ok_futuresusd_cancel_order" - OKCOIN_WEBSOCKET_FUTURES_REALTRADES = "ok_usd_future_realtrades" - OKCOIN_WEBSOCKET_FUTURES_USERINFO = "ok_futureusd_userinfo" - OKCOIN_WEBSOCKET_FUTURES_ORDER_INFO = "ok_futureusd_order_info" + okcoinWebsocketUSDRealTrades = "ok_usd_realtrades" + okcoinWebsocketCNYRealTrades = "ok_cny_realtrades" + okcoinWebsocketSpotUSDTrade = "ok_spotusd_trade" + okcoinWebsocketSpotCNYTrade = "ok_spotcny_trade" + okcoinWebsocketSpotUSDCancelOrder = "ok_spotusd_cancel_order" + okcoinWebsocketSpotCNYCancelOrder = "ok_spotcny_cancel_order" + okcoinWebsocketSpotUSDUserInfo = "ok_spotusd_userinfo" + okcoinWebsocketSpotCNYUserInfo = "ok_spotcny_userinfo" + okcoinWebsocketSpotUSDOrderInfo = "ok_spotusd_order_info" + okcoinWebsocketSpotCNYOrderInfo = "ok_spotcny_order_info" + okcoinWebsocketFuturesTrade = "ok_futuresusd_trade" + okcoinWebsocketFuturesCancelOrder = "ok_futuresusd_cancel_order" + okcoinWebsocketFuturesRealTrades = "ok_usd_future_realtrades" + okcoinWebsocketFuturesUserInfo = "ok_futureusd_userinfo" + okcoinWebsocketFuturesOrderInfo = "ok_futureusd_order_info" ) +// PingHandler handles the keep alive func (o *OKCoin) PingHandler(message string) error { err := o.WebsocketConn.WriteControl(websocket.PingMessage, []byte("{'event':'ping'}"), time.Now().Add(time.Second)) @@ -42,8 +43,9 @@ func (o *OKCoin) PingHandler(message string) error { return nil } +// AddChannel adds a new channel on the websocket client func (o *OKCoin) AddChannel(channel string) { - event := OKCoinWebsocketEvent{"addChannel", channel} + event := WebsocketEvent{"addChannel", channel} json, err := common.JSONEncode(event) if err != nil { log.Println(err) @@ -61,8 +63,9 @@ func (o *OKCoin) AddChannel(channel string) { } } +// RemoveChannel removes a channel on the websocket client func (o *OKCoin) RemoveChannel(channel string) { - event := OKCoinWebsocketEvent{"removeChannel", channel} + event := WebsocketEvent{"removeChannel", channel} json, err := common.JSONEncode(event) if err != nil { log.Println(err) @@ -80,23 +83,23 @@ func (o *OKCoin) RemoveChannel(channel string) { } } +// WebsocketSpotTrade handles spot trade request on the websocket client func (o *OKCoin) WebsocketSpotTrade(symbol, orderType string, price, amount float64) { values := make(map[string]string) values["symbol"] = symbol values["type"] = orderType values["price"] = strconv.FormatFloat(price, 'f', -1, 64) values["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) - channel := "" - if o.WebsocketURL == OKCOIN_WEBSOCKET_URL_CHINA { - channel = OKCOIN_WEBSOCKET_SPOTCNY_TRADE - } else { - channel = OKCOIN_WEBSOCKET_SPOTUSD_TRADE + channel := okcoinWebsocketSpotUSDTrade + if o.WebsocketURL == okcoinWebsocketURLChina { + channel = okcoinWebsocketSpotCNYTrade } o.AddChannelAuthenticated(channel, values) } +// WebsocketFuturesTrade handles a futures trade on the websocket client func (o *OKCoin) WebsocketFuturesTrade(symbol, contractType string, price, amount float64, orderType, matchPrice, leverage int) { values := make(map[string]string) values["symbol"] = symbol @@ -106,47 +109,48 @@ func (o *OKCoin) WebsocketFuturesTrade(symbol, contractType string, price, amoun values["type"] = strconv.Itoa(orderType) values["match_price"] = strconv.Itoa(matchPrice) values["lever_rate"] = strconv.Itoa(orderType) - o.AddChannelAuthenticated(OKCOIN_WEBSOCKET_FUTURES_TRADE, values) + o.AddChannelAuthenticated(okcoinWebsocketFuturesTrade, values) } +// WebsocketSpotCancel cancels a spot trade on the websocket client func (o *OKCoin) WebsocketSpotCancel(symbol string, orderID int64) { values := make(map[string]string) values["symbol"] = symbol values["order_id"] = strconv.FormatInt(orderID, 10) - channel := "" - if o.WebsocketURL == OKCOIN_WEBSOCKET_URL_CHINA { - channel = OKCOIN_WEBSOCKET_SPOTCNY_CANCEL_ORDER - } else { - channel = OKCOIN_WEBSOCKET_SPOTUSD_CANCEL_ORDER + channel := okcoinWebsocketSpotUSDCancelOrder + if o.WebsocketURL == okcoinWebsocketURLChina { + channel = okcoinWebsocketSpotCNYCancelOrder } o.AddChannelAuthenticated(channel, values) } +// WebsocketFuturesCancel cancels a futures contract on the websocket client func (o *OKCoin) WebsocketFuturesCancel(symbol, contractType string, orderID int64) { values := make(map[string]string) values["symbol"] = symbol values["order_id"] = strconv.FormatInt(orderID, 10) values["contract_type"] = contractType - o.AddChannelAuthenticated(OKCOIN_WEBSOCKET_FUTURES_CANCEL_ORDER, values) + o.AddChannelAuthenticated(okcoinWebsocketFuturesCancelOrder, values) } +// WebsocketSpotOrderInfo request information on an order on the websocket +// client func (o *OKCoin) WebsocketSpotOrderInfo(symbol string, orderID int64) { values := make(map[string]string) values["symbol"] = symbol values["order_id"] = strconv.FormatInt(orderID, 10) - channel := "" - if o.WebsocketURL == OKCOIN_WEBSOCKET_URL_CHINA { - channel = OKCOIN_WEBSOCKET_SPOTCNY_ORDER_INFO - } else { - channel = OKCOIN_WEBSOCKET_SPOTUSD_ORDER_INFO + channel := okcoinWebsocketSpotUSDOrderInfo + if o.WebsocketURL == okcoinWebsocketURLChina { + channel = okcoinWebsocketSpotCNYOrderInfo } o.AddChannelAuthenticated(channel, values) } +// WebsocketFuturesOrderInfo requests futures order info on the websocket client func (o *OKCoin) WebsocketFuturesOrderInfo(symbol, contractType string, orderID int64, orderStatus, currentPage, pageLength int) { values := make(map[string]string) values["symbol"] = symbol @@ -155,9 +159,10 @@ func (o *OKCoin) WebsocketFuturesOrderInfo(symbol, contractType string, orderID values["status"] = strconv.Itoa(orderStatus) values["current_page"] = strconv.Itoa(currentPage) values["page_length"] = strconv.Itoa(pageLength) - o.AddChannelAuthenticated(OKCOIN_WEBSOCKET_FUTURES_ORDER_INFO, values) + o.AddChannelAuthenticated(okcoinWebsocketFuturesOrderInfo, values) } +// ConvertToURLValues converts values to url.Values func (o *OKCoin) ConvertToURLValues(values map[string]string) url.Values { urlVals := url.Values{} for i, x := range values { @@ -166,15 +171,17 @@ func (o *OKCoin) ConvertToURLValues(values map[string]string) url.Values { return urlVals } +// WebsocketSign signs values on the webcoket client func (o *OKCoin) WebsocketSign(values map[string]string) string { values["api_key"] = o.APIKey urlVals := o.ConvertToURLValues(values) return strings.ToUpper(common.HexEncodeToString(common.GetMD5([]byte(urlVals.Encode() + "&secret_key=" + o.APISecret)))) } +// AddChannelAuthenticated adds an authenticated channel on the websocket client func (o *OKCoin) AddChannelAuthenticated(channel string, values map[string]string) { values["sign"] = o.WebsocketSign(values) - event := OKCoinWebsocketEventAuth{"addChannel", channel, values} + event := WebsocketEventAuth{"addChannel", channel, values} json, err := common.JSONEncode(event) if err != nil { log.Println(err) @@ -192,9 +199,11 @@ func (o *OKCoin) AddChannelAuthenticated(channel string, values map[string]strin } } +// RemoveChannelAuthenticated removes the added authenticated channel on the +// websocket client func (o *OKCoin) RemoveChannelAuthenticated(conn *websocket.Conn, channel string, values map[string]string) { values["sign"] = o.WebsocketSign(values) - event := OKCoinWebsocketEventAuthRemove{"removeChannel", channel, values} + event := WebsocketEventAuthRemove{"removeChannel", channel, values} json, err := common.JSONEncode(event) if err != nil { log.Println(err) @@ -212,16 +221,17 @@ func (o *OKCoin) RemoveChannelAuthenticated(conn *websocket.Conn, channel string } } +// WebsocketClient starts a websocket client func (o *OKCoin) WebsocketClient() { klineValues := []string{"1min", "3min", "5min", "15min", "30min", "1hour", "2hour", "4hour", "6hour", "12hour", "day", "3day", "week"} - currencyChan, userinfoChan := "", "" + var currencyChan, userinfoChan string - if o.WebsocketURL == OKCOIN_WEBSOCKET_URL_CHINA { - currencyChan = OKCOIN_WEBSOCKET_CNY_REALTRADES - userinfoChan = OKCOIN_WEBSOCKET_SPOTCNY_USERINFO + if o.WebsocketURL == okcoinWebsocketURLChina { + currencyChan = okcoinWebsocketCNYRealTrades + userinfoChan = okcoinWebsocketSpotCNYUserInfo } else { - currencyChan = OKCOIN_WEBSOCKET_USD_REALTRADES - userinfoChan = OKCOIN_WEBSOCKET_SPOTUSD_USERINFO + currencyChan = okcoinWebsocketUSDRealTrades + userinfoChan = okcoinWebsocketSpotUSDUserInfo } for o.Enabled && o.Websocket { @@ -241,9 +251,9 @@ func (o *OKCoin) WebsocketClient() { o.WebsocketConn.SetPingHandler(o.PingHandler) if o.AuthenticatedAPISupport { - if o.WebsocketURL == OKCOIN_WEBSOCKET_URL { - o.AddChannelAuthenticated(OKCOIN_WEBSOCKET_FUTURES_REALTRADES, map[string]string{}) - o.AddChannelAuthenticated(OKCOIN_WEBSOCKET_FUTURES_USERINFO, map[string]string{}) + if o.WebsocketURL == okcoinWebsocketURL { + o.AddChannelAuthenticated(okcoinWebsocketFuturesRealTrades, map[string]string{}) + o.AddChannelAuthenticated(okcoinWebsocketFuturesUserInfo, map[string]string{}) } o.AddChannelAuthenticated(currencyChan, map[string]string{}) o.AddChannelAuthenticated(userinfoChan, map[string]string{}) @@ -255,7 +265,7 @@ func (o *OKCoin) WebsocketClient() { if o.AuthenticatedAPISupport { o.WebsocketSpotOrderInfo(currencyUL, -1) } - if o.WebsocketURL == OKCOIN_WEBSOCKET_URL { + if o.WebsocketURL == okcoinWebsocketURL { o.AddChannel(fmt.Sprintf("ok_%s_future_index", currency)) for _, y := range o.FuturesValues { if o.AuthenticatedAPISupport { @@ -336,15 +346,15 @@ func (o *OKCoin) WebsocketClient() { case common.StringContains(channelStr, "ticker") && !common.StringContains(channelStr, "future"): tickerValues := []string{"buy", "high", "last", "low", "sell", "timestamp"} tickerMap := data.(map[string]interface{}) - ticker := OKCoinWebsocketTicker{} + ticker := WebsocketTicker{} ticker.Vol = tickerMap["vol"].(string) for _, z := range tickerValues { result := reflect.TypeOf(tickerMap[z]).String() if result == "string" { - value, err := strconv.ParseFloat(tickerMap[z].(string), 64) - if err != nil { - log.Println(err) + value, errTickVals := strconv.ParseFloat(tickerMap[z].(string), 64) + if errTickVals != nil { + log.Println(errTickVals) continue } @@ -381,7 +391,7 @@ func (o *OKCoin) WebsocketClient() { } } case common.StringContains(channelStr, "ticker") && common.StringContains(channelStr, "future"): - ticker := OKCoinWebsocketFuturesTicker{} + ticker := WebsocketFuturesTicker{} err = common.JSONDecode(dataJSON, &ticker) if err != nil { @@ -389,7 +399,7 @@ func (o *OKCoin) WebsocketClient() { continue } case common.StringContains(channelStr, "depth"): - orderbook := OKCoinWebsocketOrderbook{} + orderbook := WebsocketOrderbook{} err = common.JSONDecode(dataJSON, &orderbook) if err != nil { @@ -411,8 +421,8 @@ func (o *OKCoin) WebsocketClient() { // to-do: convert from string array to trade struct case common.StringContains(channelStr, "kline"): klines := []interface{}{} - err := common.JSONDecode(dataJSON, &klines) + err = common.JSONDecode(dataJSON, &klines) if err != nil { log.Println(err) continue @@ -421,9 +431,9 @@ func (o *OKCoin) WebsocketClient() { if string(dataJSON) == "null" { continue } - realtrades := OKCoinWebsocketRealtrades{} - err := common.JSONDecode(dataJSON, &realtrades) + realtrades := WebsocketRealtrades{} + err = common.JSONDecode(dataJSON, &realtrades) if err != nil { log.Println(err) continue @@ -432,73 +442,73 @@ func (o *OKCoin) WebsocketClient() { if string(dataJSON) == "null" { continue } - realtrades := OKCoinWebsocketFuturesRealtrades{} - err := common.JSONDecode(dataJSON, &realtrades) + realtrades := WebsocketFuturesRealtrades{} + err = common.JSONDecode(dataJSON, &realtrades) if err != nil { log.Println(err) continue } case common.StringContains(channelStr, "spot") && common.StringContains(channelStr, "trade") || common.StringContains(channelStr, "futures") && common.StringContains(channelStr, "trade"): - tradeOrder := OKCoinWebsocketTradeOrderResponse{} - err := common.JSONDecode(dataJSON, &tradeOrder) + tradeOrder := WebsocketTradeOrderResponse{} + err = common.JSONDecode(dataJSON, &tradeOrder) if err != nil { log.Println(err) continue } case common.StringContains(channelStr, "cancel_order"): - cancelOrder := OKCoinWebsocketTradeOrderResponse{} - err := common.JSONDecode(dataJSON, &cancelOrder) + cancelOrder := WebsocketTradeOrderResponse{} + err = common.JSONDecode(dataJSON, &cancelOrder) if err != nil { log.Println(err) continue } case common.StringContains(channelStr, "spot") && common.StringContains(channelStr, "userinfo"): - userinfo := OKCoinWebsocketUserinfo{} - err = common.JSONDecode(dataJSON, &userinfo) + userinfo := WebsocketUserinfo{} + err = common.JSONDecode(dataJSON, &userinfo) if err != nil { log.Println(err) continue } case common.StringContains(channelStr, "futureusd_userinfo"): - userinfo := OKCoinWebsocketFuturesUserInfo{} - err = common.JSONDecode(dataJSON, &userinfo) + userinfo := WebsocketFuturesUserInfo{} + err = common.JSONDecode(dataJSON, &userinfo) if err != nil { log.Println(err) continue } case common.StringContains(channelStr, "spot") && common.StringContains(channelStr, "order_info"): type OrderInfoResponse struct { - Result bool `json:"result"` - Orders []OKCoinWebsocketOrder `json:"orders"` + Result bool `json:"result"` + Orders []WebsocketOrder `json:"orders"` } var orders OrderInfoResponse - err := common.JSONDecode(dataJSON, &orders) + err = common.JSONDecode(dataJSON, &orders) if err != nil { log.Println(err) continue } case common.StringContains(channelStr, "futureusd_order_info"): type OrderInfoResponse struct { - Result bool `json:"result"` - Orders []OKCoinWebsocketFuturesOrder `json:"orders"` + Result bool `json:"result"` + Orders []WebsocketFuturesOrder `json:"orders"` } var orders OrderInfoResponse - err := common.JSONDecode(dataJSON, &orders) + err = common.JSONDecode(dataJSON, &orders) if err != nil { log.Println(err) continue } case common.StringContains(channelStr, "future_index"): - index := OKCoinWebsocketFutureIndex{} - err = common.JSONDecode(dataJSON, &index) + index := WebsocketFutureIndex{} + err = common.JSONDecode(dataJSON, &index) if err != nil { log.Println(err) continue @@ -512,6 +522,7 @@ func (o *OKCoin) WebsocketClient() { } } +// SetWebsocketErrorDefaults sets default errors for websocket func (o *OKCoin) SetWebsocketErrorDefaults() { o.WebsocketErrors = map[string]string{ "10001": "Illegal parameters", diff --git a/exchanges/okcoin/okcoin_wrapper.go b/exchanges/okcoin/okcoin_wrapper.go index 4fff95be..cfe10a33 100644 --- a/exchanges/okcoin/okcoin_wrapper.go +++ b/exchanges/okcoin/okcoin_wrapper.go @@ -34,7 +34,7 @@ func (o *OKCoin) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Pri currency := exchange.FormatExchangeCurrency(o.Name, p).String() var tickerPrice ticker.Price - if assetType != ticker.Spot && o.APIUrl == OKCOIN_API_URL { + if assetType != ticker.Spot && o.APIUrl == okcoinAPIURL { tick, err := o.GetFuturesTicker(currency, assetType) if err != nil { return tickerPrice, err From 85393b59b81792a3925409b9079477a0d2dc48b0 Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 16:31:41 +1100 Subject: [PATCH 10/12] Fixed linter issues for Poloniex exchange. --- exchanges/poloniex/poloniex.go | 237 ++++++++++++----------- exchanges/poloniex/poloniex_types.go | 160 ++++++++++----- exchanges/poloniex/poloniex_websocket.go | 52 ++--- exchanges/poloniex/poloniex_wrapper.go | 72 +++---- 4 files changed, 286 insertions(+), 235 deletions(-) diff --git a/exchanges/poloniex/poloniex.go b/exchanges/poloniex/poloniex.go index 3b1b1466..34171500 100644 --- a/exchanges/poloniex/poloniex.go +++ b/exchanges/poloniex/poloniex.go @@ -99,9 +99,9 @@ func (p *Poloniex) GetFee() float64 { } // GetTicker returns current ticker information -func (p *Poloniex) GetTicker() (map[string]PoloniexTicker, error) { +func (p *Poloniex) GetTicker() (map[string]Ticker, error) { type response struct { - Data map[string]PoloniexTicker + Data map[string]Ticker } resp := response{} @@ -119,17 +119,17 @@ func (p *Poloniex) GetVolume() (interface{}, error) { } // GetOrderbook returns the full orderbook from poloniex -func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbookAll, error) { +func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (OrderbookAll, error) { vals := url.Values{} if depth != 0 { vals.Set("depth", strconv.Itoa(depth)) } - oba := PoloniexOrderbookAll{Data: make(map[string]PoloniexOrderbook)} + oba := OrderbookAll{Data: make(map[string]Orderbook)} if currencyPair != "" { vals.Set("currencyPair", currencyPair) - resp := PoloniexOrderbookResponse{} + resp := OrderbookResponse{} path := fmt.Sprintf("%s/public?command=returnOrderBook&%s", poloniexAPIURL, vals.Encode()) err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp) if err != nil { @@ -139,7 +139,7 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbo log.Println(resp.Error) return oba, fmt.Errorf("Poloniex GetOrderbook() error: %s", resp.Error) } - ob := PoloniexOrderbook{} + ob := Orderbook{} for x := range resp.Asks { data := resp.Asks[x] price, err := strconv.ParseFloat(data[0].(string), 64) @@ -147,7 +147,7 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbo return oba, err } amount := data[1].(float64) - ob.Asks = append(ob.Asks, PoloniexOrderbookItem{Price: price, Amount: amount}) + ob.Asks = append(ob.Asks, OrderbookItem{Price: price, Amount: amount}) } for x := range resp.Bids { @@ -157,19 +157,19 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbo return oba, err } amount := data[1].(float64) - ob.Bids = append(ob.Bids, PoloniexOrderbookItem{Price: price, Amount: amount}) + ob.Bids = append(ob.Bids, OrderbookItem{Price: price, Amount: amount}) } - oba.Data[currencyPair] = PoloniexOrderbook{Bids: ob.Bids, Asks: ob.Asks} + oba.Data[currencyPair] = Orderbook{Bids: ob.Bids, Asks: ob.Asks} } else { vals.Set("currencyPair", "all") - resp := PoloniexOrderbookResponseAll{} + resp := OrderbookResponseAll{} path := fmt.Sprintf("%s/public?command=returnOrderBook&%s", poloniexAPIURL, vals.Encode()) err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp.Data) if err != nil { return oba, err } for currency, orderbook := range resp.Data { - ob := PoloniexOrderbook{} + ob := Orderbook{} for x := range orderbook.Asks { data := orderbook.Asks[x] price, err := strconv.ParseFloat(data[0].(string), 64) @@ -177,7 +177,7 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbo return oba, err } amount := data[1].(float64) - ob.Asks = append(ob.Asks, PoloniexOrderbookItem{Price: price, Amount: amount}) + ob.Asks = append(ob.Asks, OrderbookItem{Price: price, Amount: amount}) } for x := range orderbook.Bids { @@ -187,16 +187,16 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbo return oba, err } amount := data[1].(float64) - ob.Bids = append(ob.Bids, PoloniexOrderbookItem{Price: price, Amount: amount}) + ob.Bids = append(ob.Bids, OrderbookItem{Price: price, Amount: amount}) } - oba.Data[currency] = PoloniexOrderbook{Bids: ob.Bids, Asks: ob.Asks} + oba.Data[currency] = Orderbook{Bids: ob.Bids, Asks: ob.Asks} } } return oba, nil } // GetTradeHistory returns trades history from poloniex -func (p *Poloniex) GetTradeHistory(currencyPair, start, end string) ([]PoloniexTradeHistory, error) { +func (p *Poloniex) GetTradeHistory(currencyPair, start, end string) ([]TradeHistory, error) { vals := url.Values{} vals.Set("currencyPair", currencyPair) @@ -208,14 +208,14 @@ func (p *Poloniex) GetTradeHistory(currencyPair, start, end string) ([]PoloniexT vals.Set("end", end) } - resp := []PoloniexTradeHistory{} + resp := []TradeHistory{} path := fmt.Sprintf("%s/public?command=returnTradeHistory&%s", poloniexAPIURL, vals.Encode()) return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp) } // GetChartData returns chart data for a specific currency pair -func (p *Poloniex) GetChartData(currencyPair, start, end, period string) ([]PoloniexChartData, error) { +func (p *Poloniex) GetChartData(currencyPair, start, end, period string) ([]ChartData, error) { vals := url.Values{} vals.Set("currencyPair", currencyPair) @@ -231,7 +231,7 @@ func (p *Poloniex) GetChartData(currencyPair, start, end, period string) ([]Polo vals.Set("period", period) } - resp := []PoloniexChartData{} + resp := []ChartData{} path := fmt.Sprintf("%s/public?command=returnChartData&%s", poloniexAPIURL, vals.Encode()) err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp) @@ -243,9 +243,9 @@ func (p *Poloniex) GetChartData(currencyPair, start, end, period string) ([]Polo } // GetCurrencies returns information about currencies -func (p *Poloniex) GetCurrencies() (map[string]PoloniexCurrencies, error) { +func (p *Poloniex) GetCurrencies() (map[string]Currencies, error) { type Response struct { - Data map[string]PoloniexCurrencies + Data map[string]Currencies } resp := Response{} path := fmt.Sprintf("%s/public?command=returnCurrencies", poloniexAPIURL) @@ -271,23 +271,24 @@ func (p *Poloniex) GetExchangeCurrencies() ([]string, error) { // GetLoanOrders returns the list of loan offers and demands for a given // currency, specified by the "currency" GET parameter. -func (p *Poloniex) GetLoanOrders(currency string) (PoloniexLoanOrders, error) { - resp := PoloniexLoanOrders{} +func (p *Poloniex) GetLoanOrders(currency string) (LoanOrders, error) { + resp := LoanOrders{} path := fmt.Sprintf("%s/public?command=returnLoanOrders¤cy=%s", poloniexAPIURL, currency) return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp) } -func (p *Poloniex) GetBalances() (PoloniexBalance, error) { +// GetBalances returns balances for your account. +func (p *Poloniex) GetBalances() (Balance, error) { var result interface{} err := p.SendAuthenticatedHTTPRequest("POST", poloniexBalances, url.Values{}, &result) if err != nil { - return PoloniexBalance{}, err + return Balance{}, err } data := result.(map[string]interface{}) - balance := PoloniexBalance{} + balance := Balance{} balance.Currency = make(map[string]float64) for x, y := range data { @@ -297,25 +298,22 @@ func (p *Poloniex) GetBalances() (PoloniexBalance, error) { return balance, nil } -type PoloniexCompleteBalances struct { - Currency map[string]PoloniexCompleteBalance -} - -func (p *Poloniex) GetCompleteBalances() (PoloniexCompleteBalances, error) { +// GetCompleteBalances returns complete balances from your account. +func (p *Poloniex) GetCompleteBalances() (CompleteBalances, error) { var result interface{} err := p.SendAuthenticatedHTTPRequest("POST", poloniexBalancesComplete, url.Values{}, &result) if err != nil { - return PoloniexCompleteBalances{}, err + return CompleteBalances{}, err } data := result.(map[string]interface{}) - balance := PoloniexCompleteBalances{} - balance.Currency = make(map[string]PoloniexCompleteBalance) + balance := CompleteBalances{} + balance.Currency = make(map[string]CompleteBalance) for x, y := range data { dataVals := y.(map[string]interface{}) - balancesData := PoloniexCompleteBalance{} + balancesData := CompleteBalance{} balancesData.Available, _ = strconv.ParseFloat(dataVals["available"].(string), 64) balancesData.OnOrders, _ = strconv.ParseFloat(dataVals["onOrders"].(string), 64) balancesData.BTCValue, _ = strconv.ParseFloat(dataVals["btcValue"].(string), 64) @@ -325,9 +323,10 @@ func (p *Poloniex) GetCompleteBalances() (PoloniexCompleteBalances, error) { return balance, nil } -func (p *Poloniex) GetDepositAddresses() (PoloniexDepositAddresses, error) { +// GetDepositAddresses returns deposit addresses for all enabled cryptos. +func (p *Poloniex) GetDepositAddresses() (DepositAddresses, error) { var result interface{} - addresses := PoloniexDepositAddresses{} + addresses := DepositAddresses{} err := p.SendAuthenticatedHTTPRequest("POST", poloniexDepositAddresses, url.Values{}, &result) if err != nil { @@ -343,6 +342,7 @@ func (p *Poloniex) GetDepositAddresses() (PoloniexDepositAddresses, error) { return addresses, nil } +// GenerateNewAddress generates a new address for a currency func (p *Poloniex) GenerateNewAddress(currency string) (string, error) { type Response struct { Success int @@ -366,8 +366,9 @@ func (p *Poloniex) GenerateNewAddress(currency string) (string, error) { return resp.Response, nil } -func (p *Poloniex) GetDepositsWithdrawals(start, end string) (PoloniexDepositsWithdrawals, error) { - resp := PoloniexDepositsWithdrawals{} +// GetDepositsWithdrawals returns a list of deposits and withdrawals +func (p *Poloniex) GetDepositsWithdrawals(start, end string) (DepositsWithdrawals, error) { + resp := DepositsWithdrawals{} values := url.Values{} if start != "" { @@ -391,32 +392,33 @@ func (p *Poloniex) GetDepositsWithdrawals(start, end string) (PoloniexDepositsWi return resp, nil } +// GetOpenOrders returns current unfilled opened orders func (p *Poloniex) GetOpenOrders(currency string) (interface{}, error) { values := url.Values{} if currency != "" { values.Set("currencyPair", currency) - result := PoloniexOpenOrdersResponse{} + result := OpenOrdersResponse{} + err := p.SendAuthenticatedHTTPRequest("POST", poloniexOrders, values, &result.Data) - - if err != nil { - return result, err - } - - return result, nil - } else { - values.Set("currencyPair", "all") - result := PoloniexOpenOrdersResponseAll{} - err := p.SendAuthenticatedHTTPRequest("POST", poloniexOrders, values, &result.Data) - if err != nil { return result, err } return result, nil } + values.Set("currencyPair", "all") + result := OpenOrdersResponseAll{} + + err := p.SendAuthenticatedHTTPRequest("POST", poloniexOrders, values, &result.Data) + if err != nil { + return result, err + } + + return result, nil } +// GetAuthenticatedTradeHistory returns account trade history func (p *Poloniex) GetAuthenticatedTradeHistory(currency, start, end, limit string) (interface{}, error) { values := url.Values{} @@ -434,29 +436,29 @@ func (p *Poloniex) GetAuthenticatedTradeHistory(currency, start, end, limit stri if currency != "" && currency != "all" { values.Set("currencyPair", currency) - result := PoloniexAuthenticatedTradeHistoryResponse{} + result := AuthenticatedTradeHistoryResponse{} + err := p.SendAuthenticatedHTTPRequest("POST", poloniexTradeHistory, values, &result.Data) - - if err != nil { - return result, err - } - - return result, nil - } else { - values.Set("currencyPair", "all") - result := PoloniexAuthenticatedTradeHistoryAll{} - err := p.SendAuthenticatedHTTPRequest("POST", poloniexTradeHistory, values, &result.Data) - if err != nil { return result, err } return result, nil } + values.Set("currencyPair", "all") + result := AuthenticatedTradeHistoryAll{} + + err := p.SendAuthenticatedHTTPRequest("POST", poloniexTradeHistory, values, &result.Data) + if err != nil { + return result, err + } + + return result, nil } -func (p *Poloniex) PlaceOrder(currency string, rate, amount float64, immediate, fillOrKill, buy bool) (PoloniexOrderResponse, error) { - result := PoloniexOrderResponse{} +// PlaceOrder places a new order on the exchange +func (p *Poloniex) PlaceOrder(currency string, rate, amount float64, immediate, fillOrKill, buy bool) (OrderResponse, error) { + result := OrderResponse{} values := url.Values{} var orderType string @@ -487,8 +489,9 @@ func (p *Poloniex) PlaceOrder(currency string, rate, amount float64, immediate, return result, nil } +// CancelOrder cancels and order by orderID func (p *Poloniex) CancelOrder(orderID int64) (bool, error) { - result := PoloniexGenericResponse{} + result := GenericResponse{} values := url.Values{} values.Set("orderNumber", strconv.FormatInt(orderID, 10)) @@ -505,8 +508,9 @@ func (p *Poloniex) CancelOrder(orderID int64) (bool, error) { return true, nil } -func (p *Poloniex) MoveOrder(orderID int64, rate, amount float64) (PoloniexMoveOrderResponse, error) { - result := PoloniexMoveOrderResponse{} +// MoveOrder moves an order +func (p *Poloniex) MoveOrder(orderID int64, rate, amount float64) (MoveOrderResponse, error) { + result := MoveOrderResponse{} values := url.Values{} values.Set("orderNumber", strconv.FormatInt(orderID, 10)) values.Set("rate", strconv.FormatFloat(rate, 'f', -1, 64)) @@ -528,8 +532,9 @@ func (p *Poloniex) MoveOrder(orderID int64, rate, amount float64) (PoloniexMoveO return result, nil } +// Withdraw withdraws a currency to a specific delegated address func (p *Poloniex) Withdraw(currency, address string, amount float64) (bool, error) { - result := PoloniexWithdraw{} + result := Withdraw{} values := url.Values{} values.Set("currency", currency) @@ -549,17 +554,14 @@ func (p *Poloniex) Withdraw(currency, address string, amount float64) (bool, err return true, nil } -func (p *Poloniex) GetFeeInfo() (PoloniexFee, error) { - result := PoloniexFee{} - err := p.SendAuthenticatedHTTPRequest("POST", poloniexFeeInfo, url.Values{}, &result) +// GetFeeInfo returns fee information +func (p *Poloniex) GetFeeInfo() (Fee, error) { + result := Fee{} - if err != nil { - return result, err - } - - return result, nil + return result, p.SendAuthenticatedHTTPRequest("POST", poloniexFeeInfo, url.Values{}, &result) } +// GetTradableBalances returns tradable balances func (p *Poloniex) GetTradableBalances() (map[string]map[string]float64, error) { type Response struct { Data map[string]map[string]interface{} @@ -584,9 +586,10 @@ func (p *Poloniex) GetTradableBalances() (map[string]map[string]float64, error) return balances, nil } +// TransferBalance transfers balances between your accounts func (p *Poloniex) TransferBalance(currency, from, to string, amount float64) (bool, error) { values := url.Values{} - result := PoloniexGenericResponse{} + result := GenericResponse{} values.Set("currency", currency) values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) @@ -606,8 +609,9 @@ func (p *Poloniex) TransferBalance(currency, from, to string, amount float64) (b return true, nil } -func (p *Poloniex) GetMarginAccountSummary() (PoloniexMargin, error) { - result := PoloniexMargin{} +// GetMarginAccountSummary returns a summary on your margin accounts +func (p *Poloniex) GetMarginAccountSummary() (Margin, error) { + result := Margin{} err := p.SendAuthenticatedHTTPRequest("POST", poloniexMarginAccountSummary, url.Values{}, &result) if err != nil { @@ -617,8 +621,9 @@ func (p *Poloniex) GetMarginAccountSummary() (PoloniexMargin, error) { return result, nil } -func (p *Poloniex) PlaceMarginOrder(currency string, rate, amount, lendingRate float64, buy bool) (PoloniexOrderResponse, error) { - result := PoloniexOrderResponse{} +// PlaceMarginOrder places a margin order +func (p *Poloniex) PlaceMarginOrder(currency string, rate, amount, lendingRate float64, buy bool) (OrderResponse, error) { + result := OrderResponse{} values := url.Values{} var orderType string @@ -645,41 +650,41 @@ func (p *Poloniex) PlaceMarginOrder(currency string, rate, amount, lendingRate f return result, nil } +// GetMarginPosition returns a position on a margin order func (p *Poloniex) GetMarginPosition(currency string) (interface{}, error) { values := url.Values{} if currency != "" && currency != "all" { values.Set("currencyPair", currency) - result := PoloniexMarginPosition{} + result := MarginPosition{} + err := p.SendAuthenticatedHTTPRequest("POST", poloniexMarginPosition, values, &result) - - if err != nil { - return result, err - } - - return result, nil - } else { - values.Set("currencyPair", "all") - - type Response struct { - Data map[string]PoloniexMarginPosition - } - - result := Response{} - err := p.SendAuthenticatedHTTPRequest("POST", poloniexMarginPosition, values, &result.Data) - if err != nil { return result, err } return result, nil } + values.Set("currencyPair", "all") + + type Response struct { + Data map[string]MarginPosition + } + result := Response{} + + err := p.SendAuthenticatedHTTPRequest("POST", poloniexMarginPosition, values, &result.Data) + if err != nil { + return result, err + } + + return result, nil } +// CloseMarginPosition closes a current margin position func (p *Poloniex) CloseMarginPosition(currency string) (bool, error) { values := url.Values{} values.Set("currencyPair", currency) - result := PoloniexGenericResponse{} + result := GenericResponse{} err := p.SendAuthenticatedHTTPRequest("POST", poloniexMarginPositionClose, values, &result) @@ -694,6 +699,7 @@ func (p *Poloniex) CloseMarginPosition(currency string) (bool, error) { return true, nil } +// CreateLoanOffer places a loan offer on the exchange func (p *Poloniex) CreateLoanOffer(currency string, amount, rate float64, duration int, autoRenew bool) (int64, error) { values := url.Values{} values.Set("currency", currency) @@ -729,8 +735,9 @@ func (p *Poloniex) CreateLoanOffer(currency string, amount, rate float64, durati return result.OrderID, nil } +// CancelLoanOffer cancels a loan offer order func (p *Poloniex) CancelLoanOffer(orderNumber int64) (bool, error) { - result := PoloniexGenericResponse{} + result := GenericResponse{} values := url.Values{} values.Set("orderID", strconv.FormatInt(orderNumber, 10)) @@ -747,9 +754,10 @@ func (p *Poloniex) CancelLoanOffer(orderNumber int64) (bool, error) { return true, nil } -func (p *Poloniex) GetOpenLoanOffers() (map[string][]PoloniexLoanOffer, error) { +// GetOpenLoanOffers returns all open loan offers +func (p *Poloniex) GetOpenLoanOffers() (map[string][]LoanOffer, error) { type Response struct { - Data map[string][]PoloniexLoanOffer + Data map[string][]LoanOffer } result := Response{} @@ -760,14 +768,15 @@ func (p *Poloniex) GetOpenLoanOffers() (map[string][]PoloniexLoanOffer, error) { } if result.Data == nil { - return nil, errors.New("There are no open loan offers.") + return nil, errors.New("there are no open loan offers") } return result.Data, nil } -func (p *Poloniex) GetActiveLoans() (PoloniexActiveLoans, error) { - result := PoloniexActiveLoans{} +// GetActiveLoans returns active loans +func (p *Poloniex) GetActiveLoans() (ActiveLoans, error) { + result := ActiveLoans{} err := p.SendAuthenticatedHTTPRequest("POST", poloniexActiveLoans, url.Values{}, &result) if err != nil { @@ -777,7 +786,8 @@ func (p *Poloniex) GetActiveLoans() (PoloniexActiveLoans, error) { return result, nil } -func (p *Poloniex) GetLendingHistory(start, end string) ([]PoloniexLendingHistory, error) { +// GetLendingHistory returns lending history for the account +func (p *Poloniex) GetLendingHistory(start, end string) ([]LendingHistory, error) { vals := url.Values{} if start != "" { @@ -788,7 +798,7 @@ func (p *Poloniex) GetLendingHistory(start, end string) ([]PoloniexLendingHistor vals.Set("end", end) } - resp := []PoloniexLendingHistory{} + resp := []LendingHistory{} err := p.SendAuthenticatedHTTPRequest("POST", poloniexLendingHistory, vals, &resp) if err != nil { @@ -797,10 +807,11 @@ func (p *Poloniex) GetLendingHistory(start, end string) ([]PoloniexLendingHistor return resp, nil } +// ToggleAutoRenew allows for the autorenew of a contract func (p *Poloniex) ToggleAutoRenew(orderNumber int64) (bool, error) { values := url.Values{} values.Set("orderNumber", strconv.FormatInt(orderNumber, 10)) - result := PoloniexGenericResponse{} + result := GenericResponse{} err := p.SendAuthenticatedHTTPRequest("POST", poloniexAutoRenew, values, &result) @@ -815,6 +826,7 @@ func (p *Poloniex) ToggleAutoRenew(orderNumber int64) (bool, error) { return true, nil } +// SendAuthenticatedHTTPRequest sends an authenticated HTTP request func (p *Poloniex) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error { if !p.AuthenticatedAPISupport { return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, p.Name) @@ -835,16 +847,11 @@ func (p *Poloniex) SendAuthenticatedHTTPRequest(method, endpoint string, values headers["Sign"] = common.HexEncodeToString(hmac) path := fmt.Sprintf("%s/%s", poloniexAPIURL, poloniexAPITradingEndpoint) - resp, err := common.SendHTTPRequest(method, path, headers, bytes.NewBufferString(values.Encode())) + resp, err := common.SendHTTPRequest(method, path, headers, bytes.NewBufferString(values.Encode())) if err != nil { return err } - err = common.JSONDecode([]byte(resp), &result) - - if err != nil { - return errors.New("Unable to JSON Unmarshal response.") - } - return nil + return common.JSONDecode([]byte(resp), &result) } diff --git a/exchanges/poloniex/poloniex_types.go b/exchanges/poloniex/poloniex_types.go index 6b747d54..9e0ad507 100644 --- a/exchanges/poloniex/poloniex_types.go +++ b/exchanges/poloniex/poloniex_types.go @@ -1,6 +1,7 @@ package poloniex -type PoloniexTicker struct { +// Ticker holds ticker data +type Ticker struct { Last float64 `json:"last,string"` LowestAsk float64 `json:"lowestAsk,string"` HighestBid float64 `json:"highestBid,string"` @@ -12,32 +13,43 @@ type PoloniexTicker struct { Low24Hr float64 `json:"low24hr,string"` } -type PoloniexOrderbookResponseAll struct { - Data map[string]PoloniexOrderbookResponse +// OrderbookResponseAll holds the full response type orderbook +type OrderbookResponseAll struct { + Data map[string]OrderbookResponse } -type PoloniexOrderbookResponse struct { +// CompleteBalances holds the full balance data +type CompleteBalances struct { + Currency map[string]CompleteBalance +} + +// OrderbookResponse is a sub-type for orderbooks +type OrderbookResponse struct { Asks [][]interface{} `json:"asks"` Bids [][]interface{} `json:"bids"` IsFrozen string `json:"isFrozen"` Error string `json:"error"` } -type PoloniexOrderbookItem struct { +// OrderbookItem holds data on an individual item +type OrderbookItem struct { Price float64 Amount float64 } -type PoloniexOrderbookAll struct { - Data map[string]PoloniexOrderbook +// OrderbookAll contains the full range of orderbooks +type OrderbookAll struct { + Data map[string]Orderbook } -type PoloniexOrderbook struct { - Asks []PoloniexOrderbookItem `json:"asks"` - Bids []PoloniexOrderbookItem `json:"bids"` +// Orderbook is a generic type golding orderbook information +type Orderbook struct { + Asks []OrderbookItem `json:"asks"` + Bids []OrderbookItem `json:"bids"` } -type PoloniexTradeHistory struct { +// TradeHistory holds trade history data +type TradeHistory struct { GlobalTradeID int64 `json:"globalTradeID"` TradeID int64 `json:"tradeID"` Date string `json:"date"` @@ -47,7 +59,8 @@ type PoloniexTradeHistory struct { Total float64 `json:"total,string"` } -type PoloniexChartData struct { +// ChartData holds kline data +type ChartData struct { Date int `json:"date"` High float64 `json:"high"` Low float64 `json:"low"` @@ -59,7 +72,8 @@ type PoloniexChartData struct { Error string `json:"error"` } -type PoloniexCurrencies struct { +// Currencies contains currency information +type Currencies struct { Name string `json:"name"` MaxDailyWithdrawal string `json:"maxDailyWithdrawal"` TxFee float64 `json:"txFee,string"` @@ -70,33 +84,39 @@ type PoloniexCurrencies struct { Frozen int `json:"frozen"` } -type PoloniexLoanOrder struct { +// LoanOrder holds loan order information +type LoanOrder struct { Rate float64 `json:"rate,string"` Amount float64 `json:"amount,string"` RangeMin int `json:"rangeMin"` RangeMax int `json:"rangeMax"` } -type PoloniexLoanOrders struct { - Offers []PoloniexLoanOrder `json:"offers"` - Demands []PoloniexLoanOrder `json:"demands"` +// LoanOrders holds loan order information range +type LoanOrders struct { + Offers []LoanOrder `json:"offers"` + Demands []LoanOrder `json:"demands"` } -type PoloniexBalance struct { +// Balance holds data for a range of currencies +type Balance struct { Currency map[string]float64 } -type PoloniexCompleteBalance struct { +// CompleteBalance contains the complete balance with a btcvalue +type CompleteBalance struct { Available float64 OnOrders float64 BTCValue float64 } -type PoloniexDepositAddresses struct { +// DepositAddresses holds the full address per crypto-currency +type DepositAddresses struct { Addresses map[string]string } -type PoloniexDepositsWithdrawals struct { +// DepositsWithdrawals holds withdrawal information +type DepositsWithdrawals struct { Deposits []struct { Currency string `json:"currency"` Address string `json:"address"` @@ -119,7 +139,8 @@ type PoloniexDepositsWithdrawals struct { } `json:"withdrawals"` } -type PoloniexOrder struct { +// Order hold order information +type Order struct { OrderNumber int64 `json:"orderNumber,string"` Type string `json:"type"` Rate float64 `json:"rate,string"` @@ -129,15 +150,18 @@ type PoloniexOrder struct { Margin float64 `json:"margin"` } -type PoloniexOpenOrdersResponseAll struct { - Data map[string][]PoloniexOrder +// OpenOrdersResponseAll holds all open order responses +type OpenOrdersResponseAll struct { + Data map[string][]Order } -type PoloniexOpenOrdersResponse struct { - Data []PoloniexOrder +// OpenOrdersResponse holds open response orders +type OpenOrdersResponse struct { + Data []Order } -type PoloniexAuthentictedTradeHistory struct { +// AuthentictedTradeHistory holds client trade history information +type AuthentictedTradeHistory struct { GlobalTradeID int64 `json:"globalTradeID"` TradeID int64 `json:"tradeID,string"` Date string `json:"date"` @@ -150,15 +174,18 @@ type PoloniexAuthentictedTradeHistory struct { Category string `json:"category"` } -type PoloniexAuthenticatedTradeHistoryAll struct { - Data map[string][]PoloniexAuthentictedTradeHistory +// AuthenticatedTradeHistoryAll holds the full client trade history +type AuthenticatedTradeHistoryAll struct { + Data map[string][]AuthentictedTradeHistory } -type PoloniexAuthenticatedTradeHistoryResponse struct { - Data []PoloniexAuthentictedTradeHistory +// AuthenticatedTradeHistoryResponse is a response type for trade history +type AuthenticatedTradeHistoryResponse struct { + Data []AuthentictedTradeHistory } -type PoloniexResultingTrades struct { +// ResultingTrades holds resultant trade information +type ResultingTrades struct { Amount float64 `json:"amount,string"` Date string `json:"date"` Rate float64 `json:"rate,string"` @@ -167,36 +194,42 @@ type PoloniexResultingTrades struct { Type string `json:"type"` } -type PoloniexOrderResponse struct { - OrderNumber int64 `json:"orderNumber,string"` - Trades []PoloniexResultingTrades `json:"resultingTrades"` +// OrderResponse is a response type of trades +type OrderResponse struct { + OrderNumber int64 `json:"orderNumber,string"` + Trades []ResultingTrades `json:"resultingTrades"` } -type PoloniexGenericResponse struct { +// GenericResponse is a response type for exchange generic responses +type GenericResponse struct { Success int `json:"success"` Error string `json:"error"` } -type PoloniexMoveOrderResponse struct { - Success int `json:"success"` - Error string `json:"error"` - OrderNumber int64 `json:"orderNumber,string"` - Trades map[string][]PoloniexResultingTrades `json:"resultingTrades"` +// MoveOrderResponse is a response type for move order trades +type MoveOrderResponse struct { + Success int `json:"success"` + Error string `json:"error"` + OrderNumber int64 `json:"orderNumber,string"` + Trades map[string][]ResultingTrades `json:"resultingTrades"` } -type PoloniexWithdraw struct { +// Withdraw holds withdraw information +type Withdraw struct { Response string `json:"response"` Error string `json:"error"` } -type PoloniexFee struct { +// Fee holds fees for specific trades +type Fee struct { MakerFee float64 `json:"makerFee,string"` TakerFee float64 `json:"takerFee,string"` ThirtyDayVolume float64 `json:"thirtyDayVolume,string"` NextTier float64 `json:"nextTier,string"` } -type PoloniexMargin struct { +// Margin holds margin information +type Margin struct { TotalValue float64 `json:"totalValue,string"` ProfitLoss float64 `json:"pl,string"` LendingFees float64 `json:"lendingFees,string"` @@ -205,7 +238,8 @@ type PoloniexMargin struct { CurrentMargin float64 `json:"currentMargin,string"` } -type PoloniexMarginPosition struct { +// MarginPosition holds margin positional information +type MarginPosition struct { Amount float64 `json:"amount,string"` Total float64 `json:"total,string"` BasePrice float64 `json:"basePrice,string"` @@ -215,7 +249,8 @@ type PoloniexMarginPosition struct { Type string `json:"type"` } -type PoloniexLoanOffer struct { +// LoanOffer holds loan offer information +type LoanOffer struct { ID int64 `json:"id"` Rate float64 `json:"rate,string"` Amount float64 `json:"amount,string"` @@ -224,12 +259,14 @@ type PoloniexLoanOffer struct { Date string `json:"date"` } -type PoloniexActiveLoans struct { - Provided []PoloniexLoanOffer `json:"provided"` - Used []PoloniexLoanOffer `json:"used"` +// ActiveLoans shows the full active loans on the exchange +type ActiveLoans struct { + Provided []LoanOffer `json:"provided"` + Used []LoanOffer `json:"used"` } -type PoloniexLendingHistory struct { +// LendingHistory holds the full lending history data +type LendingHistory struct { ID int64 `json:"id"` Currency string `json:"currency"` Rate float64 `json:"rate,string"` @@ -241,3 +278,26 @@ type PoloniexLendingHistory struct { Open string `json:"open"` Close string `json:"close"` } + +// WebsocketTicker holds ticker data for the websocket +type WebsocketTicker struct { + CurrencyPair string + Last float64 + LowestAsk float64 + HighestBid float64 + PercentChange float64 + BaseVolume float64 + QuoteVolume float64 + IsFrozen bool + High float64 + Low float64 +} + +// WebsocketTrollboxMessage holds trollbox messages and information for +// websocket +type WebsocketTrollboxMessage struct { + MessageNumber float64 + Username string + Message string + Reputation float64 +} diff --git a/exchanges/poloniex/poloniex_websocket.go b/exchanges/poloniex/poloniex_websocket.go index 4c2291e7..1db5eeee 100644 --- a/exchanges/poloniex/poloniex_websocket.go +++ b/exchanges/poloniex/poloniex_websocket.go @@ -8,27 +8,15 @@ import ( ) const ( - POLONIEX_WEBSOCKET_ADDRESS = "wss://api.poloniex.com" - POLONIEX_WEBSOCKET_REALM = "realm1" - POLONIEX_WEBSOCKET_TICKER = "ticker" - POLONIEX_WEBSOCKET_TROLLBOX = "trollbox" + poloniexWebsocketAddress = "wss://api.poloniex.com" + poloniexWebsocketRealm = "realm1" + poloniexWebsocketTicker = "ticker" + poloniexWebsocketTrollbox = "trollbox" ) -type PoloniexWebsocketTicker struct { - CurrencyPair string - Last float64 - LowestAsk float64 - HighestBid float64 - PercentChange float64 - BaseVolume float64 - QuoteVolume float64 - IsFrozen bool - High float64 - Low float64 -} - -func PoloniexOnTicker(args []interface{}, kwargs map[string]interface{}) { - ticker := PoloniexWebsocketTicker{} +// OnTicker converts ticker data to a websocketTicker +func OnTicker(args []interface{}, kwargs map[string]interface{}) { + ticker := WebsocketTicker{} ticker.CurrencyPair = args[0].(string) ticker.Last, _ = strconv.ParseFloat(args[1].(string), 64) ticker.LowestAsk, _ = strconv.ParseFloat(args[2].(string), 64) @@ -47,15 +35,9 @@ func PoloniexOnTicker(args []interface{}, kwargs map[string]interface{}) { ticker.Low, _ = strconv.ParseFloat(args[9].(string), 64) } -type PoloniexWebsocketTrollboxMessage struct { - MessageNumber float64 - Username string - Message string - Reputation float64 -} - -func PoloniexOnTrollbox(args []interface{}, kwargs map[string]interface{}) { - message := PoloniexWebsocketTrollboxMessage{} +// OnTrollbox handles trollbox messages +func OnTrollbox(args []interface{}, kwargs map[string]interface{}) { + message := WebsocketTrollboxMessage{} message.MessageNumber, _ = args[1].(float64) message.Username = args[2].(string) message.Message = args[3].(string) @@ -64,7 +46,8 @@ func PoloniexOnTrollbox(args []interface{}, kwargs map[string]interface{}) { } } -func PoloniexOnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) { +// OnDepthOrTrade handles orderbook depth and trade events +func OnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) { for x := range args { data := args[x].(map[string]interface{}) msgData := data["data"].(map[string]interface{}) @@ -133,9 +116,10 @@ func PoloniexOnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) { } } +// WebsocketClient creates a new websocket client func (p *Poloniex) WebsocketClient() { for p.Enabled && p.Websocket { - c, err := turnpike.NewWebsocketClient(turnpike.JSON, POLONIEX_WEBSOCKET_ADDRESS, nil) + c, err := turnpike.NewWebsocketClient(turnpike.JSON, poloniexWebsocketAddress, nil) if err != nil { log.Printf("%s Unable to connect to Websocket. Error: %s\n", p.GetName(), err) continue @@ -145,7 +129,7 @@ func (p *Poloniex) WebsocketClient() { log.Printf("%s Connected to Websocket.\n", p.GetName()) } - _, err = c.JoinRealm(POLONIEX_WEBSOCKET_REALM, nil) + _, err = c.JoinRealm(poloniexWebsocketRealm, nil) if err != nil { log.Printf("%s Unable to join realm. Error: %s\n", p.GetName(), err) continue @@ -157,17 +141,17 @@ func (p *Poloniex) WebsocketClient() { c.ReceiveDone = make(chan bool) - if err := c.Subscribe(POLONIEX_WEBSOCKET_TICKER, PoloniexOnTicker); err != nil { + if err := c.Subscribe(poloniexWebsocketTicker, OnTicker); err != nil { log.Printf("%s Error subscribing to ticker channel: %s\n", p.GetName(), err) } - if err := c.Subscribe(POLONIEX_WEBSOCKET_TROLLBOX, PoloniexOnTrollbox); err != nil { + if err := c.Subscribe(poloniexWebsocketTrollbox, OnTrollbox); err != nil { log.Printf("%s Error subscribing to trollbox channel: %s\n", p.GetName(), err) } for x := range p.EnabledPairs { currency := p.EnabledPairs[x] - if err := c.Subscribe(currency, PoloniexOnDepthOrTrade); err != nil { + if err := c.Subscribe(currency, OnDepthOrTrade); err != nil { log.Printf("%s Error subscribing to %s channel: %s\n", p.GetName(), currency, err) } } diff --git a/exchanges/poloniex/poloniex_wrapper.go b/exchanges/poloniex/poloniex_wrapper.go index b27e2f8f..dc0b6eb1 100644 --- a/exchanges/poloniex/poloniex_wrapper.go +++ b/exchanges/poloniex/poloniex_wrapper.go @@ -12,50 +12,50 @@ import ( ) // Start starts the Poloniex go routine -func (p *Poloniex) Start() { - go p.Run() +func (po *Poloniex) Start() { + go po.Run() } // Run implements the Poloniex wrapper -func (p *Poloniex) Run() { - if p.Verbose { - log.Printf("%s Websocket: %s (url: %s).\n", p.GetName(), common.IsEnabled(p.Websocket), POLONIEX_WEBSOCKET_ADDRESS) - log.Printf("%s polling delay: %ds.\n", p.GetName(), p.RESTPollingDelay) - log.Printf("%s %d currencies enabled: %s.\n", p.GetName(), len(p.EnabledPairs), p.EnabledPairs) +func (po *Poloniex) Run() { + if po.Verbose { + log.Printf("%s Websocket: %s (url: %s).\n", po.GetName(), common.IsEnabled(po.Websocket), poloniexWebsocketAddress) + log.Printf("%s polling delay: %ds.\n", po.GetName(), po.RESTPollingDelay) + log.Printf("%s %d currencies enabled: %s.\n", po.GetName(), len(po.EnabledPairs), po.EnabledPairs) } - if p.Websocket { - go p.WebsocketClient() + if po.Websocket { + go po.WebsocketClient() } - exchangeCurrencies, err := p.GetExchangeCurrencies() + exchangeCurrencies, err := po.GetExchangeCurrencies() if err != nil { - log.Printf("%s Failed to get available symbols.\n", p.GetName()) + log.Printf("%s Failed to get available symbols.\n", po.GetName()) } else { forceUpdate := false - if common.StringDataCompare(p.AvailablePairs, "BTC_USDT") { + if common.StringDataCompare(po.AvailablePairs, "BTC_USDT") { log.Printf("%s contains invalid pair, forcing upgrade of available currencies.\n", - p.GetName()) + po.GetName()) forceUpdate = true } - err = p.UpdateAvailableCurrencies(exchangeCurrencies, forceUpdate) + err = po.UpdateAvailableCurrencies(exchangeCurrencies, forceUpdate) if err != nil { - log.Printf("%s Failed to update available currencies %s.\n", p.GetName(), err) + log.Printf("%s Failed to update available currencies %s.\n", po.GetName(), err) } } } // UpdateTicker updates and returns the ticker for a currency pair -func (p *Poloniex) UpdateTicker(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) { +func (po *Poloniex) UpdateTicker(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) { var tickerPrice ticker.Price - tick, err := p.GetTicker() + tick, err := po.GetTicker() if err != nil { return tickerPrice, err } - for _, x := range p.GetEnabledCurrencies() { + for _, x := range po.GetEnabledCurrencies() { var tp ticker.Price - curr := exchange.FormatExchangeCurrency(p.GetName(), x).String() + curr := exchange.FormatExchangeCurrency(po.GetName(), x).String() tp.Pair = x tp.Ask = tick[curr].LowestAsk tp.Bid = tick[curr].HighestBid @@ -63,39 +63,39 @@ func (p *Poloniex) UpdateTicker(currencyPair pair.CurrencyPair, assetType string tp.Last = tick[curr].Last tp.Low = tick[curr].Low24Hr tp.Volume = tick[curr].BaseVolume - ticker.ProcessTicker(p.GetName(), x, tp, assetType) + ticker.ProcessTicker(po.GetName(), x, tp, assetType) } - return ticker.GetTicker(p.Name, currencyPair, assetType) + return ticker.GetTicker(po.Name, currencyPair, assetType) } // GetTickerPrice returns the ticker for a currency pair -func (p *Poloniex) GetTickerPrice(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) { - tickerNew, err := ticker.GetTicker(p.GetName(), currencyPair, assetType) +func (po *Poloniex) GetTickerPrice(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) { + tickerNew, err := ticker.GetTicker(po.GetName(), currencyPair, assetType) if err != nil { - return p.UpdateTicker(currencyPair, assetType) + return po.UpdateTicker(currencyPair, assetType) } return tickerNew, nil } // GetOrderbookEx returns orderbook base on the currency pair -func (p *Poloniex) GetOrderbookEx(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) { - ob, err := orderbook.GetOrderbook(p.GetName(), currencyPair, assetType) +func (po *Poloniex) GetOrderbookEx(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) { + ob, err := orderbook.GetOrderbook(po.GetName(), currencyPair, assetType) if err != nil { - return p.UpdateOrderbook(currencyPair, assetType) + return po.UpdateOrderbook(currencyPair, assetType) } return ob, nil } // UpdateOrderbook updates and returns the orderbook for a currency pair -func (p *Poloniex) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) { +func (po *Poloniex) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) { var orderBook orderbook.Base - orderbookNew, err := p.GetOrderbook("", 1000) + orderbookNew, err := po.GetOrderbook("", 1000) if err != nil { return orderBook, err } - for _, x := range p.GetEnabledCurrencies() { - currency := exchange.FormatExchangeCurrency(p.Name, x).String() + for _, x := range po.GetEnabledCurrencies() { + currency := exchange.FormatExchangeCurrency(po.Name, x).String() data, ok := orderbookNew.Data[currency] if !ok { continue @@ -115,17 +115,17 @@ func (p *Poloniex) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType str obItems = append(obItems, orderbook.Item{Amount: obData.Amount, Price: obData.Price}) } orderBook.Asks = obItems - orderbook.ProcessOrderbook(p.Name, x, orderBook, assetType) + orderbook.ProcessOrderbook(po.Name, x, orderBook, assetType) } - return orderbook.GetOrderbook(p.Name, currencyPair, assetType) + return orderbook.GetOrderbook(po.Name, currencyPair, assetType) } // GetExchangeAccountInfo retrieves balances for all enabled currencies for the // Poloniex exchange -func (p *Poloniex) GetExchangeAccountInfo() (exchange.AccountInfo, error) { +func (po *Poloniex) GetExchangeAccountInfo() (exchange.AccountInfo, error) { var response exchange.AccountInfo - response.ExchangeName = p.GetName() - accountBalance, err := p.GetBalances() + response.ExchangeName = po.GetName() + accountBalance, err := po.GetBalances() if err != nil { return response, err } From bd24b002817cd61c1b6d7d34779743fbaa2bc41e Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 16:34:43 +1100 Subject: [PATCH 11/12] Fixed linter issues for Yobit exchange. --- exchanges/yobit/yobit.go | 4 ++-- exchanges/yobit/yobit_types.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/exchanges/yobit/yobit.go b/exchanges/yobit/yobit.go index 9eb5d559..5669605a 100644 --- a/exchanges/yobit/yobit.go +++ b/exchanges/yobit/yobit.go @@ -207,7 +207,7 @@ func (y *Yobit) GetTradeHistory(TIDFrom, Count, TIDEnd int64, order, since, end, return result, y.SendAuthenticatedHTTPRequest(privateTradeHistory, req, &result) } -// CoinDepositAddress returns the deposit address for a specific currency +// GetDepositAddress returns the deposit address for a specific currency func (y *Yobit) GetDepositAddress(coin string) (DepositAddress, error) { req := url.Values{} req.Add("coinName", coin) @@ -217,7 +217,7 @@ func (y *Yobit) GetDepositAddress(coin string) (DepositAddress, error) { return result, y.SendAuthenticatedHTTPRequest(privateGetDepositAddress, req, &result) } -// CoinDepositAddress returns the deposit address for a specific currency +// WithdrawCoinsToAddress initiates a withdrawal to a specified address func (y *Yobit) WithdrawCoinsToAddress(coin string, amount float64, address string) (WithdrawCoinsToAddress, error) { req := url.Values{} req.Add("coinName", coin) diff --git a/exchanges/yobit/yobit_types.go b/exchanges/yobit/yobit_types.go index 7f8b3c20..11b24c9c 100644 --- a/exchanges/yobit/yobit_types.go +++ b/exchanges/yobit/yobit_types.go @@ -111,14 +111,14 @@ type TradeHistory struct { Timestamp float64 `json:"timestamp"` } -// CoinDepositAddress stores a curency deposit address +// DepositAddress stores a curency deposit address type DepositAddress struct { Address string `json:"address"` ProcessedAmount float64 `json:"processed_amount"` ServerTime int64 `json:"server_time"` } -// WithdrawCoins stores information for a withdrawcoins request +// WithdrawCoinsToAddress stores information for a withdrawcoins request type WithdrawCoinsToAddress struct { ServerTime int64 `json:"server_time"` } From 0488ebc2dcecaa8158dc35334eddf59d71c2ddeb Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 26 Feb 2018 16:52:36 +1100 Subject: [PATCH 12/12] Modified tests for Binance and GDAX exchange. --- exchanges/binance/binance_test.go | 5 +---- exchanges/gdax/gdax_test.go | 8 -------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/exchanges/binance/binance_test.go b/exchanges/binance/binance_test.go index d73f74c2..a02a02c7 100644 --- a/exchanges/binance/binance_test.go +++ b/exchanges/binance/binance_test.go @@ -1,7 +1,6 @@ package binance import ( - "log" "testing" "github.com/thrasher-/gocryptotrader/config" @@ -60,12 +59,10 @@ func TestGetRecentTrades(t *testing.T) { func TestGetHistoricalTrades(t *testing.T) { t.Parallel() - b.Verbose = true - v, err := b.GetHistoricalTrades("BTCUSDT", 5, 1337) + _, err := b.GetHistoricalTrades("BTCUSDT", 5, 1337) if err == nil { t.Error("Test Failed - Binance GetHistoricalTrades() error", err) } - log.Println(v) } func TestGetAggregatedTrades(t *testing.T) { diff --git a/exchanges/gdax/gdax_test.go b/exchanges/gdax/gdax_test.go index 266458f4..abb4b780 100644 --- a/exchanges/gdax/gdax_test.go +++ b/exchanges/gdax/gdax_test.go @@ -31,7 +31,6 @@ func TestSetup(t *testing.T) { } func TestGetFee(t *testing.T) { - t.Parallel() if g.GetFee(false) == 0 { t.Error("Test failed - GetFee() error") } @@ -41,7 +40,6 @@ func TestGetFee(t *testing.T) { } func TestGetProducts(t *testing.T) { - t.Parallel() _, err := g.GetProducts() if err != nil { t.Error("Test failed - GetProducts() error") @@ -49,7 +47,6 @@ func TestGetProducts(t *testing.T) { } func TestGetTicker(t *testing.T) { - t.Parallel() _, err := g.GetTicker("BTC-USD") if err != nil { t.Error("Test failed - GetTicker() error", err) @@ -57,7 +54,6 @@ func TestGetTicker(t *testing.T) { } func TestGetTrades(t *testing.T) { - t.Parallel() _, err := g.GetTrades("BTC-USD") if err != nil { t.Error("Test failed - GetTrades() error", err) @@ -65,7 +61,6 @@ func TestGetTrades(t *testing.T) { } func TestGetHistoricRates(t *testing.T) { - t.Parallel() _, err := g.GetHistoricRates("BTC-USD", 0, 0, 0) if err != nil { t.Error("Test failed - GetHistoricRates() error", err) @@ -73,7 +68,6 @@ func TestGetHistoricRates(t *testing.T) { } func TestGetStats(t *testing.T) { - t.Parallel() _, err := g.GetStats("BTC-USD") if err != nil { t.Error("Test failed - GetStats() error", err) @@ -81,7 +75,6 @@ func TestGetStats(t *testing.T) { } func TestGetCurrencies(t *testing.T) { - t.Parallel() _, err := g.GetCurrencies() if err != nil { t.Error("Test failed - GetCurrencies() error", err) @@ -89,7 +82,6 @@ func TestGetCurrencies(t *testing.T) { } func TestGetServerTime(t *testing.T) { - t.Parallel() _, err := g.GetServerTime() if err != nil { t.Error("Test failed - GetServerTime() error", err)