From 4eaa9d0ec96f8e2b039b35f9c718bfe3ff8c82e6 Mon Sep 17 00:00:00 2001 From: Adrian Gallagher Date: Mon, 21 Aug 2017 13:10:57 +1000 Subject: [PATCH] Prevent authenticated calls when authenticated API support is disabled --- exchanges/alphapoint/alphapoint.go | 4 ++++ exchanges/anx/anx.go | 4 ++++ exchanges/bitfinex/bitfinex.go | 4 ++-- exchanges/bitstamp/bitstamp.go | 4 ++++ exchanges/bittrex/bittrex.go | 4 ++++ exchanges/btcc/btcc.go | 4 ++++ exchanges/btce/btce.go | 4 ++++ exchanges/btcmarkets/btcmarkets.go | 4 ++++ exchanges/coinut/coinut.go | 5 +++++ exchanges/exchange.go | 10 ++++++++++ exchanges/gdax/gdax.go | 5 ++++- exchanges/gemini/gemini.go | 4 ++++ exchanges/huobi/huobi.go | 4 ++++ exchanges/itbit/itbit.go | 5 +++++ exchanges/kraken/kraken.go | 4 ++++ exchanges/lakebtc/lakebtc.go | 4 ++++ exchanges/liqui/liqui.go | 4 ++++ exchanges/localbitcoins/localbitcoins.go | 4 ++++ exchanges/okcoin/okcoin.go | 5 +++++ exchanges/poloniex/poloniex.go | 3 +++ wallet_routes.go | 10 +++++++--- 21 files changed, 93 insertions(+), 6 deletions(-) diff --git a/exchanges/alphapoint/alphapoint.go b/exchanges/alphapoint/alphapoint.go index b434e2ff..e24f4a33 100644 --- a/exchanges/alphapoint/alphapoint.go +++ b/exchanges/alphapoint/alphapoint.go @@ -409,6 +409,10 @@ func (a *Alphapoint) SendRequest(method, path string, data map[string]interface{ } func (a *Alphapoint) SendAuthenticatedHTTPRequest(method, path string, data map[string]interface{}, result interface{}) error { + if !a.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, a.Name) + } + headers := make(map[string]string) headers["Content-Type"] = "application/json" data["apiKey"] = a.APIKey diff --git a/exchanges/anx/anx.go b/exchanges/anx/anx.go index d7135b98..cedd294d 100644 --- a/exchanges/anx/anx.go +++ b/exchanges/anx/anx.go @@ -286,6 +286,10 @@ func (a *ANX) GetDepositAddress(currency, name string, new bool) (string, error) } func (a *ANX) SendAuthenticatedHTTPRequest(path string, params map[string]interface{}, result interface{}) error { + if !a.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, a.Name) + } + request := make(map[string]interface{}) request["nonce"] = strconv.FormatInt(time.Now().UnixNano(), 10)[0:13] path = fmt.Sprintf("api/%s/%s", ANX_API_VERSION, path) diff --git a/exchanges/bitfinex/bitfinex.go b/exchanges/bitfinex/bitfinex.go index f897fa3f..6f28fff6 100644 --- a/exchanges/bitfinex/bitfinex.go +++ b/exchanges/bitfinex/bitfinex.go @@ -589,8 +589,8 @@ func (b *Bitfinex) Withdrawal(withdrawType, wallet, address string, amount float } func (b *Bitfinex) SendAuthenticatedHTTPRequest(method, path string, params map[string]interface{}, result interface{}) error { - if len(b.APIKey) == 0 { - return errors.New("SendAuthenticatedHTTPRequest: Invalid API key") + if !b.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name) } request := make(map[string]interface{}) diff --git a/exchanges/bitstamp/bitstamp.go b/exchanges/bitstamp/bitstamp.go index ac44f745..7202be8b 100644 --- a/exchanges/bitstamp/bitstamp.go +++ b/exchanges/bitstamp/bitstamp.go @@ -468,6 +468,10 @@ func (b *Bitstamp) GetXRPDepositAddress() (BitstampXRPDepositResponse, error) { } func (b *Bitstamp) SendAuthenticatedHTTPRequest(path string, v2 bool, values url.Values, result interface{}) (err error) { + if !b.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name) + } + nonce := strconv.FormatInt(time.Now().UnixNano(), 10) if values == nil { diff --git a/exchanges/bittrex/bittrex.go b/exchanges/bittrex/bittrex.go index 011fa499..2743ce5f 100644 --- a/exchanges/bittrex/bittrex.go +++ b/exchanges/bittrex/bittrex.go @@ -314,6 +314,10 @@ func (b *Bittrex) GetDepositHistory(currency string) ([]WithdrawalHistory, error // SendAuthenticatedHTTPRequest sends an authenticated http request to a desired // path func (b *Bittrex) SendAuthenticatedHTTPRequest(path string, values url.Values, result interface{}) (err error) { + if !b.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name) + } + nonce := strconv.FormatInt(time.Now().UnixNano(), 10) values.Set("apikey", b.APIKey) values.Set("apisecret", b.APISecret) diff --git a/exchanges/btcc/btcc.go b/exchanges/btcc/btcc.go index dfae06c7..111791b9 100644 --- a/exchanges/btcc/btcc.go +++ b/exchanges/btcc/btcc.go @@ -516,6 +516,10 @@ func (b *BTCC) CancelStopOrder(orderID int64, market string) { } func (b *BTCC) SendAuthenticatedHTTPRequest(method string, params []interface{}) (err error) { + if !b.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name) + } + nonce := strconv.FormatInt(time.Now().UnixNano(), 10)[0:16] encoded := fmt.Sprintf("tonce=%s&accesskey=%s&requestmethod=post&id=%d&method=%s¶ms=", nonce, b.APIKey, 1, method) diff --git a/exchanges/btce/btce.go b/exchanges/btce/btce.go index d3b399ae..0dd0d822 100644 --- a/exchanges/btce/btce.go +++ b/exchanges/btce/btce.go @@ -293,6 +293,10 @@ func (b *BTCE) RedeemCoupon(coupon string) (BTCERedeemCoupon, error) { } func (b *BTCE) SendAuthenticatedHTTPRequest(method string, values url.Values, result interface{}) (err error) { + if !b.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name) + } + nonce := strconv.FormatInt(time.Now().Unix(), 10) values.Set("nonce", nonce) values.Set("method", method) diff --git a/exchanges/btcmarkets/btcmarkets.go b/exchanges/btcmarkets/btcmarkets.go index f68d8eac..ab193b9c 100644 --- a/exchanges/btcmarkets/btcmarkets.go +++ b/exchanges/btcmarkets/btcmarkets.go @@ -281,6 +281,10 @@ func (b *BTCMarkets) GetAccountBalance() ([]BTCMarketsAccountBalance, error) { } func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path string, data interface{}, result interface{}) (err error) { + if !b.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name) + } + nonce := strconv.FormatInt(time.Now().UnixNano(), 10)[0:13] request := "" payload := []byte("") diff --git a/exchanges/coinut/coinut.go b/exchanges/coinut/coinut.go index 1b6fc0f8..c26dde45 100644 --- a/exchanges/coinut/coinut.go +++ b/exchanges/coinut/coinut.go @@ -3,6 +3,7 @@ package coinut import ( "bytes" "errors" + "fmt" "log" "time" @@ -271,6 +272,10 @@ func (c *COINUT) GetOpenPosition(instrumentID int) ([]CoinutOpenPosition, error) //to-do: user position update via websocket func (c *COINUT) SendAuthenticatedHTTPRequest(apiRequest string, params map[string]interface{}, result interface{}) (err error) { + if !c.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, c.Name) + } + timestamp := time.Now().Unix() payload := []byte("") diff --git a/exchanges/exchange.go b/exchanges/exchange.go index 997d95b6..5644cc15 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -13,6 +13,9 @@ import ( const ( warningBase64DecryptSecretKeyFailed = "WARNING -- Exchange %s unable to base64 decode secret key.. Disabling Authenticated API support." + + // WarningAuthenticatedRequestWithoutCredentialsSet error message for authenticated request without credentails set + WarningAuthenticatedRequestWithoutCredentialsSet = "WARNING -- Exchange %s authenticated HTTP request called but not supported due to unset/default API keys." // ErrExchangeNotFound is a constant for an error message ErrExchangeNotFound = "Exchange not found in dataset." ) @@ -60,6 +63,13 @@ type IBotExchange interface { GetOrderbookEx(currency pair.CurrencyPair) (orderbook.OrderbookBase, error) GetEnabledCurrencies() []string GetExchangeAccountInfo() (AccountInfo, error) + GetAuthenticatedAPISupport() bool +} + +// GetAuthenticatedAPISupport returns whether the exchange supports +// authenticated API requests +func (e *Base) GetAuthenticatedAPISupport() bool { + return e.AuthenticatedAPISupport } // GetName is a method that returns the name of the exchange base diff --git a/exchanges/gdax/gdax.go b/exchanges/gdax/gdax.go index ba294a82..e3a0a9fa 100644 --- a/exchanges/gdax/gdax.go +++ b/exchanges/gdax/gdax.go @@ -370,8 +370,11 @@ func (g *GDAX) GetReportStatus(reportID string) (GDAXReportResponse, error) { } func (g *GDAX) SendAuthenticatedHTTPRequest(method, path string, params map[string]interface{}, result interface{}) (err error) { - timestamp := strconv.FormatInt(time.Now().Unix(), 10) + if !g.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, g.Name) + } + timestamp := strconv.FormatInt(time.Now().Unix(), 10) payload := []byte("") if params != nil { diff --git a/exchanges/gemini/gemini.go b/exchanges/gemini/gemini.go index ef2f40a4..3edf8ac4 100644 --- a/exchanges/gemini/gemini.go +++ b/exchanges/gemini/gemini.go @@ -245,6 +245,10 @@ func (g *Gemini) PostHeartbeat() (bool, error) { } func (g *Gemini) SendAuthenticatedHTTPRequest(method, path string, params map[string]interface{}, result interface{}) (err error) { + if !g.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, g.Name) + } + request := make(map[string]interface{}) request["request"] = fmt.Sprintf("/v%s/%s", GEMINI_API_VERSION, path) request["nonce"] = time.Now().UnixNano() diff --git a/exchanges/huobi/huobi.go b/exchanges/huobi/huobi.go index 672bb8d3..f3edab71 100644 --- a/exchanges/huobi/huobi.go +++ b/exchanges/huobi/huobi.go @@ -177,6 +177,10 @@ func (h *HUOBI) GetOrderIDByTradeID(coinType, orderID int) { } func (h *HUOBI) SendAuthenticatedRequest(method string, v url.Values) error { + if !h.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, h.Name) + } + v.Set("access_key", h.APIKey) v.Set("created", strconv.FormatInt(time.Now().Unix(), 10)) v.Set("method", method) diff --git a/exchanges/itbit/itbit.go b/exchanges/itbit/itbit.go index e051e099..0a6c486f 100644 --- a/exchanges/itbit/itbit.go +++ b/exchanges/itbit/itbit.go @@ -3,6 +3,7 @@ package itbit import ( "bytes" "errors" + "fmt" "log" "net/url" "strconv" @@ -226,6 +227,10 @@ func (i *ItBit) WalletTransfer(walletID, sourceWallet, destWallet string, amount } func (i *ItBit) SendAuthenticatedHTTPRequest(method string, path string, params map[string]interface{}) (err error) { + if !i.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, i.Name) + } + timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)[0:13] nonce, err := strconv.Atoi(timestamp) diff --git a/exchanges/kraken/kraken.go b/exchanges/kraken/kraken.go index bee3ea15..54712f4f 100644 --- a/exchanges/kraken/kraken.go +++ b/exchanges/kraken/kraken.go @@ -509,6 +509,10 @@ func (k *Kraken) CancelOrder(orderID int64) { } func (k *Kraken) SendAuthenticatedHTTPRequest(method string, values url.Values) (interface{}, error) { + if !k.AuthenticatedAPISupport { + return nil, fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, k.Name) + } + path := fmt.Sprintf("/%s/private/%s", KRAKEN_API_VERSION, method) values.Set("nonce", strconv.FormatInt(time.Now().UnixNano(), 10)) secret, err := common.Base64Decode(k.APISecret) diff --git a/exchanges/lakebtc/lakebtc.go b/exchanges/lakebtc/lakebtc.go index ecb50f29..794761a4 100644 --- a/exchanges/lakebtc/lakebtc.go +++ b/exchanges/lakebtc/lakebtc.go @@ -272,6 +272,10 @@ func (l *LakeBTC) CreateWithdraw(amount float64, accountID int64) (LakeBTCWithdr } func (l *LakeBTC) SendAuthenticatedHTTPRequest(method, params string, result interface{}) (err error) { + if !l.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, l.Name) + } + nonce := strconv.FormatInt(time.Now().UnixNano(), 10) req := fmt.Sprintf("tonce=%s&accesskey=%s&requestmethod=post&id=1&method=%s¶ms=%s", nonce, l.APIKey, method, params) hmac := common.GetHMAC(common.HashSHA1, []byte(req), []byte(l.APISecret)) diff --git a/exchanges/liqui/liqui.go b/exchanges/liqui/liqui.go index 0a58328a..3ddac444 100644 --- a/exchanges/liqui/liqui.go +++ b/exchanges/liqui/liqui.go @@ -249,6 +249,10 @@ func (l *Liqui) WithdrawCoins(coin string, amount float64, address string) (Liqu } func (l *Liqui) SendAuthenticatedHTTPRequest(method string, values url.Values, result interface{}) (err error) { + if !l.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, l.Name) + } + nonce := strconv.FormatInt(time.Now().Unix(), 10) values.Set("nonce", nonce) values.Set("method", method) diff --git a/exchanges/localbitcoins/localbitcoins.go b/exchanges/localbitcoins/localbitcoins.go index 43ad14a7..adb2bd40 100644 --- a/exchanges/localbitcoins/localbitcoins.go +++ b/exchanges/localbitcoins/localbitcoins.go @@ -267,6 +267,10 @@ func (l *LocalBitcoins) GetWalletAddress() (string, error) { } func (l *LocalBitcoins) SendAuthenticatedHTTPRequest(method, path string, values url.Values, result interface{}) (err error) { + if !l.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, l.Name) + } + nonce := strconv.FormatInt(time.Now().UnixNano(), 10) payload := "" path = "/api/" + path diff --git a/exchanges/okcoin/okcoin.go b/exchanges/okcoin/okcoin.go index 6a7d531f..0f2994aa 100644 --- a/exchanges/okcoin/okcoin.go +++ b/exchanges/okcoin/okcoin.go @@ -2,6 +2,7 @@ package okcoin import ( "errors" + "fmt" "log" "net/url" "strconv" @@ -877,6 +878,10 @@ func (o *OKCoin) GetFuturesUserPosition4Fix(symbol, contractType string) { } func (o *OKCoin) SendAuthenticatedHTTPRequest(method string, v url.Values, result interface{}) (err error) { + if !o.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, o.Name) + } + v.Set("api_key", o.APIKey) hasher := common.GetMD5([]byte(v.Encode() + "&secret_key=" + o.APISecret)) v.Set("sign", strings.ToUpper(common.HexEncodeToString(hasher))) diff --git a/exchanges/poloniex/poloniex.go b/exchanges/poloniex/poloniex.go index a895d787..bf318fab 100644 --- a/exchanges/poloniex/poloniex.go +++ b/exchanges/poloniex/poloniex.go @@ -745,6 +745,9 @@ func (p *Poloniex) ToggleAutoRenew(orderNumber int64) (bool, error) { } func (p *Poloniex) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error { + if !p.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, p.Name) + } headers := make(map[string]string) headers["Content-Type"] = "application/x-www-form-urlencoded" headers["Key"] = p.APIKey diff --git a/wallet_routes.go b/wallet_routes.go index 61dec117..3ed2e1f3 100644 --- a/wallet_routes.go +++ b/wallet_routes.go @@ -54,11 +54,15 @@ func GetAllEnabledExchangeAccountInfo() AllEnabledExchangeAccounts { var response AllEnabledExchangeAccounts for _, individualBot := range bot.exchanges { if individualBot != nil && individualBot.IsEnabled() { + if !individualBot.GetAuthenticatedAPISupport() { + log.Printf("GetAllEnabledExchangeAccountInfo: Skippping %s due to disabled authenticated API support.", individualBot.GetName()) + continue + } individualExchange, err := individualBot.GetExchangeAccountInfo() if err != nil { - log.Println( - "Error encountered retrieving exchange account for '" + individualExchange.ExchangeName + "'", - ) + log.Printf("Error encountered retrieving exchange account info for %s. Error %s", + individualBot.GetName(), err) + continue } response.Data = append(response.Data, individualExchange) }