mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-08 15:11:07 +00:00
golangci-lint/CI: Bump versions and introduce new linters (#798)
* golangci-lint/CI: Bump versions
Fix remaining linter issues
* Specifically set AppVeyor version
* Fix the infamous typos 👀
* Add go env cmd to AppVeyor
* Add go version cmd to AppVeyor
* Specify AppVeyor image, adjust linters
* Update go get to go install due to deprecation
* Bump golangci-lint timeout time for AppVeyor
* Change NW contract to NQ
* Address nitters
* GetRandomPair -> Pair{}
* Address nits
* Address time nitterinos plus additional tweaks
* More time inception upgrades!
* Bending time and space
This commit is contained in:
@@ -10,8 +10,10 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
@@ -214,46 +216,59 @@ func (k *Kraken) GetOHLC(ctx context.Context, symbol currency.Pair, interval str
|
||||
Data map[string]interface{} `json:"result"`
|
||||
}
|
||||
|
||||
var OHLC []OpenHighLowClose
|
||||
var result Response
|
||||
|
||||
path := fmt.Sprintf("/%s/public/%s?%s", krakenAPIVersion, krakenOHLC, values.Encode())
|
||||
|
||||
err = k.SendHTTPRequest(ctx, exchange.RestSpot, path, &result)
|
||||
if err != nil {
|
||||
return OHLC, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(result.Error) != 0 {
|
||||
return OHLC, fmt.Errorf("getOHLC error: %s", result.Error)
|
||||
return nil, fmt.Errorf("getOHLC error: %s", result.Error)
|
||||
}
|
||||
|
||||
_, ok := result.Data[translatedAsset].([]interface{})
|
||||
ohlcData, ok := result.Data[translatedAsset].([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("invalid data returned")
|
||||
}
|
||||
|
||||
for _, y := range result.Data[translatedAsset].([]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.VolumeWeightedAveragePrice, _ = strconv.ParseFloat(x.(string), 64)
|
||||
case 6:
|
||||
o.Volume, _ = strconv.ParseFloat(x.(string), 64)
|
||||
case 7:
|
||||
o.Count = x.(float64)
|
||||
}
|
||||
var OHLC []OpenHighLowClose
|
||||
for x := range ohlcData {
|
||||
subData, ok := ohlcData[x].([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert subData")
|
||||
}
|
||||
|
||||
if len(subData) < 8 {
|
||||
return nil, errors.New("unexpected data length returned")
|
||||
}
|
||||
|
||||
var o OpenHighLowClose
|
||||
if o.Time, ok = subData[0].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert time")
|
||||
}
|
||||
if o.Open, err = convert.FloatFromString(subData[1]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if o.High, err = convert.FloatFromString(subData[2]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if o.Low, err = convert.FloatFromString(subData[3]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if o.Close, err = convert.FloatFromString(subData[4]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if o.VolumeWeightedAveragePrice, err = convert.FloatFromString(subData[5]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if o.Volume, err = convert.FloatFromString(subData[6]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if o.Count, ok = subData[7].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert count")
|
||||
}
|
||||
OHLC = append(OHLC, o)
|
||||
}
|
||||
@@ -280,24 +295,40 @@ func (k *Kraken) GetDepth(ctx context.Context, symbol currency.Pair) (Orderbook,
|
||||
return orderBook, fmt.Errorf("%s GetDepth result is nil", k.Name)
|
||||
}
|
||||
|
||||
data := result.(map[string]interface{})
|
||||
if data["result"] == nil {
|
||||
data, ok := result.(map[string]interface{})
|
||||
if !ok {
|
||||
return orderBook, errors.New("unable to type assert data")
|
||||
}
|
||||
orderbookData, ok := data["result"].(map[string]interface{})
|
||||
if !ok {
|
||||
return orderBook, fmt.Errorf("%s GetDepth data[result] is nil", k.Name)
|
||||
}
|
||||
orderbookData := data["result"].(map[string]interface{})
|
||||
|
||||
var bidsData []interface{}
|
||||
var asksData []interface{}
|
||||
for _, y := range orderbookData {
|
||||
yData := y.(map[string]interface{})
|
||||
bidsData = yData["bids"].([]interface{})
|
||||
asksData = yData["asks"].([]interface{})
|
||||
yData, ok := y.(map[string]interface{})
|
||||
if !ok {
|
||||
return orderBook, errors.New("unable to type assert yData")
|
||||
}
|
||||
if bidsData, ok = yData["bids"].([]interface{}); !ok {
|
||||
return orderBook, errors.New("unable to type assert bidsData")
|
||||
}
|
||||
if asksData, ok = yData["asks"].([]interface{}); !ok {
|
||||
return orderBook, errors.New("unable to type assert asksData")
|
||||
}
|
||||
}
|
||||
|
||||
processOrderbook := func(data []interface{}) ([]OrderbookBase, error) {
|
||||
var result []OrderbookBase
|
||||
for x := range data {
|
||||
entry := data[x].([]interface{})
|
||||
entry, ok := data[x].([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert entry")
|
||||
}
|
||||
|
||||
if len(entry) < 2 {
|
||||
return nil, errors.New("unexpected entry length")
|
||||
}
|
||||
|
||||
price, priceErr := strconv.ParseFloat(entry[0].(string), 64)
|
||||
if priceErr != nil {
|
||||
@@ -439,30 +470,48 @@ func (k *Kraken) GetSpread(ctx context.Context, symbol currency.Pair) ([]Spread,
|
||||
}
|
||||
values.Set("pair", symbolValue)
|
||||
|
||||
var peanutButter []Spread
|
||||
var response interface{}
|
||||
|
||||
resp := struct {
|
||||
SpreadData map[string]interface{} `json:"result"`
|
||||
}{}
|
||||
path := fmt.Sprintf("/%s/public/%s?%s", krakenAPIVersion, krakenSpread, values.Encode())
|
||||
|
||||
err = k.SendHTTPRequest(ctx, exchange.RestSpot, path, &response)
|
||||
err = k.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp)
|
||||
if err != nil {
|
||||
return peanutButter, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := response.(map[string]interface{})
|
||||
result := data["result"].(map[string]interface{})
|
||||
data, ok := resp.SpreadData[symbolValue]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to find %s in spread data", symbolValue)
|
||||
}
|
||||
|
||||
for _, x := range result[symbolValue].([]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)
|
||||
}
|
||||
spreadData, ok := data.([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert spreadData")
|
||||
}
|
||||
|
||||
var peanutButter []Spread
|
||||
for x := range spreadData {
|
||||
subData, ok := spreadData[x].([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert subData")
|
||||
}
|
||||
|
||||
if len(subData) < 3 {
|
||||
return nil, errors.New("unexpected data length")
|
||||
}
|
||||
|
||||
var s Spread
|
||||
timeData, ok := subData[0].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert timeData")
|
||||
}
|
||||
s.Time = time.Unix(int64(timeData), 0)
|
||||
|
||||
if s.Bid, err = convert.FloatFromString(subData[1]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s.Ask, err = convert.FloatFromString(subData[2]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
peanutButter = append(peanutButter, s)
|
||||
}
|
||||
@@ -1203,8 +1252,7 @@ func (a *assetTranslatorStore) Seed(orig, alt string) {
|
||||
a.Assets = make(map[string]string)
|
||||
}
|
||||
|
||||
_, ok := a.Assets[orig]
|
||||
if ok {
|
||||
if _, ok := a.Assets[orig]; ok {
|
||||
a.l.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ func (k *Kraken) SendFuturesAuthRequest(ctx context.Context, method, path string
|
||||
|
||||
interim := json.RawMessage{}
|
||||
newRequest := func() (*request.Item, error) {
|
||||
nonce := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
|
||||
nonce := strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||||
reqData := ""
|
||||
if len(data) > 0 {
|
||||
temp, err := json.Marshal(data)
|
||||
|
||||
@@ -1128,6 +1128,7 @@ func TestWithdrawCancel(t *testing.T) {
|
||||
// ---------------------------- Websocket tests -----------------------------------------
|
||||
|
||||
func setupWsTests(t *testing.T) {
|
||||
t.Helper()
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
@@ -1205,16 +1206,14 @@ func TestWsAddOrder(t *testing.T) {
|
||||
|
||||
func TestWsCancelOrder(t *testing.T) {
|
||||
setupWsTests(t)
|
||||
err := k.wsCancelOrders([]string{"1337"})
|
||||
if err != nil {
|
||||
if err := k.wsCancelOrders([]string{"1337"}); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWsCancelAllOrders(t *testing.T) {
|
||||
setupWsTests(t)
|
||||
_, err := k.wsCancelAllOrders()
|
||||
if err != nil {
|
||||
if _, err := k.wsCancelAllOrders(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -1994,6 +1993,7 @@ func Test_FormatExchangeKlineInterval(t *testing.T) {
|
||||
test := testCases[x]
|
||||
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ret := k.FormatExchangeKlineInterval(test.interval)
|
||||
|
||||
if ret != test.output {
|
||||
|
||||
@@ -188,7 +188,7 @@ type Orderbook struct {
|
||||
|
||||
// Spread holds the spread between trades
|
||||
type Spread struct {
|
||||
Time float64
|
||||
Time time.Time
|
||||
Bid float64
|
||||
Ask float64
|
||||
}
|
||||
|
||||
@@ -717,16 +717,38 @@ func (k *Kraken) wsProcessTickers(channelData *WebsocketChannelData, data map[st
|
||||
|
||||
// wsProcessSpread converts spread/orderbook data and sends it to the datahandler
|
||||
func (k *Kraken) wsProcessSpread(channelData *WebsocketChannelData, data []interface{}) {
|
||||
bestBid := data[0].(string)
|
||||
bestAsk := data[1].(string)
|
||||
if len(data) < 5 {
|
||||
k.Websocket.DataHandler <- fmt.Errorf("%s unexpected wsProcessSpread data length", k.Name)
|
||||
return
|
||||
}
|
||||
bestBid, ok := data[0].(string)
|
||||
if !ok {
|
||||
k.Websocket.DataHandler <- fmt.Errorf("%s wsProcessSpread: unable to type assert bestBid", k.Name)
|
||||
return
|
||||
}
|
||||
bestAsk, ok := data[1].(string)
|
||||
if !ok {
|
||||
k.Websocket.DataHandler <- fmt.Errorf("%s wsProcessSpread: unable to type assert bestAsk", k.Name)
|
||||
return
|
||||
}
|
||||
timeData, err := strconv.ParseFloat(data[2].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
k.Websocket.DataHandler <- fmt.Errorf("%s wsProcessSpread: unable to parse timeData. Error: %s",
|
||||
k.Name,
|
||||
err)
|
||||
return
|
||||
}
|
||||
bidVolume, ok := data[3].(string)
|
||||
if !ok {
|
||||
k.Websocket.DataHandler <- fmt.Errorf("%s wsProcessSpread: unable to type assert bidVolume", k.Name)
|
||||
return
|
||||
}
|
||||
askVolume, ok := data[4].(string)
|
||||
if !ok {
|
||||
k.Websocket.DataHandler <- fmt.Errorf("%s wsProcessSpread: unable to type assert askVolume", k.Name)
|
||||
return
|
||||
}
|
||||
|
||||
bidVolume := data[3].(string)
|
||||
askVolume := data[4].(string)
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys,
|
||||
"%v Spread data for '%v' received. Best bid: '%v' Best ask: '%v' Time: '%v', Bid volume '%v', Ask volume '%v'",
|
||||
@@ -839,7 +861,13 @@ func (k *Kraken) wsProcessOrderBookPartial(channelData *WebsocketChannelData, as
|
||||
// to respect both within a reasonable degree
|
||||
var highestLastUpdate time.Time
|
||||
for i := range askData {
|
||||
asks := askData[i].([]interface{})
|
||||
asks, ok := askData[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert asks")
|
||||
}
|
||||
if len(asks) < 3 {
|
||||
return errors.New("unexpected asks length")
|
||||
}
|
||||
price, err := strconv.ParseFloat(asks[0].(string), 64)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -863,7 +891,13 @@ func (k *Kraken) wsProcessOrderBookPartial(channelData *WebsocketChannelData, as
|
||||
}
|
||||
|
||||
for i := range bidData {
|
||||
bids := bidData[i].([]interface{})
|
||||
bids, ok := bidData[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert bids")
|
||||
}
|
||||
if len(bids) < 3 {
|
||||
return errors.New("unexpected bids length")
|
||||
}
|
||||
price, err := strconv.ParseFloat(bids[0].(string), 64)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -906,7 +940,10 @@ func (k *Kraken) wsProcessOrderBookUpdate(channelData *WebsocketChannelData, ask
|
||||
var highestLastUpdate time.Time
|
||||
// Ask data is not always sent
|
||||
for i := range askData {
|
||||
asks := askData[i].([]interface{})
|
||||
asks, ok := askData[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("asks type assertion failure")
|
||||
}
|
||||
|
||||
priceStr, ok := asks[0].(string)
|
||||
if !ok {
|
||||
@@ -966,7 +1003,10 @@ func (k *Kraken) wsProcessOrderBookUpdate(channelData *WebsocketChannelData, ask
|
||||
|
||||
// Bid data is not always sent
|
||||
for i := range bidData {
|
||||
bids := bidData[i].([]interface{})
|
||||
bids, ok := bidData[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert bids")
|
||||
}
|
||||
|
||||
priceStr, ok := bids[0].(string)
|
||||
if !ok {
|
||||
|
||||
@@ -487,8 +487,7 @@ func (k *Kraken) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (k *Kraken) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := k.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := k.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(k.Name, p, a)
|
||||
@@ -615,8 +614,7 @@ func (k *Kraken) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
})
|
||||
}
|
||||
}
|
||||
err := account.Process(&info)
|
||||
if err != nil {
|
||||
if err := account.Process(&info); err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
return info, nil
|
||||
@@ -698,8 +696,7 @@ func (k *Kraken) GetHistoricTrades(_ context.Context, _ currency.Pair, _ asset.I
|
||||
// SubmitOrder submits a new order
|
||||
func (k *Kraken) SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitResponse, error) {
|
||||
var submitOrderResponse order.SubmitResponse
|
||||
err := s.Validate()
|
||||
if err != nil {
|
||||
if err := s.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
switch s.AssetType {
|
||||
@@ -707,7 +704,7 @@ func (k *Kraken) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submit
|
||||
if k.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
var resp string
|
||||
s.Pair.Delimiter = "/" // required pair format: ISO 4217-A3
|
||||
resp, err = k.wsAddOrder(&WsAddOrderRequest{
|
||||
resp, err := k.wsAddOrder(&WsAddOrderRequest{
|
||||
OrderType: s.Type.Lower(),
|
||||
OrderSide: s.Side.Lower(),
|
||||
Pair: s.Pair.String(),
|
||||
@@ -721,7 +718,7 @@ func (k *Kraken) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submit
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
} else {
|
||||
var response AddOrderResponse
|
||||
response, err = k.AddOrder(ctx,
|
||||
response, err := k.AddOrder(ctx,
|
||||
s.Pair,
|
||||
s.Side.String(),
|
||||
s.Type.String(),
|
||||
|
||||
Reference in New Issue
Block a user