mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-23 23:16:49 +00:00
Tests: Various race fixes and move TestFixtureToDataHandler (#1534)
* Tests: Move and simplify TestFixtureToDataHandler * Currency: Fix PairsManager.Load breaking matcher * Tests: Add multi-instance cache to UpdatePairsOnce * Kraken: Fix TestUpdateTickers race error Calling StorePairs on global instance can lead to race * Bitfinex: Fix TestUpdateTickers racing intermittently * Currency: Fix concurrent access to PM formats * Currency: Fix SupportsAsset implementation This should delegate entirely to PairManager's IsAssetSupported * Okx: Fix PM intrusion, rm GetPairFromInstrumentID * Exchange: Fix SetGlobalPairsManager to set asset enabled * Bitflyer: Fix race on set TestGetCurrURL TestGetCurrencyTradeURL would fail sometimes due to sequencing of enabling futures but not having pairs for it. * Tests: Simplify usage pattern for FixtureToDH
This commit is contained in:
@@ -547,6 +547,8 @@ func TestUpdateTicker(t *testing.T) {
|
||||
func TestUpdateTickers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
b := new(Bitfinex) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
require.NoError(t, testexch.Setup(b), "Test instance Setup must not error")
|
||||
testexch.UpdatePairsOnce(t, b)
|
||||
|
||||
assets := b.GetAssetTypes(false)
|
||||
|
||||
@@ -455,14 +455,14 @@ func TestUpdateTradablePairs(t *testing.T) {
|
||||
func TestGetCurrencyTradeURL(t *testing.T) {
|
||||
t.Parallel()
|
||||
testexch.UpdatePairsOnce(t, b)
|
||||
err := b.CurrencyPairs.SetAssetEnabled(asset.Futures, true)
|
||||
require.NoError(t, err)
|
||||
err := b.CurrencyPairs.SetAssetEnabled(asset.Futures, false)
|
||||
require.NoError(t, err, "SetAssetEnabled must not error")
|
||||
for _, a := range b.GetAssetTypes(false) {
|
||||
pairs, err := b.CurrencyPairs.GetPairs(a, false)
|
||||
require.NoError(t, err, "cannot get pairs for %s", a)
|
||||
require.NotEmpty(t, pairs, "no pairs for %s", a)
|
||||
resp, err := b.GetCurrencyTradeURL(context.Background(), a, pairs[0])
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, resp)
|
||||
require.NoError(t, err, "GetCurrencyTradeURL must not error")
|
||||
assert.NotEmpty(t, resp, "GetCurrencyTradeURL should return an url")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,84 +776,79 @@ func TestWsOrderbook2(t *testing.T) {
|
||||
func TestWsOrderUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
n := new(Bitstamp)
|
||||
sharedtestvalues.TestFixtureToDataHandler(t, b, n, "testdata/wsMyOrders.json", n.wsHandleData)
|
||||
seen := 0
|
||||
for reading := true; reading; {
|
||||
select {
|
||||
default:
|
||||
reading = false
|
||||
case resp := <-n.GetBase().Websocket.DataHandler:
|
||||
seen++
|
||||
switch v := resp.(type) {
|
||||
case *order.Detail:
|
||||
switch seen {
|
||||
case 1:
|
||||
assert.Equal(t, "1658864794234880", v.OrderID, "OrderID")
|
||||
assert.Equal(t, time.UnixMicro(1693831262313000), v.Date, "Date")
|
||||
assert.Equal(t, "test_market_buy", v.ClientOrderID, "ClientOrderID")
|
||||
assert.Equal(t, order.New, v.Status, "Status")
|
||||
assert.Equal(t, order.Buy, v.Side, "Side")
|
||||
assert.Equal(t, asset.Spot, v.AssetType, "AssetType")
|
||||
assert.Equal(t, currency.NewPairWithDelimiter("BTC", "USD", "/"), v.Pair, "Pair")
|
||||
assert.Equal(t, 0.0, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 999999999.0, v.Price, "Price") // Market Buy Price
|
||||
// Note: Amount is 0 for market order create messages, oddly
|
||||
case 2:
|
||||
assert.Equal(t, "1658864794234880", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.PartiallyFilled, v.Status, "Status")
|
||||
assert.Equal(t, 0.00038667, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.00000001, v.RemainingAmount, "RemainingAmount") // During live tests we consistently got back this Sat remaining
|
||||
assert.Equal(t, 0.00038666, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 25862.0, v.Price, "Price")
|
||||
case 3:
|
||||
assert.Equal(t, "1658864794234880", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Cancelled, v.Status, "Status") // Even though they probably consider it filled, Deleted + PartialFill = Cancelled
|
||||
assert.Equal(t, 0.00038667, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.00000001, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038666, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 25862.0, v.Price, "Price")
|
||||
case 4:
|
||||
assert.Equal(t, "1658870500933632", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.New, v.Status, "Status")
|
||||
assert.Equal(t, order.Sell, v.Side, "Side")
|
||||
assert.Equal(t, 0.0, v.Price, "Price") // Market Sell Price
|
||||
case 5:
|
||||
assert.Equal(t, "1658870500933632", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.PartiallyFilled, v.Status, "Status")
|
||||
assert.Equal(t, 0.00038679, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.00000001, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038678, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 25854.0, v.Price, "Price")
|
||||
case 6:
|
||||
assert.Equal(t, "1658870500933632", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Cancelled, v.Status, "Status")
|
||||
assert.Equal(t, 0.00038679, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.00000001, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038678, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 25854.0, v.Price, "Price")
|
||||
case 7:
|
||||
assert.Equal(t, "1658869033291777", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.New, v.Status, "Status")
|
||||
assert.Equal(t, order.Sell, v.Side, "Side")
|
||||
assert.Equal(t, 25845.0, v.Price, "Price")
|
||||
assert.Equal(t, 0.00038692, v.Amount, "Amount")
|
||||
case 8:
|
||||
assert.Equal(t, "1658869033291777", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Filled, v.Status, "Status")
|
||||
assert.Equal(t, 25845.0, v.Price, "Price")
|
||||
assert.Equal(t, 0.00038692, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.0, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038692, v.ExecutedAmount, "ExecutedAmount")
|
||||
}
|
||||
case error:
|
||||
t.Error(v)
|
||||
default:
|
||||
t.Errorf("Got unexpected data: %T %v", v, v)
|
||||
b := new(Bitstamp) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
require.NoError(t, testexch.Setup(b), "Test instance Setup must not error")
|
||||
testexch.FixtureToDataHandler(t, "testdata/wsMyOrders.json", b.wsHandleData)
|
||||
close(b.Websocket.DataHandler)
|
||||
assert.Len(t, b.Websocket.DataHandler, 8, "Should see 8 orders")
|
||||
for resp := range b.Websocket.DataHandler {
|
||||
switch v := resp.(type) {
|
||||
case *order.Detail:
|
||||
switch len(b.Websocket.DataHandler) {
|
||||
case 7:
|
||||
assert.Equal(t, "1658864794234880", v.OrderID, "OrderID")
|
||||
assert.Equal(t, time.UnixMicro(1693831262313000), v.Date, "Date")
|
||||
assert.Equal(t, "test_market_buy", v.ClientOrderID, "ClientOrderID")
|
||||
assert.Equal(t, order.New, v.Status, "Status")
|
||||
assert.Equal(t, order.Buy, v.Side, "Side")
|
||||
assert.Equal(t, asset.Spot, v.AssetType, "AssetType")
|
||||
assert.Equal(t, currency.NewPairWithDelimiter("BTC", "USD", "/"), v.Pair, "Pair")
|
||||
assert.Equal(t, 0.0, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 999999999.0, v.Price, "Price") // Market Buy Price
|
||||
// Note: Amount is 0 for market order create messages, oddly
|
||||
case 6:
|
||||
assert.Equal(t, "1658864794234880", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.PartiallyFilled, v.Status, "Status")
|
||||
assert.Equal(t, 0.00038667, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.00000001, v.RemainingAmount, "RemainingAmount") // During live tests we consistently got back this Sat remaining
|
||||
assert.Equal(t, 0.00038666, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 25862.0, v.Price, "Price")
|
||||
case 5:
|
||||
assert.Equal(t, "1658864794234880", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Cancelled, v.Status, "Status") // Even though they probably consider it filled, Deleted + PartialFill = Cancelled
|
||||
assert.Equal(t, 0.00038667, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.00000001, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038666, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 25862.0, v.Price, "Price")
|
||||
case 4:
|
||||
assert.Equal(t, "1658870500933632", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.New, v.Status, "Status")
|
||||
assert.Equal(t, order.Sell, v.Side, "Side")
|
||||
assert.Equal(t, 0.0, v.Price, "Price") // Market Sell Price
|
||||
case 3:
|
||||
assert.Equal(t, "1658870500933632", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.PartiallyFilled, v.Status, "Status")
|
||||
assert.Equal(t, 0.00038679, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.00000001, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038678, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 25854.0, v.Price, "Price")
|
||||
case 2:
|
||||
assert.Equal(t, "1658870500933632", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Cancelled, v.Status, "Status")
|
||||
assert.Equal(t, 0.00038679, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.00000001, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038678, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 25854.0, v.Price, "Price")
|
||||
case 1:
|
||||
assert.Equal(t, "1658869033291777", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.New, v.Status, "Status")
|
||||
assert.Equal(t, order.Sell, v.Side, "Side")
|
||||
assert.Equal(t, 25845.0, v.Price, "Price")
|
||||
assert.Equal(t, 0.00038692, v.Amount, "Amount")
|
||||
case 0:
|
||||
assert.Equal(t, "1658869033291777", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Filled, v.Status, "Status")
|
||||
assert.Equal(t, 25845.0, v.Price, "Price")
|
||||
assert.Equal(t, 0.00038692, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.0, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038692, v.ExecutedAmount, "ExecutedAmount")
|
||||
}
|
||||
case error:
|
||||
t.Error(v)
|
||||
default:
|
||||
t.Errorf("Got unexpected data: %T %v", v, v)
|
||||
}
|
||||
}
|
||||
assert.Equal(t, 8, seen, "Number of messages")
|
||||
}
|
||||
|
||||
func TestWsRequestReconnect(t *testing.T) {
|
||||
|
||||
@@ -55,10 +55,6 @@ var (
|
||||
errEndpointStringNotFound = errors.New("endpoint string not found")
|
||||
errConfigPairFormatRequiresDelimiter = errors.New("config pair format requires delimiter")
|
||||
errSymbolCannotBeMatched = errors.New("symbol cannot be matched")
|
||||
errGlobalRequestFormatIsNil = errors.New("global request format is nil")
|
||||
errGlobalConfigFormatIsNil = errors.New("global config format is nil")
|
||||
errAssetRequestFormatIsNil = errors.New("asset type request format is nil")
|
||||
errAssetConfigFormatIsNil = errors.New("asset type config format is nil")
|
||||
errSetDefaultsNotCalled = errors.New("set defaults not called")
|
||||
errExchangeIsNil = errors.New("exchange is nil")
|
||||
errBatchSizeZero = errors.New("batch size cannot be 0")
|
||||
@@ -397,39 +393,9 @@ func (b *Base) GetSupportedFeatures() FeaturesSupported {
|
||||
return b.Features.Supports
|
||||
}
|
||||
|
||||
// GetPairFormat returns the pair format based on the exchange and
|
||||
// asset type
|
||||
func (b *Base) GetPairFormat(assetType asset.Item, requestFormat bool) (currency.PairFormat, error) {
|
||||
if b.CurrencyPairs.UseGlobalFormat {
|
||||
if requestFormat {
|
||||
if b.CurrencyPairs.RequestFormat == nil {
|
||||
return currency.EMPTYFORMAT, errGlobalRequestFormatIsNil
|
||||
}
|
||||
return *b.CurrencyPairs.RequestFormat, nil
|
||||
}
|
||||
|
||||
if b.CurrencyPairs.ConfigFormat == nil {
|
||||
return currency.EMPTYFORMAT, errGlobalConfigFormatIsNil
|
||||
}
|
||||
return *b.CurrencyPairs.ConfigFormat, nil
|
||||
}
|
||||
|
||||
ps, err := b.CurrencyPairs.Get(assetType)
|
||||
if err != nil {
|
||||
return currency.EMPTYFORMAT, err
|
||||
}
|
||||
|
||||
if requestFormat {
|
||||
if ps.RequestFormat == nil {
|
||||
return currency.EMPTYFORMAT, errAssetRequestFormatIsNil
|
||||
}
|
||||
return *ps.RequestFormat, nil
|
||||
}
|
||||
|
||||
if ps.ConfigFormat == nil {
|
||||
return currency.EMPTYFORMAT, errAssetConfigFormatIsNil
|
||||
}
|
||||
return *ps.ConfigFormat, nil
|
||||
// GetPairFormat returns the pair format based on the exchange and asset type
|
||||
func (b *Base) GetPairFormat(a asset.Item, r bool) (currency.PairFormat, error) {
|
||||
return b.CurrencyPairs.GetFormat(a, r)
|
||||
}
|
||||
|
||||
// GetEnabledPairs is a method that returns the enabled currency pairs of
|
||||
@@ -1007,11 +973,9 @@ func (b *Base) FormatWithdrawPermissions() string {
|
||||
return NoAPIWithdrawalMethodsText
|
||||
}
|
||||
|
||||
// SupportsAsset whether or not the supplied asset is supported
|
||||
// by the exchange
|
||||
// SupportsAsset whether or not the supplied asset is supported by the exchange
|
||||
func (b *Base) SupportsAsset(a asset.Item) bool {
|
||||
_, ok := b.CurrencyPairs.Pairs[a]
|
||||
return ok
|
||||
return b.CurrencyPairs.IsAssetSupported(a)
|
||||
}
|
||||
|
||||
// PrintEnabledPairs prints the exchanges enabled asset pairs
|
||||
@@ -1082,12 +1046,10 @@ func (b *Base) StoreAssetPairFormat(a asset.Item, f currency.PairStore) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetGlobalPairsManager sets defined asset and pairs management system with
|
||||
// global formatting
|
||||
// SetGlobalPairsManager sets defined asset and pairs management system with global formatting
|
||||
func (b *Base) SetGlobalPairsManager(request, config *currency.PairFormat, assets ...asset.Item) error {
|
||||
if request == nil {
|
||||
return fmt.Errorf("%s cannot set pairs manager, request pair format not provided",
|
||||
b.Name)
|
||||
return fmt.Errorf("%s cannot set pairs manager, request pair format not provided", b.Name)
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
@@ -1119,10 +1081,10 @@ func (b *Base) SetGlobalPairsManager(request, config *currency.PairFormat, asset
|
||||
for i := range assets {
|
||||
if assets[i].String() == "" {
|
||||
b.CurrencyPairs.Pairs = nil
|
||||
return fmt.Errorf("%s cannot set pairs manager, asset is empty string",
|
||||
b.Name)
|
||||
return fmt.Errorf("%s cannot set pairs manager, asset is empty string", b.Name)
|
||||
}
|
||||
b.CurrencyPairs.Pairs[assets[i]] = new(currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[assets[i]].AssetEnabled = convert.BoolPtr(true)
|
||||
b.CurrencyPairs.Pairs[assets[i]].ConfigFormat = config
|
||||
b.CurrencyPairs.Pairs[assets[i]].RequestFormat = request
|
||||
}
|
||||
|
||||
@@ -696,56 +696,12 @@ func TestGetFeatures(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetPairFormat ensures that GetPairFormat delegates to PairsManager.GetFormat
|
||||
func TestGetPairFormat(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Test global formatting
|
||||
var b Base
|
||||
b.CurrencyPairs.UseGlobalFormat = true
|
||||
b.CurrencyPairs.ConfigFormat = ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
}
|
||||
b.CurrencyPairs.RequestFormat = ¤cy.PairFormat{
|
||||
Delimiter: "~",
|
||||
}
|
||||
pFmt, err := b.GetPairFormat(asset.Spot, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pFmt.Delimiter != "~" && !pFmt.Uppercase {
|
||||
t.Error("incorrect pair format values")
|
||||
}
|
||||
pFmt, err = b.GetPairFormat(asset.Spot, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pFmt.Delimiter != "" && pFmt.Uppercase {
|
||||
t.Error("incorrect pair format values")
|
||||
}
|
||||
|
||||
// Test individual asset pair store formatting
|
||||
b.CurrencyPairs.UseGlobalFormat = false
|
||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||
ConfigFormat: &pFmt,
|
||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/", Uppercase: true},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pFmt, err = b.GetPairFormat(asset.Spot, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pFmt.Delimiter != "" && pFmt.Uppercase {
|
||||
t.Error("incorrect pair format values")
|
||||
}
|
||||
pFmt, err = b.GetPairFormat(asset.Spot, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pFmt.Delimiter != "~" && !pFmt.Uppercase {
|
||||
t.Error("incorrect pair format values")
|
||||
}
|
||||
_, err := new(Base).GetPairFormat(asset.Spot, true)
|
||||
require.ErrorIs(t, err, asset.ErrNotSupported, "Must delegate to GetFormat and error")
|
||||
}
|
||||
|
||||
func TestGetPairs(t *testing.T) {
|
||||
@@ -778,6 +734,7 @@ func TestGetPairs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestFormatExchangeCurrencies exercises FormatExchangeCurrencies
|
||||
func TestFormatExchangeCurrencies(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -797,32 +754,18 @@ func TestFormatExchangeCurrencies(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
p1, err := currency.NewPairDelimiter("BTC_USD", "_")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p2, err := currency.NewPairDelimiter("LTC_BTC", "_")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var pairs = []currency.Pair{
|
||||
p1,
|
||||
p2,
|
||||
currency.NewPairWithDelimiter("BTC", "USD", "_"),
|
||||
currency.NewPairWithDelimiter("LTC", "BTC", "_"),
|
||||
}
|
||||
|
||||
actual, err := e.FormatExchangeCurrencies(pairs, asset.Spot)
|
||||
if err != nil {
|
||||
t.Errorf("Exchange TestFormatExchangeCurrencies error %s", err)
|
||||
}
|
||||
if expected := "btc~usd^ltc~btc"; actual != expected {
|
||||
t.Errorf("Exchange TestFormatExchangeCurrencies %s != %s",
|
||||
actual, expected)
|
||||
}
|
||||
got, err := e.FormatExchangeCurrencies(pairs, asset.Spot)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "btc~usd^ltc~btc", got)
|
||||
|
||||
_, err = e.FormatExchangeCurrencies(nil, asset.Spot)
|
||||
if err == nil {
|
||||
t.Error("nil pairs should return an error")
|
||||
}
|
||||
assert.ErrorContains(t, err, "returned empty string", err, "FormatExchangeCurrencies should error correctly")
|
||||
}
|
||||
|
||||
func TestFormatExchangeCurrency(t *testing.T) {
|
||||
@@ -1342,14 +1285,12 @@ func TestSupportsAsset(t *testing.T) {
|
||||
t.Parallel()
|
||||
var b Base
|
||||
b.CurrencyPairs.Pairs = map[asset.Item]*currency.PairStore{
|
||||
asset.Spot: {},
|
||||
}
|
||||
if !b.SupportsAsset(asset.Spot) {
|
||||
t.Error("spot should be supported")
|
||||
}
|
||||
if b.SupportsAsset(asset.Index) {
|
||||
t.Error("index shouldn't be supported")
|
||||
asset.Spot: {
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
},
|
||||
}
|
||||
assert.True(t, b.SupportsAsset(asset.Spot), "Spot should be supported")
|
||||
assert.False(t, b.SupportsAsset(asset.Index), "Index should not be supported")
|
||||
}
|
||||
|
||||
func TestPrintEnabledPairs(t *testing.T) {
|
||||
@@ -1494,58 +1435,36 @@ func TestStoreAssetPairFormat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetGlobalPairsManager(t *testing.T) {
|
||||
b := Base{
|
||||
Config: &config.Exchange{Name: "kitties"},
|
||||
}
|
||||
b := Base{Config: &config.Exchange{Name: "kitties"}}
|
||||
|
||||
err := b.SetGlobalPairsManager(nil, nil, asset.Empty)
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
assert.ErrorContains(t, err, "cannot set pairs manager, request pair format not provided")
|
||||
|
||||
err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true}, nil, asset.Empty)
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
assert.ErrorContains(t, err, "cannot set pairs manager, config pair format not provided")
|
||||
|
||||
err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true},
|
||||
¤cy.PairFormat{Uppercase: true})
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true}, ¤cy.PairFormat{Uppercase: true})
|
||||
assert.ErrorContains(t, err, " cannot set pairs manager, no assets provided")
|
||||
|
||||
err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true},
|
||||
¤cy.PairFormat{Uppercase: true}, asset.Empty)
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true}, ¤cy.PairFormat{Uppercase: true}, asset.Empty)
|
||||
assert.ErrorContains(t, err, " cannot set global pairs manager config pair format requires delimiter for assets")
|
||||
|
||||
err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true},
|
||||
¤cy.PairFormat{Uppercase: true},
|
||||
asset.Spot,
|
||||
asset.Binary)
|
||||
if !errors.Is(err, errConfigPairFormatRequiresDelimiter) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, errConfigPairFormatRequiresDelimiter)
|
||||
}
|
||||
assert.ErrorIs(t, err, errConfigPairFormatRequiresDelimiter)
|
||||
|
||||
err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true},
|
||||
¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
||||
asset.Spot,
|
||||
asset.Binary)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true}, ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}, asset.Spot, asset.Binary)
|
||||
require.NoError(t, err, "SetGlobalPairsManager must not error")
|
||||
|
||||
if !b.SupportsAsset(asset.Binary) || !b.SupportsAsset(asset.Spot) {
|
||||
t.Fatal("global pairs manager not set correctly")
|
||||
}
|
||||
assert.True(t, b.SupportsAsset(asset.Binary), "Pairs Manager must support Binary")
|
||||
assert.True(t, b.SupportsAsset(asset.Spot), "Pairs Manager must support Spot")
|
||||
|
||||
err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true},
|
||||
¤cy.PairFormat{Uppercase: true}, asset.Spot, asset.Binary)
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true}, ¤cy.PairFormat{Uppercase: true}, asset.Spot, asset.Binary)
|
||||
assert.ErrorIs(t, err, errConfigPairFormatRequiresDelimiter, "SetGlobalPairsManager should error correctly")
|
||||
}
|
||||
|
||||
func Test_FormatExchangeKlineInterval(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -2366,9 +2285,7 @@ func TestGetKlineRequest(t *testing.T) {
|
||||
b.Features.Enabled.Kline.Intervals = kline.DeployExchangeIntervals(kline.IntervalCapacity{Interval: kline.OneMin})
|
||||
b.Features.Enabled.Kline.GlobalResultLimit = 1439
|
||||
_, err = b.GetKlineRequest(pair, asset.Spot, kline.OneHour, time.Time{}, time.Time{}, false)
|
||||
if !errors.Is(err, errAssetRequestFormatIsNil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, errAssetRequestFormatIsNil)
|
||||
}
|
||||
assert.ErrorIs(t, err, currency.ErrPairFormatIsNil, "GetKlineRequest should return Format is Nil")
|
||||
|
||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
@@ -2533,9 +2450,7 @@ func TestGetKlineExtendedRequest(t *testing.T) {
|
||||
}
|
||||
|
||||
_, err = b.GetKlineExtendedRequest(pair, asset.Spot, kline.OneHour, start, end)
|
||||
if !errors.Is(err, errAssetRequestFormatIsNil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, errAssetRequestFormatIsNil)
|
||||
}
|
||||
assert.ErrorIs(t, err, currency.ErrPairFormatIsNil, "GetKlineExtendedRequest should error correctly")
|
||||
|
||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
|
||||
@@ -3753,8 +3753,12 @@ func (g *Gateio) IsValidPairString(currencyPair string) bool {
|
||||
if len(currencyPair) < 3 {
|
||||
return false
|
||||
}
|
||||
if strings.Contains(currencyPair, g.CurrencyPairs.RequestFormat.Delimiter) {
|
||||
result := strings.Split(currencyPair, g.CurrencyPairs.RequestFormat.Delimiter)
|
||||
pf, err := g.CurrencyPairs.GetFormat(asset.Spot, true)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if strings.Contains(currencyPair, pf.Delimiter) {
|
||||
result := strings.Split(currencyPair, pf.Delimiter)
|
||||
return len(result) >= 2
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -130,31 +130,28 @@ func TestUpdateTicker(t *testing.T) {
|
||||
|
||||
func TestUpdateTickers(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")
|
||||
testexch.UpdatePairsOnce(t, k)
|
||||
err := k.UpdateTickers(context.Background(), asset.Spot)
|
||||
require.NoError(t, err, "UpdateTickers must not error")
|
||||
ap, err := k.GetAvailablePairs(asset.Spot)
|
||||
require.NoError(t, err)
|
||||
err = k.CurrencyPairs.StorePairs(asset.Spot, ap, true)
|
||||
require.NoError(t, err)
|
||||
err = k.UpdateTickers(context.Background(), asset.Spot)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err, "GetAvailablePairs must not error")
|
||||
for i := range ap {
|
||||
_, err = ticker.GetTicker(k.Name, ap[i], asset.Spot)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err, "GetTicker must not error")
|
||||
}
|
||||
|
||||
ap, err = k.GetAvailablePairs(asset.Futures)
|
||||
require.NoError(t, err)
|
||||
err = k.CurrencyPairs.StorePairs(asset.Futures, ap, true)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err, "GetAvailablePairs must not error")
|
||||
err = k.UpdateTickers(context.Background(), asset.Futures)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err, "UpdateTickers must not error")
|
||||
for i := range ap {
|
||||
_, err = ticker.GetTicker(k.Name, ap[i], asset.Futures)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err, "GetTicker must not error")
|
||||
}
|
||||
|
||||
err = k.UpdateTickers(context.Background(), asset.Index)
|
||||
assert.ErrorIs(t, err, asset.ErrNotSupported)
|
||||
assert.ErrorIs(t, err, asset.ErrNotSupported, "UpdateTickers should error correctly on Index asset")
|
||||
}
|
||||
|
||||
func TestUpdateOrderbook(t *testing.T) {
|
||||
@@ -1827,73 +1824,68 @@ func TestWsOwnTrades(t *testing.T) {
|
||||
|
||||
func TestWsOpenOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
n := new(Kraken)
|
||||
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")
|
||||
testexch.UpdatePairsOnce(t, k)
|
||||
sharedtestvalues.TestFixtureToDataHandler(t, k, n, "testdata/wsOpenTrades.json", n.wsHandleData)
|
||||
seen := 0
|
||||
for reading := true; reading; {
|
||||
select {
|
||||
default:
|
||||
reading = false
|
||||
case resp := <-n.Websocket.DataHandler:
|
||||
seen++
|
||||
switch v := resp.(type) {
|
||||
case *order.Detail:
|
||||
switch seen {
|
||||
case 1:
|
||||
assert.Equal(t, "OGTT3Y-C6I3P-XRI6HR", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Limit, v.Type, "order type")
|
||||
assert.Equal(t, order.Sell, v.Side, "order side")
|
||||
assert.Equal(t, order.Open, v.Status, "order status")
|
||||
assert.Equal(t, 34.5, v.Price, "price")
|
||||
assert.Equal(t, 10.00345345, v.Amount, "amount")
|
||||
case 2:
|
||||
assert.Equal(t, "OKB55A-UEMMN-YUXM2A", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Market, v.Type, "order type")
|
||||
assert.Equal(t, order.Buy, v.Side, "order side")
|
||||
assert.Equal(t, order.Pending, v.Status, "order status")
|
||||
assert.Equal(t, 0.0, v.Price, "price")
|
||||
assert.Equal(t, 0.0001, v.Amount, "amount")
|
||||
assert.Equal(t, time.UnixMicro(1692851641361371), v.Date, "Date")
|
||||
case 3:
|
||||
assert.Equal(t, "OKB55A-UEMMN-YUXM2A", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Open, v.Status, "order status")
|
||||
case 4:
|
||||
assert.Equal(t, "OKB55A-UEMMN-YUXM2A", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.UnknownStatus, v.Status, "order status")
|
||||
assert.Equal(t, 26425.2, v.AverageExecutedPrice, "AverageExecutedPrice")
|
||||
assert.Equal(t, 0.0001, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 0.0, v.RemainingAmount, "RemainingAmount") // Not in the message; Testing regression to bad derivation
|
||||
assert.Equal(t, 0.00687, v.Fee, "Fee")
|
||||
case 5:
|
||||
assert.Equal(t, "OKB55A-UEMMN-YUXM2A", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Closed, v.Status, "order status")
|
||||
assert.Equal(t, 0.0001, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 26425.2, v.AverageExecutedPrice, "AverageExecutedPrice")
|
||||
assert.Equal(t, 0.00687, v.Fee, "Fee")
|
||||
assert.Equal(t, time.UnixMicro(1692851641361447), v.LastUpdated, "LastUpdated")
|
||||
case 6:
|
||||
assert.Equal(t, "OGTT3Y-C6I3P-XRI6HR", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.UnknownStatus, v.Status, "order status")
|
||||
assert.Equal(t, 10.00345345, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 0.001, v.Fee, "Fee")
|
||||
assert.Equal(t, 34.5, v.AverageExecutedPrice, "AverageExecutedPrice")
|
||||
case 7:
|
||||
assert.Equal(t, "OGTT3Y-C6I3P-XRI6HR", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Closed, v.Status, "order status")
|
||||
assert.Equal(t, time.UnixMicro(1692675961789052), v.LastUpdated, "LastUpdated")
|
||||
assert.Equal(t, 10.00345345, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 0.001, v.Fee, "Fee")
|
||||
assert.Equal(t, 34.5, v.AverageExecutedPrice, "AverageExecutedPrice")
|
||||
reading = false
|
||||
}
|
||||
default:
|
||||
t.Errorf("Unexpected type in DataHandler: %T (%s)", v, v)
|
||||
testexch.FixtureToDataHandler(t, "testdata/wsOpenTrades.json", k.wsHandleData)
|
||||
close(k.Websocket.DataHandler)
|
||||
assert.Len(t, k.Websocket.DataHandler, 7, "Should see 7 orders")
|
||||
for resp := range k.Websocket.DataHandler {
|
||||
switch v := resp.(type) {
|
||||
case *order.Detail:
|
||||
switch len(k.Websocket.DataHandler) {
|
||||
case 6:
|
||||
assert.Equal(t, "OGTT3Y-C6I3P-XRI6HR", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Limit, v.Type, "order type")
|
||||
assert.Equal(t, order.Sell, v.Side, "order side")
|
||||
assert.Equal(t, order.Open, v.Status, "order status")
|
||||
assert.Equal(t, 34.5, v.Price, "price")
|
||||
assert.Equal(t, 10.00345345, v.Amount, "amount")
|
||||
case 5:
|
||||
assert.Equal(t, "OKB55A-UEMMN-YUXM2A", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Market, v.Type, "order type")
|
||||
assert.Equal(t, order.Buy, v.Side, "order side")
|
||||
assert.Equal(t, order.Pending, v.Status, "order status")
|
||||
assert.Equal(t, 0.0, v.Price, "price")
|
||||
assert.Equal(t, 0.0001, v.Amount, "amount")
|
||||
assert.Equal(t, time.UnixMicro(1692851641361371), v.Date, "Date")
|
||||
case 4:
|
||||
assert.Equal(t, "OKB55A-UEMMN-YUXM2A", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Open, v.Status, "order status")
|
||||
case 3:
|
||||
assert.Equal(t, "OKB55A-UEMMN-YUXM2A", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.UnknownStatus, v.Status, "order status")
|
||||
assert.Equal(t, 26425.2, v.AverageExecutedPrice, "AverageExecutedPrice")
|
||||
assert.Equal(t, 0.0001, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 0.0, v.RemainingAmount, "RemainingAmount") // Not in the message; Testing regression to bad derivation
|
||||
assert.Equal(t, 0.00687, v.Fee, "Fee")
|
||||
case 2:
|
||||
assert.Equal(t, "OKB55A-UEMMN-YUXM2A", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Closed, v.Status, "order status")
|
||||
assert.Equal(t, 0.0001, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 26425.2, v.AverageExecutedPrice, "AverageExecutedPrice")
|
||||
assert.Equal(t, 0.00687, v.Fee, "Fee")
|
||||
assert.Equal(t, time.UnixMicro(1692851641361447), v.LastUpdated, "LastUpdated")
|
||||
case 1:
|
||||
assert.Equal(t, "OGTT3Y-C6I3P-XRI6HR", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.UnknownStatus, v.Status, "order status")
|
||||
assert.Equal(t, 10.00345345, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 0.001, v.Fee, "Fee")
|
||||
assert.Equal(t, 34.5, v.AverageExecutedPrice, "AverageExecutedPrice")
|
||||
case 0:
|
||||
assert.Equal(t, "OGTT3Y-C6I3P-XRI6HR", v.OrderID, "OrderID")
|
||||
assert.Equal(t, order.Closed, v.Status, "order status")
|
||||
assert.Equal(t, time.UnixMicro(1692675961789052), v.LastUpdated, "LastUpdated")
|
||||
assert.Equal(t, 10.00345345, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 0.001, v.Fee, "Fee")
|
||||
assert.Equal(t, 34.5, v.AverageExecutedPrice, "AverageExecutedPrice")
|
||||
}
|
||||
case error:
|
||||
t.Error(v)
|
||||
default:
|
||||
t.Errorf("Unexpected type in DataHandler: %T (%s)", v, v)
|
||||
}
|
||||
}
|
||||
|
||||
assert.Equal(t, 7, seen, "number of DataHandler emissions")
|
||||
}
|
||||
|
||||
func TestWsAddOrderJSON(t *testing.T) {
|
||||
|
||||
@@ -1988,8 +1988,9 @@ func TestGetAuthenticatedServersInstances(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPushData(t *testing.T) {
|
||||
n := new(Kucoin)
|
||||
sharedtestvalues.TestFixtureToDataHandler(t, ku, n, "testdata/wsHandleData.json", ku.wsHandleData)
|
||||
t.Parallel()
|
||||
ku := testInstance(t) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
testexch.FixtureToDataHandler(t, "testdata/wsHandleData.json", ku.wsHandleData)
|
||||
}
|
||||
|
||||
func verifySubs(tb testing.TB, subs []subscription.Subscription, a asset.Item, prefix string, expected ...string) {
|
||||
@@ -2049,14 +2050,10 @@ func TestGenerateDefaultSubscriptions(t *testing.T) {
|
||||
func TestGenerateAuthSubscriptions(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create a parallel safe Kucoin to mess with
|
||||
nu := new(Kucoin)
|
||||
nu.Base.Features = ku.Base.Features
|
||||
assert.NoError(t, nu.CurrencyPairs.Load(&ku.CurrencyPairs), "Loading Pairs should not error")
|
||||
nu.Websocket = sharedtestvalues.NewTestWebsocket()
|
||||
nu.Websocket.SetCanUseAuthenticatedEndpoints(true)
|
||||
ku := testInstance(t) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
ku.Websocket.SetCanUseAuthenticatedEndpoints(true)
|
||||
|
||||
subs, err := nu.GenerateDefaultSubscriptions()
|
||||
subs, err := ku.GenerateDefaultSubscriptions()
|
||||
assert.NoError(t, err, "GenerateDefaultSubscriptions with Auth should not error")
|
||||
assert.Len(t, subs, 24, "Should generate the correct number of subs when logged in")
|
||||
|
||||
@@ -2086,17 +2083,12 @@ func TestGenerateAuthSubscriptions(t *testing.T) {
|
||||
func TestGenerateCandleSubscription(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create a parallel safe Kucoin to mess with
|
||||
nu := new(Kucoin)
|
||||
nu.Base.Features = ku.Base.Features
|
||||
nu.Websocket = sharedtestvalues.NewTestWebsocket()
|
||||
assert.NoError(t, nu.CurrencyPairs.Load(&ku.CurrencyPairs), "Loading Pairs should not error")
|
||||
|
||||
nu.Features.Subscriptions = []*subscription.Subscription{
|
||||
ku := testInstance(t) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
ku.Features.Subscriptions = []*subscription.Subscription{
|
||||
{Channel: subscription.CandlesChannel, Interval: kline.FourHour},
|
||||
}
|
||||
|
||||
subs, err := nu.GenerateDefaultSubscriptions()
|
||||
subs, err := ku.GenerateDefaultSubscriptions()
|
||||
assert.NoError(t, err, "GenerateDefaultSubscriptions with Candles should not error")
|
||||
|
||||
assert.Len(t, subs, 6, "Should generate the correct number of subs for candles")
|
||||
@@ -2111,17 +2103,12 @@ func TestGenerateCandleSubscription(t *testing.T) {
|
||||
func TestGenerateMarketSubscription(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create a parallel safe Kucoin to mess with
|
||||
nu := new(Kucoin)
|
||||
nu.Base.Features = ku.Base.Features
|
||||
nu.Websocket = sharedtestvalues.NewTestWebsocket()
|
||||
assert.NoError(t, nu.CurrencyPairs.Load(&ku.CurrencyPairs), "Loading Pairs should not error")
|
||||
|
||||
nu.Features.Subscriptions = []*subscription.Subscription{
|
||||
ku := testInstance(t) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
ku.Features.Subscriptions = []*subscription.Subscription{
|
||||
{Channel: marketSnapshotChannel},
|
||||
}
|
||||
|
||||
subs, err := nu.GenerateDefaultSubscriptions()
|
||||
subs, err := ku.GenerateDefaultSubscriptions()
|
||||
assert.NoError(t, err, "GenerateDefaultSubscriptions with MarketSnapshot should not error")
|
||||
|
||||
assert.Len(t, subs, 7, "Should generate the correct number of subs for snapshot")
|
||||
@@ -2490,59 +2477,51 @@ func TestProcessOrderbook(t *testing.T) {
|
||||
|
||||
func TestProcessMarketSnapshot(t *testing.T) {
|
||||
t.Parallel()
|
||||
n := new(Kucoin)
|
||||
sharedtestvalues.TestFixtureToDataHandler(t, ku, n, "testdata/wsMarketSnapshot.json", n.wsHandleData)
|
||||
seen := 0
|
||||
ku := testInstance(t) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
testexch.FixtureToDataHandler(t, "testdata/wsMarketSnapshot.json", ku.wsHandleData)
|
||||
close(ku.Websocket.DataHandler)
|
||||
assert.Len(t, ku.Websocket.DataHandler, 4, "Should see 4 tickers")
|
||||
seenAssetTypes := map[asset.Item]int{}
|
||||
for reading := true; reading; {
|
||||
select {
|
||||
default:
|
||||
reading = false
|
||||
case resp := <-n.GetBase().Websocket.DataHandler:
|
||||
seen++
|
||||
switch v := resp.(type) {
|
||||
case *ticker.Price:
|
||||
switch seen {
|
||||
case 1:
|
||||
assert.Equal(t, asset.Margin, v.AssetType, "AssetType")
|
||||
assert.Equal(t, time.UnixMilli(1700555342007), v.LastUpdated, "datetime")
|
||||
assert.Equal(t, 0.004445, v.High, "high")
|
||||
assert.Equal(t, 0.004415, v.Last, "lastTradedPrice")
|
||||
assert.Equal(t, 0.004191, v.Low, "low")
|
||||
assert.Equal(t, currency.NewPairWithDelimiter("TRX", "BTC", "-"), v.Pair, "symbol")
|
||||
assert.Equal(t, 13097.3357, v.Volume, "volume")
|
||||
assert.Equal(t, 57.44552981, v.QuoteVolume, "volValue")
|
||||
case 2, 3:
|
||||
assert.Equal(t, time.UnixMilli(1700555340197), v.LastUpdated, "datetime")
|
||||
assert.Contains(t, []asset.Item{asset.Spot, asset.Margin}, v.AssetType, "AssetType is Spot or Margin")
|
||||
seenAssetTypes[v.AssetType]++
|
||||
assert.Equal(t, 1, seenAssetTypes[v.AssetType], "Each Asset Type is sent only once per unique snapshot")
|
||||
assert.Equal(t, 0.054846, v.High, "high")
|
||||
assert.Equal(t, 0.053778, v.Last, "lastTradedPrice")
|
||||
assert.Equal(t, 0.05364, v.Low, "low")
|
||||
assert.Equal(t, currency.NewPairWithDelimiter("ETH", "BTC", "-"), v.Pair, "symbol")
|
||||
assert.Equal(t, 2958.3139116, v.Volume, "volume")
|
||||
assert.Equal(t, 160.7847672784213, v.QuoteVolume, "volValue")
|
||||
case 4:
|
||||
assert.Equal(t, asset.Spot, v.AssetType, "AssetType")
|
||||
assert.Equal(t, time.UnixMilli(1700555342151), v.LastUpdated, "datetime")
|
||||
assert.Equal(t, 37750.0, v.High, "high")
|
||||
assert.Equal(t, 37366.8, v.Last, "lastTradedPrice")
|
||||
assert.Equal(t, 36700.0, v.Low, "low")
|
||||
assert.Equal(t, currency.NewPairWithDelimiter("BTC", "USDT", "-"), v.Pair, "symbol")
|
||||
assert.Equal(t, 2900.37846402, v.Volume, "volume")
|
||||
assert.Equal(t, 108210331.34015164, v.QuoteVolume, "volValue")
|
||||
default:
|
||||
t.Errorf("Got an unexpected *ticker.Price: %v", v)
|
||||
}
|
||||
case error:
|
||||
t.Error(v)
|
||||
default:
|
||||
t.Errorf("Got unexpected data: %T %v", v, v)
|
||||
for resp := range ku.Websocket.DataHandler {
|
||||
switch v := resp.(type) {
|
||||
case *ticker.Price:
|
||||
switch len(ku.Websocket.DataHandler) {
|
||||
case 3:
|
||||
assert.Equal(t, asset.Margin, v.AssetType, "AssetType")
|
||||
assert.Equal(t, time.UnixMilli(1700555342007), v.LastUpdated, "datetime")
|
||||
assert.Equal(t, 0.004445, v.High, "high")
|
||||
assert.Equal(t, 0.004415, v.Last, "lastTradedPrice")
|
||||
assert.Equal(t, 0.004191, v.Low, "low")
|
||||
assert.Equal(t, currency.NewPairWithDelimiter("TRX", "BTC", "-"), v.Pair, "symbol")
|
||||
assert.Equal(t, 13097.3357, v.Volume, "volume")
|
||||
assert.Equal(t, 57.44552981, v.QuoteVolume, "volValue")
|
||||
case 2, 1:
|
||||
assert.Equal(t, time.UnixMilli(1700555340197), v.LastUpdated, "datetime")
|
||||
assert.Contains(t, []asset.Item{asset.Spot, asset.Margin}, v.AssetType, "AssetType is Spot or Margin")
|
||||
seenAssetTypes[v.AssetType]++
|
||||
assert.Equal(t, 1, seenAssetTypes[v.AssetType], "Each Asset Type is sent only once per unique snapshot")
|
||||
assert.Equal(t, 0.054846, v.High, "high")
|
||||
assert.Equal(t, 0.053778, v.Last, "lastTradedPrice")
|
||||
assert.Equal(t, 0.05364, v.Low, "low")
|
||||
assert.Equal(t, currency.NewPairWithDelimiter("ETH", "BTC", "-"), v.Pair, "symbol")
|
||||
assert.Equal(t, 2958.3139116, v.Volume, "volume")
|
||||
assert.Equal(t, 160.7847672784213, v.QuoteVolume, "volValue")
|
||||
case 0:
|
||||
assert.Equal(t, asset.Spot, v.AssetType, "AssetType")
|
||||
assert.Equal(t, time.UnixMilli(1700555342151), v.LastUpdated, "datetime")
|
||||
assert.Equal(t, 37750.0, v.High, "high")
|
||||
assert.Equal(t, 37366.8, v.Last, "lastTradedPrice")
|
||||
assert.Equal(t, 36700.0, v.Low, "low")
|
||||
assert.Equal(t, currency.NewPairWithDelimiter("BTC", "USDT", "-"), v.Pair, "symbol")
|
||||
assert.Equal(t, 2900.37846402, v.Volume, "volume")
|
||||
assert.Equal(t, 108210331.34015164, v.QuoteVolume, "volValue")
|
||||
}
|
||||
case error:
|
||||
t.Error(v)
|
||||
default:
|
||||
t.Errorf("Got unexpected data: %T %v", v, v)
|
||||
}
|
||||
}
|
||||
assert.Equal(t, 4, seen, "Number of messages")
|
||||
}
|
||||
|
||||
func TestSubscribeMarketSnapshot(t *testing.T) {
|
||||
@@ -2735,16 +2714,16 @@ func TestUpdateOrderExecutionLimits(t *testing.T) {
|
||||
func TestGetOpenInterest(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
nu := new(Kucoin)
|
||||
require.NoError(t, testexch.Setup(nu), "Test exchange Setup must not error")
|
||||
_, err := nu.GetOpenInterest(context.Background(), key.PairAsset{
|
||||
ku := testInstance(t) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
|
||||
_, err := ku.GetOpenInterest(context.Background(), key.PairAsset{
|
||||
Base: currency.ETH.Item,
|
||||
Quote: currency.USDT.Item,
|
||||
Asset: asset.USDTMarginedFutures,
|
||||
})
|
||||
assert.ErrorIs(t, err, asset.ErrNotSupported)
|
||||
|
||||
resp, err := nu.GetOpenInterest(context.Background(), key.PairAsset{
|
||||
resp, err := ku.GetOpenInterest(context.Background(), key.PairAsset{
|
||||
Base: futuresTradablePair.Base.Item,
|
||||
Quote: futuresTradablePair.Quote.Item,
|
||||
Asset: asset.Futures,
|
||||
@@ -2753,8 +2732,8 @@ func TestGetOpenInterest(t *testing.T) {
|
||||
assert.NotEmpty(t, resp)
|
||||
|
||||
cp1 := currency.NewPair(currency.ETH, currency.USDTM)
|
||||
sharedtestvalues.SetupCurrencyPairsForExchangeAsset(t, nu, asset.Futures, cp1)
|
||||
resp, err = nu.GetOpenInterest(context.Background(),
|
||||
sharedtestvalues.SetupCurrencyPairsForExchangeAsset(t, ku, asset.Futures, cp1)
|
||||
resp, err = ku.GetOpenInterest(context.Background(),
|
||||
key.PairAsset{
|
||||
Base: futuresTradablePair.Base.Item,
|
||||
Quote: futuresTradablePair.Quote.Item,
|
||||
@@ -2769,7 +2748,7 @@ func TestGetOpenInterest(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, resp)
|
||||
|
||||
resp, err = nu.GetOpenInterest(context.Background())
|
||||
resp, err = ku.GetOpenInterest(context.Background())
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, resp)
|
||||
}
|
||||
@@ -2786,3 +2765,15 @@ func TestGetCurrencyTradeURL(t *testing.T) {
|
||||
assert.NotEmpty(t, resp)
|
||||
}
|
||||
}
|
||||
|
||||
// testInstance returns a local Kucoin for isolated testing
|
||||
func testInstance(tb testing.TB) *Kucoin {
|
||||
tb.Helper()
|
||||
ku := new(Kucoin)
|
||||
require.NoError(tb, testexch.Setup(ku), "Test instance Setup must not error")
|
||||
ku.obm = &orderbookManager{
|
||||
state: make(map[currency.Code]map[currency.Code]map[asset.Item]*update),
|
||||
jobs: make(chan job, maxWSOrderbookJobs),
|
||||
}
|
||||
return ku
|
||||
}
|
||||
|
||||
@@ -3065,15 +3065,6 @@ func (ok *Okx) GetUnderlying(pair currency.Pair, a asset.Item) (string, error) {
|
||||
return pair.Base.String() + format.Delimiter + pair.Quote.String(), nil
|
||||
}
|
||||
|
||||
// GetPairFromInstrumentID returns a currency pair give an instrument ID and asset Item, which represents the instrument type.
|
||||
func (ok *Okx) GetPairFromInstrumentID(instrumentID string) (currency.Pair, error) {
|
||||
codes := strings.Split(instrumentID, ok.CurrencyPairs.RequestFormat.Delimiter)
|
||||
if len(codes) >= 2 {
|
||||
instrumentID = codes[0] + ok.CurrencyPairs.RequestFormat.Delimiter + strings.Join(codes[1:], ok.CurrencyPairs.RequestFormat.Delimiter)
|
||||
}
|
||||
return currency.NewPairFromString(instrumentID)
|
||||
}
|
||||
|
||||
// GetOrderBookDepth returns the recent order asks and bids before specified timestamp.
|
||||
func (ok *Okx) GetOrderBookDepth(ctx context.Context, instrumentID string, depth int64) (*OrderBookResponse, error) {
|
||||
params := url.Values{}
|
||||
@@ -4320,11 +4311,15 @@ func (ok *Okx) GetAssetsFromInstrumentTypeOrID(instType, instrumentID string) ([
|
||||
if instrumentID == "" {
|
||||
return nil, fmt.Errorf("%w instrumentID", errEmptyArgument)
|
||||
}
|
||||
splitSymbol := strings.Split(instrumentID, ok.CurrencyPairs.RequestFormat.Delimiter)
|
||||
pf, err := ok.CurrencyPairs.GetFormat(asset.Spot, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
splitSymbol := strings.Split(instrumentID, pf.Delimiter)
|
||||
if len(splitSymbol) <= 1 {
|
||||
return nil, fmt.Errorf("%w %v", currency.ErrCurrencyNotSupported, instrumentID)
|
||||
}
|
||||
pair, err := currency.NewPairDelimiter(instrumentID, ok.CurrencyPairs.RequestFormat.Delimiter)
|
||||
pair, err := currency.NewPairDelimiter(instrumentID, pf.Delimiter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2206,24 +2206,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPairFromInstrumentID(t *testing.T) {
|
||||
t.Parallel()
|
||||
instruments := []string{
|
||||
"BTC-USDT",
|
||||
"BTC-USDT-SWAP",
|
||||
"BTC-USDT-ER33234",
|
||||
}
|
||||
if _, err := ok.GetPairFromInstrumentID(instruments[0]); err != nil {
|
||||
t.Error("Okx GetPairFromInstrumentID() error", err)
|
||||
}
|
||||
if _, ere := ok.GetPairFromInstrumentID(instruments[1]); ere != nil {
|
||||
t.Error("Okx GetPairFromInstrumentID() error", ere)
|
||||
}
|
||||
if _, erf := ok.GetPairFromInstrumentID(instruments[2]); erf != nil {
|
||||
t.Error("Okx GetPairFromInstrumentID() error", erf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
|
||||
@@ -2534,68 +2516,63 @@ func TestBalanceAndPosition(t *testing.T) {
|
||||
|
||||
func TestOrderPushData(t *testing.T) {
|
||||
t.Parallel()
|
||||
n := new(Okx)
|
||||
sharedtestvalues.TestFixtureToDataHandler(t, ok, n, "testdata/wsOrders.json", n.WsHandleData)
|
||||
seen := 0
|
||||
for reading := true; reading; {
|
||||
select {
|
||||
default:
|
||||
reading = false
|
||||
case resp := <-n.GetBase().Websocket.DataHandler:
|
||||
seen++
|
||||
switch v := resp.(type) {
|
||||
case *order.Detail:
|
||||
switch seen {
|
||||
case 1:
|
||||
assert.Equal(t, "452197707845865472", v.OrderID, "OrderID")
|
||||
assert.Equal(t, "HamsterParty14", v.ClientOrderID, "ClientOrderID")
|
||||
assert.Equal(t, asset.Spot, v.AssetType, "AssetType")
|
||||
assert.Equal(t, order.Sell, v.Side, "Side")
|
||||
assert.Equal(t, order.Filled, v.Status, "Status")
|
||||
assert.Equal(t, order.Limit, v.Type, "Type")
|
||||
assert.Equal(t, currency.NewPairWithDelimiter("BTC", "USDT", "-"), v.Pair, "Pair")
|
||||
assert.Equal(t, 31527.1, v.AverageExecutedPrice, "AverageExecutedPrice")
|
||||
assert.Equal(t, time.UnixMilli(1654084334977), v.Date, "Date")
|
||||
assert.Equal(t, time.UnixMilli(1654084353263), v.CloseTime, "CloseTime")
|
||||
assert.Equal(t, 0.001, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.001, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 0.000, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 31527.1, v.Price, "Price")
|
||||
assert.Equal(t, 0.02522168, v.Fee, "Fee")
|
||||
assert.Equal(t, currency.USDT, v.FeeAsset, "FeeAsset")
|
||||
case 2:
|
||||
assert.Equal(t, "620258920632008725", v.OrderID, "OrderID")
|
||||
assert.Equal(t, asset.Spot, v.AssetType, "AssetType")
|
||||
assert.Equal(t, order.Market, v.Type, "Type")
|
||||
assert.Equal(t, order.Sell, v.Side, "Side")
|
||||
assert.Equal(t, order.Active, v.Status, "Status")
|
||||
assert.Equal(t, 0.0, v.Amount, "Amount should be 0 for a market sell")
|
||||
assert.Equal(t, 10.0, v.QuoteAmount, "QuoteAmount")
|
||||
case 3:
|
||||
assert.Equal(t, "620258920632008725", v.OrderID, "OrderID")
|
||||
assert.Equal(t, 10.0, v.QuoteAmount, "QuoteAmount")
|
||||
assert.Equal(t, 0.00038127046945832905, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.010000249968, v.Fee, "Fee")
|
||||
assert.Equal(t, 0.0, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038128, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, order.PartiallyFilled, v.Status, "Status")
|
||||
case 4:
|
||||
assert.Equal(t, "620258920632008725", v.OrderID, "OrderID")
|
||||
assert.Equal(t, 10.0, v.QuoteAmount, "QuoteAmount")
|
||||
assert.Equal(t, 0.010000249968, v.Fee, "Fee")
|
||||
assert.Equal(t, 0.0, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038128, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 0.00038128, v.Amount, "Amount should be derived because order filled")
|
||||
assert.Equal(t, order.Filled, v.Status, "Status")
|
||||
}
|
||||
case error:
|
||||
t.Error(v)
|
||||
default:
|
||||
t.Errorf("Got unexpected data: %T %v", v, v)
|
||||
ok := new(Okx) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
require.NoError(t, testexch.Setup(ok), "Test instance Setup must not error")
|
||||
testexch.FixtureToDataHandler(t, "testdata/wsOrders.json", ok.WsHandleData)
|
||||
close(ok.Websocket.DataHandler)
|
||||
assert.Len(t, ok.Websocket.DataHandler, 4, "Should see 4 orders")
|
||||
for resp := range ok.Websocket.DataHandler {
|
||||
switch v := resp.(type) {
|
||||
case *order.Detail:
|
||||
switch len(ok.Websocket.DataHandler) {
|
||||
case 3:
|
||||
assert.Equal(t, "452197707845865472", v.OrderID, "OrderID")
|
||||
assert.Equal(t, "HamsterParty14", v.ClientOrderID, "ClientOrderID")
|
||||
assert.Equal(t, asset.Spot, v.AssetType, "AssetType")
|
||||
assert.Equal(t, order.Sell, v.Side, "Side")
|
||||
assert.Equal(t, order.Filled, v.Status, "Status")
|
||||
assert.Equal(t, order.Limit, v.Type, "Type")
|
||||
assert.Equal(t, currency.NewPairWithDelimiter("BTC", "USDT", "-"), v.Pair, "Pair")
|
||||
assert.Equal(t, 31527.1, v.AverageExecutedPrice, "AverageExecutedPrice")
|
||||
assert.Equal(t, time.UnixMilli(1654084334977), v.Date, "Date")
|
||||
assert.Equal(t, time.UnixMilli(1654084353263), v.CloseTime, "CloseTime")
|
||||
assert.Equal(t, 0.001, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.001, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 0.000, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 31527.1, v.Price, "Price")
|
||||
assert.Equal(t, 0.02522168, v.Fee, "Fee")
|
||||
assert.Equal(t, currency.USDT, v.FeeAsset, "FeeAsset")
|
||||
case 2:
|
||||
assert.Equal(t, "620258920632008725", v.OrderID, "OrderID")
|
||||
assert.Equal(t, asset.Spot, v.AssetType, "AssetType")
|
||||
assert.Equal(t, order.Market, v.Type, "Type")
|
||||
assert.Equal(t, order.Sell, v.Side, "Side")
|
||||
assert.Equal(t, order.Active, v.Status, "Status")
|
||||
assert.Equal(t, 0.0, v.Amount, "Amount should be 0 for a market sell")
|
||||
assert.Equal(t, 10.0, v.QuoteAmount, "QuoteAmount")
|
||||
case 1:
|
||||
assert.Equal(t, "620258920632008725", v.OrderID, "OrderID")
|
||||
assert.Equal(t, 10.0, v.QuoteAmount, "QuoteAmount")
|
||||
assert.Equal(t, 0.00038127046945832905, v.Amount, "Amount")
|
||||
assert.Equal(t, 0.010000249968, v.Fee, "Fee")
|
||||
assert.Equal(t, 0.0, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038128, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, order.PartiallyFilled, v.Status, "Status")
|
||||
case 0:
|
||||
assert.Equal(t, "620258920632008725", v.OrderID, "OrderID")
|
||||
assert.Equal(t, 10.0, v.QuoteAmount, "QuoteAmount")
|
||||
assert.Equal(t, 0.010000249968, v.Fee, "Fee")
|
||||
assert.Equal(t, 0.0, v.RemainingAmount, "RemainingAmount")
|
||||
assert.Equal(t, 0.00038128, v.ExecutedAmount, "ExecutedAmount")
|
||||
assert.Equal(t, 0.00038128, v.Amount, "Amount should be derived because order filled")
|
||||
assert.Equal(t, order.Filled, v.Status, "Status")
|
||||
}
|
||||
case error:
|
||||
t.Error(v)
|
||||
default:
|
||||
t.Errorf("Got unexpected data: %T %v", v, v)
|
||||
}
|
||||
}
|
||||
assert.Equal(t, 4, seen, "Saw 4 records")
|
||||
}
|
||||
|
||||
const algoOrdersPushDataJSON = `{"arg": {"channel": "orders-algo","uid": "77982378738415879","instType": "FUTURES","instId": "BTC-USD-200329"},"data": [{"instType": "FUTURES","instId": "BTC-USD-200329","ordId": "312269865356374016","ccy": "BTC","algoId": "1234","px": "999","sz": "3","tdMode": "cross","tgtCcy": "","notionalUsd": "","ordType": "trigger","side": "buy","posSide": "long","state": "live","lever": "20","tpTriggerPx": "","tpTriggerPxType": "","tpOrdPx": "","slTriggerPx": "","slTriggerPxType": "","triggerPx": "99","triggerPxType": "last","ordPx": "12","actualSz": "","actualPx": "","tag": "adadadadad","actualSide": "","triggerTime": "1597026383085","cTime": "1597026383000"}]}`
|
||||
|
||||
@@ -688,7 +688,8 @@ func (ok *Okx) wsProcessIndexCandles(respRaw []byte) error {
|
||||
if len(response.Data) == 0 {
|
||||
return errNoCandlestickDataFound
|
||||
}
|
||||
pair, err := ok.GetPairFromInstrumentID(response.Argument.InstrumentID)
|
||||
|
||||
pair, err := currency.NewPairFromString(response.Argument.InstrumentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -750,7 +751,7 @@ func (ok *Okx) wsProcessOrderbook5(data []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
pair, err := ok.GetPairFromInstrumentID(resp.Argument.InstrumentID)
|
||||
pair, err := currency.NewPairFromString(resp.Argument.InstrumentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -809,13 +810,11 @@ func (ok *Okx) wsProcessOrderBooks(data []byte) error {
|
||||
response.Action != wsOrderbookSnapshot {
|
||||
return errors.New("invalid order book action")
|
||||
}
|
||||
var pair currency.Pair
|
||||
var assets []asset.Item
|
||||
assets, err = ok.GetAssetsFromInstrumentTypeOrID(response.Argument.InstrumentType, response.Argument.InstrumentID)
|
||||
assets, err := ok.GetAssetsFromInstrumentTypeOrID(response.Argument.InstrumentType, response.Argument.InstrumentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pair, err = ok.GetPairFromInstrumentID(response.Argument.InstrumentID)
|
||||
pair, err := currency.NewPairFromString(response.Argument.InstrumentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1062,8 +1061,7 @@ func (ok *Okx) wsProcessTrades(data []byte) error {
|
||||
}
|
||||
trades := make([]trade.Data, 0, len(response.Data)*len(assets))
|
||||
for i := range response.Data {
|
||||
var pair currency.Pair
|
||||
pair, err = ok.GetPairFromInstrumentID(response.Data[i].InstrumentID)
|
||||
pair, err := currency.NewPairFromString(response.Data[i].InstrumentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1086,7 +1084,6 @@ func (ok *Okx) wsProcessTrades(data []byte) error {
|
||||
// wsProcessOrders handles websocket order push data responses.
|
||||
func (ok *Okx) wsProcessOrders(respRaw []byte) error {
|
||||
var response WsOrderResponse
|
||||
var pair currency.Pair
|
||||
err := json.Unmarshal(respRaw, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1109,7 +1106,7 @@ func (ok *Okx) wsProcessOrders(respRaw []byte) error {
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
pair, err = ok.GetPairFromInstrumentID(response.Data[x].InstrumentID)
|
||||
pair, err := currency.NewPairFromString(response.Data[x].InstrumentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1189,7 +1186,7 @@ func (ok *Okx) wsProcessCandles(respRaw []byte) error {
|
||||
if len(response.Data) == 0 {
|
||||
return errNoCandlestickDataFound
|
||||
}
|
||||
pair, err := ok.GetPairFromInstrumentID(response.Argument.InstrumentID)
|
||||
pair, err := currency.NewPairFromString(response.Argument.InstrumentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1260,8 +1257,7 @@ func (ok *Okx) wsProcessTickers(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var c currency.Pair
|
||||
c, err = ok.GetPairFromInstrumentID(response.Data[i].InstrumentID)
|
||||
c, err := currency.NewPairFromString(response.Data[i].InstrumentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -259,9 +259,13 @@ func (ok *Okx) FetchTradablePairs(ctx context.Context, a asset.Item) (currency.P
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pf, err := ok.CurrencyPairs.GetFormat(a, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pairs := make([]currency.Pair, len(insts))
|
||||
for x := range insts {
|
||||
pairs[x], err = currency.NewPairDelimiter(insts[x].InstrumentID, ok.CurrencyPairs.ConfigFormat.Delimiter)
|
||||
pairs[x], err = currency.NewPairDelimiter(insts[x].InstrumentID, pf.Delimiter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -378,7 +382,7 @@ func (ok *Okx) UpdateTickers(ctx context.Context, assetType asset.Item) error {
|
||||
}
|
||||
|
||||
for y := range ticks {
|
||||
pair, err := ok.GetPairFromInstrumentID(ticks[y].InstrumentID)
|
||||
pair, err := currency.NewPairFromString(ticks[y].InstrumentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1192,8 +1196,7 @@ allOrders:
|
||||
break allOrders
|
||||
}
|
||||
orderSide := orderList[i].Side
|
||||
var pair currency.Pair
|
||||
pair, err = ok.GetPairFromInstrumentID(orderList[i].InstrumentID)
|
||||
pair, err := currency.NewPairFromString(orderList[i].InstrumentID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1286,8 +1289,7 @@ allOrders:
|
||||
// reached end of orders to crawl
|
||||
break allOrders
|
||||
}
|
||||
var pair currency.Pair
|
||||
pair, err = ok.GetPairFromInstrumentID(orderList[i].InstrumentID)
|
||||
pair, err := currency.NewPairFromString(orderList[i].InstrumentID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package sharedtestvalues
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -9,15 +8,14 @@ import (
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
|
||||
)
|
||||
|
||||
@@ -64,6 +62,7 @@ func NewTestWebsocket() *stream.Websocket {
|
||||
Subscribe: make(chan []subscription.Subscription, 10),
|
||||
Unsubscribe: make(chan []subscription.Subscription, 10),
|
||||
Match: stream.NewMatch(),
|
||||
Orderbook: buffer.Orderbook{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,38 +153,6 @@ func ForceFileStandard(t *testing.T, pattern string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TestFixtureToDataHandler takes a new empty exchange and configures a new websocket handler for it, and squirts the json path contents to it
|
||||
// It accepts a reader function, which is probably e.wsHandleData but could be anything
|
||||
func TestFixtureToDataHandler(t *testing.T, seed, e exchange.IBotExchange, fixturePath string, reader func([]byte) error) {
|
||||
t.Helper()
|
||||
b := e.GetBase()
|
||||
seedBase := seed.GetBase()
|
||||
|
||||
err := b.CurrencyPairs.Load(&seedBase.CurrencyPairs)
|
||||
assert.NoError(t, err, "Loading currency pairs should not error")
|
||||
|
||||
b.Name = "fixture"
|
||||
b.Websocket = &stream.Websocket{
|
||||
Wg: new(sync.WaitGroup),
|
||||
DataHandler: make(chan interface{}, 128),
|
||||
}
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
|
||||
fixture, err := os.Open(fixturePath)
|
||||
assert.NoError(t, err, "Opening fixture '%s' should not error", fixturePath)
|
||||
defer func() {
|
||||
assert.NoError(t, fixture.Close(), "Closing the fixture file should not error")
|
||||
}()
|
||||
|
||||
s := bufio.NewScanner(fixture)
|
||||
for s.Scan() {
|
||||
msg := s.Bytes()
|
||||
err := reader(msg)
|
||||
assert.NoErrorf(t, err, "Fixture message should not error:\n%s", msg)
|
||||
}
|
||||
assert.NoError(t, s.Err(), "Fixture Scanner should not error")
|
||||
}
|
||||
|
||||
// SetupCurrencyPairsForExchangeAsset enables an asset for an exchange
|
||||
// and adds the currency pair(s) to the available and enabled list of existing pairs
|
||||
// if it is already enabled or part of the pairs, no error is raised
|
||||
|
||||
Reference in New Issue
Block a user