Kraken: Fix TestGetOpenInterest (#1611)

* Kraken: Fix TestGetOpenInterest

We see daily failures on OpenInterest for Kraken.
This fix assumes that the issue might be related to volume of ETHUSD
open interest, and switches the single pair test to XBTUSD instead

Also isolates the test from others, since we're changing stored pairs
and we might be colliding on the global k

* Kraken: Handle Errors field in futures response
This commit is contained in:
Gareth Kirwan
2024-08-16 05:47:32 +01:00
committed by GitHub
parent 91ff6c5c12
commit 0becfbd0a6
11 changed files with 69 additions and 34 deletions

View File

@@ -848,15 +848,10 @@ func (k *Kraken) SendHTTPRequest(ctx context.Context, ep exchange.URL, path stri
return genResponse.Error.Errors()
}
var genResp genericFuturesResponse
if err := json.Unmarshal(rawMessage, &genResp); err != nil {
if err := getFuturesErr(rawMessage); err != nil {
return err
}
if genResp.Error != "" && genResp.Result != "success" {
return errors.New(genResp.Error)
}
return json.Unmarshal(rawMessage, result)
}

View File

@@ -377,20 +377,46 @@ func (k *Kraken) SendFuturesAuthRequest(ctx context.Context, method, path string
}, nil
}
if err := k.SendPayload(ctx, request.Unset, newRequest, request.AuthenticatedRequest); err != nil {
return err
err = k.SendPayload(ctx, request.Unset, newRequest, request.AuthenticatedRequest)
if err == nil {
err = getFuturesErr(interim)
}
var resp genericFuturesResponse
if err := json.Unmarshal(interim, &resp); err != nil {
return fmt.Errorf("%w %w", request.ErrAuthRequestFailed, err)
} else if resp.Error != "" && resp.Result != "success" {
return fmt.Errorf("%w %v", request.ErrAuthRequestFailed, resp.Error)
if err == nil {
err = json.Unmarshal(interim, result)
}
if err := json.Unmarshal(interim, result); err != nil {
if err != nil {
return fmt.Errorf("%w %w", request.ErrAuthRequestFailed, err)
}
return nil
}
func getFuturesErr(msg json.RawMessage) error {
var resp genericFuturesResponse
if err := json.Unmarshal(msg, &resp); err != nil {
return err
}
// Result may be omitted entirely, so we don't test for == "success"
if resp.Result != "error" {
return nil
}
var errs error
if resp.Error != "" {
errs = errors.New(resp.Error)
}
for _, err := range resp.Errors {
errs = common.AppendError(errs, errors.New(err))
}
if errs == nil {
return fmt.Errorf("%w from message: %s", common.ErrUnknownError, msg)
}
return errs
}

View File

@@ -2079,20 +2079,15 @@ func TestChecksumCalculation(t *testing.T) {
func TestGetCharts(t *testing.T) {
t.Parallel()
cp, err := currency.NewPairFromStrings("PI", "BCHUSD")
if err != nil {
t.Error(err)
}
require.NoError(t, err)
cp.Delimiter = "_"
resp, err := k.GetFuturesCharts(context.Background(), "1d", "spot", cp, time.Time{}, time.Time{})
if err != nil {
t.Error(err)
}
require.NoError(t, err)
require.NotEmpty(t, resp.Candles)
end := time.UnixMilli(resp.Candles[0].Time)
_, err = k.GetFuturesCharts(context.Background(), "1d", "spot", cp, end.Add(-time.Hour*24*7), end)
if err != nil {
t.Error(err)
}
require.NoError(t, err)
}
func TestGetFuturesTrades(t *testing.T) {
@@ -2251,6 +2246,9 @@ func TestIsPerpetualFutureCurrency(t *testing.T) {
func TestGetOpenInterest(t *testing.T) {
t.Parallel()
k := new(Kraken) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
require.NoError(t, testexch.Setup(k), "Test instance Setup must not error")
_, err := k.GetOpenInterest(context.Background(), key.PairAsset{
Base: currency.ETH.Item,
Quote: currency.USDT.Item,
@@ -2258,8 +2256,8 @@ func TestGetOpenInterest(t *testing.T) {
})
assert.ErrorIs(t, err, asset.ErrNotSupported)
cp1 := currency.NewPair(currency.PF, currency.NewCode("ETHUSD"))
cp2 := currency.NewPair(currency.PF, currency.NewCode("XBTUSD"))
cp1 := currency.NewPair(currency.PF, currency.NewCode("XBTUSD"))
cp2 := currency.NewPair(currency.PF, currency.NewCode("ETHUSD"))
sharedtestvalues.SetupCurrencyPairsForExchangeAsset(t, k, asset.Futures, cp1, cp2)
resp, err := k.GetOpenInterest(context.Background(), key.PairAsset{
@@ -2396,3 +2394,20 @@ func TestErrorResponse(t *testing.T) {
})
}
}
func TestGetFuturesErr(t *testing.T) {
t.Parallel()
assert.ErrorContains(t, getFuturesErr(json.RawMessage(`unparsable rubbish`)), "invalid character", "Bad JSON should error correctly")
assert.NoError(t, getFuturesErr(json.RawMessage(`{"candles":[]}`)), "JSON with no Result should not error")
assert.NoError(t, getFuturesErr(json.RawMessage(`{"Result":"4 goats"}`)), "JSON with non-error Result should not error")
assert.ErrorIs(t, getFuturesErr(json.RawMessage(`{"Result":"error"}`)), common.ErrUnknownError, "JSON with error Result should error correctly")
assert.ErrorContains(t, getFuturesErr(json.RawMessage(`{"Result":"error", "error": "1 goat"}`)), "1 goat", "JSON with an error should error correctly")
err := getFuturesErr(json.RawMessage(`{"Result":"error", "errors": ["2 goats", "3 goats"]}`))
assert.ErrorContains(t, err, "2 goat", "JSON with errors should error correctly")
assert.ErrorContains(t, err, "3 goat", "JSON with errors should error correctly")
err = getFuturesErr(json.RawMessage(`{"Result":"error", "error": "too many goats", "errors": ["2 goats", "3 goats"]}`))
assert.ErrorContains(t, err, "2 goat", "JSON with both error and errors should error correctly")
assert.ErrorContains(t, err, "3 goat", "JSON with both error and errors should error correctly")
assert.ErrorContains(t, err, "too many goat", "JSON both error and with errors should error correctly")
}

View File

@@ -93,6 +93,7 @@ type genericFuturesResponse struct {
Result string `json:"result"`
ServerTime time.Time `json:"serverTime"`
Error string `json:"error"`
Errors []string `json:"errors"`
}
// Asset holds asset information

View File

@@ -66,7 +66,6 @@ var (
m sync.Mutex
errNoWebsocketOrderbookData = errors.New("no websocket orderbook data")
errParsingWSField = errors.New("error parsing WS field")
errUnknownError = errors.New("unknown error")
errCancellingOrder = errors.New("error cancelling order")
)
@@ -1360,7 +1359,7 @@ func (k *Kraken) wsCancelOrder(orderID string) error {
return nil
}
err = errUnknownError
err = common.ErrUnknownError
if msg, pErr := jsonparser.GetUnsafeString(resp, "errorMessage"); pErr == nil && msg != "" {
err = errors.New(msg)
}