Fixed linter issues for Kraken package and added testing.

This commit is contained in:
Ryan O'Hara-Reid
2017-11-22 15:50:50 +11:00
parent ce908ee939
commit baae729014
4 changed files with 552 additions and 244 deletions

View File

@@ -1,7 +1,6 @@
package kraken
import (
"errors"
"fmt"
"log"
"net/url"
@@ -16,37 +15,39 @@ import (
)
const (
KRAKEN_API_URL = "https://api.kraken.com"
KRAKEN_API_VERSION = "0"
KRAKEN_SERVER_TIME = "Time"
KRAKEN_ASSETS = "Assets"
KRAKEN_ASSET_PAIRS = "AssetPairs"
KRAKEN_TICKER = "Ticker"
KRAKEN_OHLC = "OHLC"
KRAKEN_DEPTH = "Depth"
KRAKEN_TRADES = "Trades"
KRAKEN_SPREAD = "Spread"
KRAKEN_BALANCE = "Balance"
KRAKEN_TRADE_BALANCE = "TradeBalance"
KRAKEN_OPEN_ORDERS = "OpenOrders"
KRAKEN_CLOSED_ORDERS = "ClosedOrders"
KRAKEN_QUERY_ORDERS = "QueryOrders"
KRAKEN_TRADES_HISTORY = "TradesHistory"
KRAKEN_QUERY_TRADES = "QueryTrades"
KRAKEN_OPEN_POSITIONS = "OpenPositions"
KRAKEN_LEDGERS = "Ledgers"
KRAKEN_QUERY_LEDGERS = "QueryLedgers"
KRAKEN_TRADE_VOLUME = "TradeVolume"
KRAKEN_ORDER_CANCEL = "CancelOrder"
KRAKEN_ORDER_PLACE = "AddOrder"
krakenAPIURL = "https://api.kraken.com"
krakenAPIVersion = "0"
krakenServerTime = "Time"
krakenAssets = "Assets"
krakenAssetPairs = "AssetPairs"
krakenTicker = "Ticker"
krakenOHLC = "OHLC"
krakenDepth = "Depth"
krakenTrades = "Trades"
krakenSpread = "Spread"
krakenBalance = "Balance"
krakenTradeBalance = "TradeBalance"
krakenOpenOrders = "OpenOrders"
krakenClosedOrders = "ClosedOrders"
krakenQueryOrders = "QueryOrders"
krakenTradeHistory = "TradesHistory"
krakenQueryTrades = "QueryTrades"
krakenOpenPositions = "OpenPositions"
krakenLedgers = "Ledgers"
krakenQueryLedgers = "QueryLedgers"
krakenTradeVolume = "TradeVolume"
krakenOrderCancel = "CancelOrder"
krakenOrderPlace = "AddOrder"
)
// Kraken is the overarching type across the alphapoint package
type Kraken struct {
exchange.Base
CryptoFee, FiatFee float64
Ticker map[string]KrakenTicker
Ticker map[string]Ticker
}
// SetDefaults sets current default settings
func (k *Kraken) SetDefaults() {
k.Name = "Kraken"
k.Enabled = false
@@ -55,7 +56,7 @@ func (k *Kraken) SetDefaults() {
k.Verbose = false
k.Websocket = false
k.RESTPollingDelay = 10
k.Ticker = make(map[string]KrakenTicker)
k.Ticker = make(map[string]Ticker)
k.RequestCurrencyPairFormat.Delimiter = ""
k.RequestCurrencyPairFormat.Uppercase = true
k.RequestCurrencyPairFormat.Separator = ","
@@ -64,6 +65,7 @@ func (k *Kraken) SetDefaults() {
k.AssetTypes = []string{ticker.Spot}
}
// Setup sets current exchange configuration
func (k *Kraken) Setup(exch config.ExchangeConfig) {
if !exch.Enabled {
k.SetEnabled(false)
@@ -88,81 +90,75 @@ func (k *Kraken) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns current fee for either crypto or fiat
func (k *Kraken) GetFee(cryptoTrade bool) float64 {
if cryptoTrade {
return k.CryptoFee
} else {
return k.FiatFee
}
return k.FiatFee
}
func (k *Kraken) GetServerTime() error {
var result interface{}
path := fmt.Sprintf("%s/%s/public/%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_SERVER_TIME)
// GetServerTime returns current server time
func (k *Kraken) GetServerTime(unixTime bool) (interface{}, error) {
var result GeneralResponse
path := fmt.Sprintf("%s/%s/public/%s", krakenAPIURL, krakenAPIVersion, krakenServerTime)
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
return err
return nil, fmt.Errorf("getServerTime() error %s", err)
}
log.Println(result)
return nil
}
func (k *Kraken) GetAssets() error {
var result interface{}
path := fmt.Sprintf("%s/%s/public/%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_ASSETS)
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
return err
if unixTime {
return result.Result["unixtime"], nil
}
log.Println(result)
return nil
return result.Result["rfc1123"], nil
}
func (k *Kraken) GetAssetPairs() (map[string]KrakenAssetPairs, error) {
// GetAssets returns a full asset list
func (k *Kraken) GetAssets() (interface{}, error) {
var result GeneralResponse
path := fmt.Sprintf("%s/%s/public/%s", krakenAPIURL, krakenAPIVersion, krakenAssets)
return result.Result, common.SendHTTPGetRequest(path, true, k.Verbose, &result)
}
// GetAssetPairs returns a full asset pair list
func (k *Kraken) GetAssetPairs() (map[string]AssetPairs, error) {
type Response struct {
Result map[string]KrakenAssetPairs `json:"result"`
Error []interface{} `json:"error"`
Result map[string]AssetPairs `json:"result"`
Error []interface{} `json:"error"`
}
response := Response{}
path := fmt.Sprintf("%s/%s/public/%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_ASSET_PAIRS)
err := common.SendHTTPGetRequest(path, true, k.Verbose, &response)
path := fmt.Sprintf("%s/%s/public/%s", krakenAPIURL, krakenAPIVersion, krakenAssetPairs)
if err != nil {
return nil, err
}
return response.Result, nil
return response.Result, common.SendHTTPGetRequest(path, true, k.Verbose, &response)
}
func (k *Kraken) GetTicker(symbol string) error {
// GetTicker returns ticker information from kraken
func (k *Kraken) GetTicker(symbol string) (Ticker, error) {
ticker := Ticker{}
values := url.Values{}
values.Set("pair", symbol)
type Response struct {
Error []interface{} `json:"error"`
Data map[string]KrakenTickerResponse `json:"result"`
Error []interface{} `json:"error"`
Data map[string]TickerResponse `json:"result"`
}
resp := Response{}
path := fmt.Sprintf("%s/%s/public/%s?%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_TICKER, values.Encode())
err := common.SendHTTPGetRequest(path, true, k.Verbose, &resp)
path := fmt.Sprintf("%s/%s/public/%s?%s", krakenAPIURL, krakenAPIVersion, krakenTicker, values.Encode())
err := common.SendHTTPGetRequest(path, true, k.Verbose, &resp)
if err != nil {
return err
return ticker, err
}
if len(resp.Error) > 0 {
return errors.New(fmt.Sprintf("Kraken error: %s", resp.Error))
return ticker, fmt.Errorf("Kraken error: %s", resp.Error)
}
for x, y := range resp.Data {
x = x[1:4] + x[5:]
ticker := KrakenTicker{}
for _, y := range resp.Data {
ticker.Ask, _ = strconv.ParseFloat(y.Ask[0], 64)
ticker.Bid, _ = strconv.ParseFloat(y.Bid[0], 64)
ticker.Last, _ = strconv.ParseFloat(y.Last[0], 64)
@@ -172,25 +168,59 @@ func (k *Kraken) GetTicker(symbol string) error {
ticker.Low, _ = strconv.ParseFloat(y.Low[1], 64)
ticker.High, _ = strconv.ParseFloat(y.High[1], 64)
ticker.Open, _ = strconv.ParseFloat(y.Open, 64)
k.Ticker[x] = ticker
}
return nil
return ticker, nil
}
func (k *Kraken) GetOHLC(symbol string) error {
// GetOHLC returns an array of open high low close values of a currency pair
func (k *Kraken) GetOHLC(symbol string) ([]OpenHighLowClose, error) {
values := url.Values{}
values.Set("pair", symbol)
var result interface{}
path := fmt.Sprintf("%s/%s/public/%s?%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_OHLC, values.Encode())
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
return err
type Response struct {
Error []interface{} `json:"error"`
Data map[string]interface{} `json:"result"`
}
log.Println(result)
return nil
var OHLC []OpenHighLowClose
var result Response
path := fmt.Sprintf("%s/%s/public/%s?%s", krakenAPIURL, krakenAPIVersion, krakenOHLC, values.Encode())
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
return OHLC, err
}
if len(result.Error) != 0 {
return OHLC, fmt.Errorf("GetOHLC error: %s", result.Error)
}
for _, y := range result.Data[symbol].([]interface{}) {
o := OpenHighLowClose{}
for i, x := range y.([]interface{}) {
switch i {
case 0:
o.Time = x.(float64)
case 1:
o.Open, _ = strconv.ParseFloat(x.(string), 64)
case 2:
o.High, _ = strconv.ParseFloat(x.(string), 64)
case 3:
o.Low, _ = strconv.ParseFloat(x.(string), 64)
case 4:
o.Close, _ = strconv.ParseFloat(x.(string), 64)
case 5:
o.Vwap, _ = strconv.ParseFloat(x.(string), 64)
case 6:
o.Volume, _ = strconv.ParseFloat(x.(string), 64)
case 7:
o.Count = x.(float64)
}
}
OHLC = append(OHLC, o)
}
return OHLC, nil
}
// GetDepth returns the orderbook for a particular currency
@@ -199,12 +229,13 @@ func (k *Kraken) GetDepth(symbol string) (Orderbook, error) {
values.Set("pair", symbol)
var result interface{}
var ob Orderbook
path := fmt.Sprintf("%s/%s/public/%s?%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_DEPTH, values.Encode())
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
var orderBook Orderbook
path := fmt.Sprintf("%s/%s/public/%s?%s", krakenAPIURL, krakenAPIVersion, krakenDepth, values.Encode())
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
return ob, err
return orderBook, err
}
data := result.(map[string]interface{})
@@ -223,14 +254,14 @@ func (k *Kraken) GetDepth(symbol string) (Orderbook, error) {
for x := range data {
entry := data[x].([]interface{})
price, err := strconv.ParseFloat(entry[0].(string), 64)
if err != nil {
return nil, err
price, priceErr := strconv.ParseFloat(entry[0].(string), 64)
if priceErr != nil {
return nil, priceErr
}
amount, err := strconv.ParseFloat(entry[1].(string), 64)
if err != nil {
return nil, err
amount, amountErr := strconv.ParseFloat(entry[1].(string), 64)
if amountErr != nil {
return nil, amountErr
}
result = append(result, OrderbookBase{Price: price, Amount: amount})
@@ -238,82 +269,116 @@ func (k *Kraken) GetDepth(symbol string) (Orderbook, error) {
return result, nil
}
ob.Bids, err = processOrderbook(bidsData)
orderBook.Bids, err = processOrderbook(bidsData)
if err != nil {
return ob, err
return orderBook, err
}
ob.Asks, err = processOrderbook(asksData)
orderBook.Asks, err = processOrderbook(asksData)
if err != nil {
return ob, err
return orderBook, err
}
return ob, nil
return orderBook, nil
}
func (k *Kraken) GetTrades(symbol string) error {
// GetTrades returns current trades on Kraken
func (k *Kraken) GetTrades(symbol string) ([]RecentTrades, error) {
values := url.Values{}
values.Set("pair", symbol)
var recentTrades []RecentTrades
var result interface{}
path := fmt.Sprintf("%s/%s/public/%s?%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_TRADES, values.Encode())
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
path := fmt.Sprintf("%s/%s/public/%s?%s", krakenAPIURL, krakenAPIVersion, krakenTrades, values.Encode())
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
return err
return recentTrades, err
}
log.Println(result)
return nil
data := result.(map[string]interface{})
tradeInfo := data["result"].(map[string]interface{})
for _, x := range tradeInfo[symbol].([]interface{}) {
r := RecentTrades{}
for i, y := range x.([]interface{}) {
switch i {
case 0:
r.Price, _ = strconv.ParseFloat(y.(string), 64)
case 1:
r.Volume, _ = strconv.ParseFloat(y.(string), 64)
case 2:
r.Time = y.(float64)
case 3:
r.BuyOrSell = y.(string)
case 4:
r.MarketOrLimit = y.(string)
case 5:
r.Miscellaneous = y.(string)
}
}
recentTrades = append(recentTrades, r)
}
return recentTrades, nil
}
func (k *Kraken) GetSpread(symbol string) {
// GetSpread returns the full spread on Kraken
func (k *Kraken) GetSpread(symbol string) ([]Spread, error) {
values := url.Values{}
values.Set("pair", symbol)
var result interface{}
path := fmt.Sprintf("%s/%s/public/%s?%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_SPREAD, values.Encode())
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
var peanutButter []Spread
var response interface{}
path := fmt.Sprintf("%s/%s/public/%s?%s", krakenAPIURL, krakenAPIVersion, krakenSpread, values.Encode())
err := common.SendHTTPGetRequest(path, true, k.Verbose, &response)
if err != nil {
log.Println(err)
return
}
}
func (k *Kraken) GetBalance() {
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_BALANCE, url.Values{})
if err != nil {
log.Println(err)
return
return peanutButter, err
}
log.Println(result)
data := response.(map[string]interface{})
result := data["result"].(map[string]interface{})
for _, x := range result[symbol].([]interface{}) {
s := Spread{}
for i, y := range x.([]interface{}) {
switch i {
case 0:
s.Time = y.(float64)
case 1:
s.Bid, _ = strconv.ParseFloat(y.(string), 64)
case 2:
s.Ask, _ = strconv.ParseFloat(y.(string), 64)
}
}
peanutButter = append(peanutButter, s)
}
return peanutButter, nil
}
func (k *Kraken) GetTradeBalance(symbol, asset string) {
// GetBalance returns your balance associated with your keys
func (k *Kraken) GetBalance() (interface{}, error) {
return k.SendAuthenticatedHTTPRequest(krakenBalance, url.Values{})
}
// GetTradeBalance returns full information about your trades on Kraken
func (k *Kraken) GetTradeBalance(symbol, asset string) (interface{}, error) {
values := url.Values{}
if len(symbol) > 0 {
values.Set("aclass", symbol)
}
if len(asset) > 0 {
values.Set("asset", asset)
}
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_TRADE_BALANCE, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenTradeBalance, values)
}
func (k *Kraken) GetOpenOrders(showTrades bool, userref int64) {
// GetOpenOrders returns all current open orders
func (k *Kraken) GetOpenOrders(showTrades bool, userref int64) (interface{}, error) {
values := url.Values{}
if showTrades {
@@ -324,17 +389,11 @@ func (k *Kraken) GetOpenOrders(showTrades bool, userref int64) {
values.Set("userref", strconv.FormatInt(userref, 10))
}
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_OPEN_ORDERS, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenOpenOrders, values)
}
func (k *Kraken) GetClosedOrders(showTrades bool, userref, start, end, offset int64, closetime string) {
// GetClosedOrders returns a list of closed orders
func (k *Kraken) GetClosedOrders(showTrades bool, userref, start, end, offset int64, closetime string) (interface{}, error) {
values := url.Values{}
if showTrades {
@@ -361,17 +420,11 @@ func (k *Kraken) GetClosedOrders(showTrades bool, userref, start, end, offset in
values.Set("closetime", closetime)
}
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_CLOSED_ORDERS, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenClosedOrders, values)
}
func (k *Kraken) QueryOrdersInfo(showTrades bool, userref, txid int64) {
// QueryOrdersInfo returns order information
func (k *Kraken) QueryOrdersInfo(showTrades bool, userref, txid int64) (interface{}, error) {
values := url.Values{}
if showTrades {
@@ -386,17 +439,11 @@ func (k *Kraken) QueryOrdersInfo(showTrades bool, userref, txid int64) {
values.Set("txid", strconv.FormatInt(userref, 10))
}
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_QUERY_ORDERS, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenQueryOrders, values)
}
func (k *Kraken) GetTradesHistory(tradeType string, showRelatedTrades bool, start, end, offset int64) {
// GetTradesHistory returns trade history information
func (k *Kraken) GetTradesHistory(tradeType string, showRelatedTrades bool, start, end, offset int64) (interface{}, error) {
values := url.Values{}
if len(tradeType) > 0 {
@@ -419,17 +466,11 @@ func (k *Kraken) GetTradesHistory(tradeType string, showRelatedTrades bool, star
values.Set("offset", strconv.FormatInt(offset, 10))
}
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_TRADES_HISTORY, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenTradeHistory, values)
}
func (k *Kraken) QueryTrades(txid int64, showRelatedTrades bool) {
// QueryTrades returns information on a specific trade
func (k *Kraken) QueryTrades(txid int64, showRelatedTrades bool) (interface{}, error) {
values := url.Values{}
values.Set("txid", strconv.FormatInt(txid, 10))
@@ -437,17 +478,11 @@ func (k *Kraken) QueryTrades(txid int64, showRelatedTrades bool) {
values.Set("trades", "true")
}
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_QUERY_TRADES, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenQueryTrades, values)
}
func (k *Kraken) OpenPositions(txid int64, showPL bool) {
// OpenPositions returns current open positions
func (k *Kraken) OpenPositions(txid int64, showPL bool) (interface{}, error) {
values := url.Values{}
values.Set("txid", strconv.FormatInt(txid, 10))
@@ -455,17 +490,11 @@ func (k *Kraken) OpenPositions(txid int64, showPL bool) {
values.Set("docalcs", "true")
}
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_OPEN_POSITIONS, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenOpenPositions, values)
}
func (k *Kraken) GetLedgers(symbol, asset, ledgerType string, start, end, offset int64) {
// GetLedgers returns current ledgers
func (k *Kraken) GetLedgers(symbol, asset, ledgerType string, start, end, offset int64) (interface{}, error) {
values := url.Values{}
if len(symbol) > 0 {
@@ -492,45 +521,27 @@ func (k *Kraken) GetLedgers(symbol, asset, ledgerType string, start, end, offset
values.Set("offset", strconv.FormatInt(offset, 10))
}
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_LEDGERS, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenLedgers, values)
}
func (k *Kraken) QueryLedgers(id string) {
// QueryLedgers queries an individual ledger by ID
func (k *Kraken) QueryLedgers(id string) (interface{}, error) {
values := url.Values{}
values.Set("id", id)
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_QUERY_LEDGERS, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenQueryLedgers, values)
}
func (k *Kraken) GetTradeVolume(symbol string) {
// GetTradeVolume returns your trade volume by currency
func (k *Kraken) GetTradeVolume(symbol string) (interface{}, error) {
values := url.Values{}
values.Set("pair", symbol)
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_TRADE_VOLUME, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenTradeVolume, values)
}
func (k *Kraken) AddOrder(symbol, side, orderType string, price, price2, volume, leverage, position float64) {
// AddOrder adds a new order for Kraken exchange
func (k *Kraken) AddOrder(symbol, side, orderType string, price, price2, volume, leverage, position float64) (interface{}, error) {
values := url.Values{}
values.Set("pairs", symbol)
values.Set("type", side)
@@ -541,36 +552,24 @@ func (k *Kraken) AddOrder(symbol, side, orderType string, price, price2, volume,
values.Set("leverage", strconv.FormatFloat(leverage, 'f', -1, 64))
values.Set("position", strconv.FormatFloat(position, 'f', -1, 64))
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_ORDER_PLACE, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenOrderPlace, values)
}
func (k *Kraken) CancelOrder(orderID int64) {
// CancelOrder cancels order by orderID
func (k *Kraken) CancelOrder(orderID int64) (interface{}, error) {
values := url.Values{}
values.Set("txid", strconv.FormatInt(orderID, 10))
result, err := k.SendAuthenticatedHTTPRequest(KRAKEN_ORDER_CANCEL, values)
if err != nil {
log.Println(err)
return
}
log.Println(result)
return k.SendAuthenticatedHTTPRequest(krakenOrderCancel, values)
}
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
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)
path := fmt.Sprintf("/%s/private/%s", krakenAPIVersion, method)
if k.Nonce.Get() == 0 {
k.Nonce.Set(time.Now().UnixNano())
} else {
@@ -578,8 +577,8 @@ func (k *Kraken) SendAuthenticatedHTTPRequest(method string, values url.Values)
}
values.Set("nonce", k.Nonce.String())
secret, err := common.Base64Decode(k.APISecret)
secret, err := common.Base64Decode(k.APISecret)
if err != nil {
return nil, err
}
@@ -588,22 +587,33 @@ func (k *Kraken) SendAuthenticatedHTTPRequest(method string, values url.Values)
signature := common.Base64Encode(common.GetHMAC(common.HashSHA512, append([]byte(path), shasum...), secret))
if k.Verbose {
log.Printf("Sending POST request to %s, path: %s.", KRAKEN_API_URL, path)
log.Printf("Sending POST request to %s, path: %s.", krakenAPIURL, path)
}
headers := make(map[string]string)
headers["API-Key"] = k.APIKey
headers["API-Sign"] = signature
resp, err := common.SendHTTPRequest("POST", KRAKEN_API_URL+path, headers, strings.NewReader(values.Encode()))
rawResp, err := common.SendHTTPRequest("POST", krakenAPIURL+path, headers, strings.NewReader(values.Encode()))
if err != nil {
return nil, err
}
if k.Verbose {
log.Printf("Received raw: \n%s\n", resp)
log.Printf("Received raw: \n%s\n", rawResp)
}
return resp, nil
var resp interface{}
err = common.JSONDecode([]byte(rawResp), &resp)
if err != nil {
return nil, err
}
data := resp.(map[string]interface{})
if len(data["error"].([]interface{})) != 0 {
return nil, fmt.Errorf("kraken AuthenticattedHTTPRequest error: %s", data["error"])
}
return data["result"].(interface{}), nil
}

View File

@@ -0,0 +1,218 @@
package kraken
import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
)
var k Kraken
// Please add your own APIkeys to do correct due diligence testing.
const (
apiKey = ""
apiSecret = ""
clientID = ""
)
func TestSetDefaults(t *testing.T) {
k.SetDefaults()
}
func TestSetup(t *testing.T) {
cfg := config.GetConfig()
cfg.LoadConfig("../../testdata/configtest.json")
krakenConfig, err := cfg.GetExchangeConfig("Kraken")
if err != nil {
t.Error("Test Failed - kraken Setup() init error", err)
}
krakenConfig.AuthenticatedAPISupport = true
krakenConfig.APIKey = apiKey
krakenConfig.APISecret = apiSecret
krakenConfig.ClientID = clientID
k.Setup(krakenConfig)
}
func TestGetFee(t *testing.T) {
t.Parallel()
if k.GetFee(true) != 0.1 {
t.Error("Test Failed - kraken GetFee() error")
}
if k.GetFee(false) != 0.35 {
t.Error("Test Failed - kraken GetFee() error")
}
}
func TestGetServerTime(t *testing.T) {
t.Parallel()
_, err := k.GetServerTime(false)
if err != nil {
t.Error("Test Failed - GetServerTime() error", err)
}
_, err = k.GetServerTime(true)
if err != nil {
t.Error("Test Failed - GetServerTime() error", err)
}
}
func TestGetAssets(t *testing.T) {
t.Parallel()
_, err := k.GetAssets()
if err != nil {
t.Error("Test Failed - GetAssets() error", err)
}
}
func TestGetAssetPairs(t *testing.T) {
t.Parallel()
_, err := k.GetAssetPairs()
if err != nil {
t.Error("Test Failed - GetAssetPairs() error", err)
}
}
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := k.GetTicker("BCHEUR")
if err != nil {
t.Error("Test Failed - GetTicker() error", err)
}
}
func TestGetOHLC(t *testing.T) {
t.Parallel()
_, err := k.GetOHLC("BCHEUR")
if err != nil {
t.Error("Test Failed - GetOHLC() error", err)
}
}
func TestGetDepth(t *testing.T) {
t.Parallel()
_, err := k.GetDepth("BCHEUR")
if err != nil {
t.Error("Test Failed - GetDepth() error", err)
}
}
func TestGetTrades(t *testing.T) {
t.Parallel()
_, err := k.GetTrades("BCHEUR")
if err != nil {
t.Error("Test Failed - GetTrades() error", err)
}
}
func TestGetSpread(t *testing.T) {
t.Parallel()
_, err := k.GetSpread("BCHEUR")
if err != nil {
t.Error("Test Failed - GetSpread() error", err)
}
}
func TestGetBalance(t *testing.T) {
t.Parallel()
_, err := k.GetBalance()
if err == nil {
t.Error("Test Failed - GetBalance() error", err)
}
}
func TestGetTradeBalance(t *testing.T) {
t.Parallel()
_, err := k.GetTradeBalance("", "")
if err == nil {
t.Error("Test Failed - GetTradeBalance() error", err)
}
}
func TestGetOpenOrders(t *testing.T) {
t.Parallel()
_, err := k.GetOpenOrders(true, 0)
if err == nil {
t.Error("Test Failed - GetOpenOrders() error", err)
}
}
func TestGetClosedOrders(t *testing.T) {
t.Parallel()
_, err := k.GetClosedOrders(true, 0, 0, 0, 0, "")
if err == nil {
t.Error("Test Failed - GetClosedOrders() error", err)
}
}
func TestQueryOrdersInfo(t *testing.T) {
t.Parallel()
_, err := k.QueryOrdersInfo(false, 0, 0)
if err == nil {
t.Error("Test Failed - QueryOrdersInfo() error", err)
}
}
func TestGetTradesHistory(t *testing.T) {
t.Parallel()
_, err := k.GetTradesHistory("", false, 0, 0, 0)
if err == nil {
t.Error("Test Failed - GetTradesHistory() error", err)
}
}
func TestQueryTrades(t *testing.T) {
t.Parallel()
_, err := k.QueryTrades(0, false)
if err == nil {
t.Error("Test Failed - QueryTrades() error", err)
}
}
func TestOpenPositions(t *testing.T) {
t.Parallel()
_, err := k.OpenPositions(0, false)
if err == nil {
t.Error("Test Failed - OpenPositions() error", err)
}
}
func TestGetLedgers(t *testing.T) {
t.Parallel()
_, err := k.GetLedgers("bla", "bla", "bla", 0, 0, 0)
if err == nil {
t.Error("Test Failed - GetLedgers() error", err)
}
}
func TestQueryLedgers(t *testing.T) {
t.Parallel()
_, err := k.QueryLedgers("1337")
if err == nil {
t.Error("Test Failed - QueryLedgers() error", err)
}
}
func TestGetTradeVolume(t *testing.T) {
t.Parallel()
_, err := k.GetTradeVolume("BCHEUR")
if err == nil {
t.Error("Test Failed - GetTradeVolume() error", err)
}
}
func TestAddOrder(t *testing.T) {
t.Parallel()
_, err := k.AddOrder("bla", "bla", "bla", 0, 0, 0, 0, 0)
if err == nil {
t.Error("Test Failed - AddOrder() error", err)
}
}
func TestCancelOrder(t *testing.T) {
t.Parallel()
_, err := k.CancelOrder(1337)
if err == nil {
t.Error("Test Failed - CancelOrder() error", err)
}
}

View File

@@ -1,6 +1,13 @@
package kraken
type KrakenAssetPairs struct {
// GeneralResponse is a generalized response type
type GeneralResponse struct {
Result map[string]interface{} `json:"result"`
Error []interface{} `json:"error"`
}
// AssetPairs holds asset pair information
type AssetPairs struct {
Altname string `json:"altname"`
AclassBase string `json:"aclass_base"`
Base string `json:"base"`
@@ -19,7 +26,8 @@ type KrakenAssetPairs struct {
MarginStop int `json:"margin_stop"`
}
type KrakenTicker struct {
// Ticker is a standard ticker type
type Ticker struct {
Ask float64
Bid float64
Last float64
@@ -31,6 +39,41 @@ type KrakenTicker struct {
Open float64
}
// TickerResponse holds ticker information before its put into the Ticker struct
type TickerResponse struct {
Ask []string `json:"a"`
Bid []string `json:"b"`
Last []string `json:"c"`
Volume []string `json:"v"`
VWAP []string `json:"p"`
Trades []int64 `json:"t"`
Low []string `json:"l"`
High []string `json:"h"`
Open string `json:"o"`
}
// OpenHighLowClose contains ticker event information
type OpenHighLowClose struct {
Time float64
Open float64
High float64
Low float64
Close float64
Vwap float64
Volume float64
Count float64
}
// RecentTrades holds recent trade data
type RecentTrades struct {
Price float64
Volume float64
Time float64
BuyOrSell string
MarketOrLimit string
Miscellaneous interface{}
}
// OrderbookBase stores the orderbook price and amount data
type OrderbookBase struct {
Price float64
@@ -43,14 +86,9 @@ type Orderbook struct {
Asks []OrderbookBase
}
type KrakenTickerResponse struct {
Ask []string `json:"a"`
Bid []string `json:"b"`
Last []string `json:"c"`
Volume []string `json:"v"`
VWAP []string `json:"p"`
Trades []int64 `json:"t"`
Low []string `json:"l"`
High []string `json:"h"`
Open string `json:"o"`
// Spread holds the spread between trades
type Spread struct {
Time float64
Bid float64
Ask float64
}

View File

@@ -1,8 +1,12 @@
package kraken
import (
"fmt"
"log"
"net/url"
"strconv"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/currency/pair"
"github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
@@ -44,7 +48,7 @@ func (k *Kraken) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Pri
if err != nil {
return tickerPrice, err
}
err = k.GetTicker(pairsCollated.String())
err = k.SetTicker(pairsCollated.String())
if err != nil {
return tickerPrice, err
}
@@ -68,6 +72,44 @@ func (k *Kraken) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Pri
return ticker.GetTicker(k.GetName(), p, assetType)
}
// SetTicker sets ticker information from kraken
func (k *Kraken) SetTicker(symbol string) error {
values := url.Values{}
values.Set("pair", symbol)
type Response struct {
Error []interface{} `json:"error"`
Data map[string]TickerResponse `json:"result"`
}
resp := Response{}
path := fmt.Sprintf("%s/%s/public/%s?%s", krakenAPIURL, krakenAPIVersion, krakenTicker, values.Encode())
err := common.SendHTTPGetRequest(path, true, k.Verbose, &resp)
if err != nil {
return err
}
if len(resp.Error) > 0 {
return fmt.Errorf("Kraken error: %s", resp.Error)
}
for x, y := range resp.Data {
ticker := Ticker{}
ticker.Ask, _ = strconv.ParseFloat(y.Ask[0], 64)
ticker.Bid, _ = strconv.ParseFloat(y.Bid[0], 64)
ticker.Last, _ = strconv.ParseFloat(y.Last[0], 64)
ticker.Volume, _ = strconv.ParseFloat(y.Volume[1], 64)
ticker.VWAP, _ = strconv.ParseFloat(y.VWAP[1], 64)
ticker.Trades = y.Trades[1]
ticker.Low, _ = strconv.ParseFloat(y.Low[1], 64)
ticker.High, _ = strconv.ParseFloat(y.High[1], 64)
ticker.Open, _ = strconv.ParseFloat(y.Open, 64)
k.Ticker[x] = ticker
}
return nil
}
// GetTickerPrice returns the ticker for a currency pair
func (k *Kraken) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
tickerNew, err := ticker.GetTicker(k.GetName(), p, assetType)