diff --git a/cmd/exchange_template/wrapper_file.tmpl b/cmd/exchange_template/wrapper_file.tmpl index 68e1639ca31..c1c4e7e8888 100644 --- a/cmd/exchange_template/wrapper_file.tmpl +++ b/cmd/exchange_template/wrapper_file.tmpl @@ -55,22 +55,24 @@ func ({{.Variable}} *{{.CapitalName}}) SetDefaults() { // can use this example below: fmt1 := currency.PairStore{ + AssetEnabled: true, RequestFormat: ¤cy.PairFormat{Uppercase: true}, ConfigFormat: ¤cy.PairFormat{Uppercase: true}, } fmt2 := currency.PairStore{ + AssetEnabled: true, RequestFormat: ¤cy.PairFormat{Uppercase: true}, ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: ":"}, } - err = {{.Variable}}.StoreAssetPairFormat(asset.Spot, fmt1) + err = {{.Variable}}.StoreAssetPairStore(asset.Spot, fmt1) if err != nil { - log.Errorln(log.ExchangeSys, err) + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", {{.Variable}}.Name, asset.Spot, err) } - err = {{.Variable}}.StoreAssetPairFormat(asset.Margin, fmt2) + err = {{.Variable}}.StoreAssetPairStore(asset.Margin, fmt2) if err != nil { - log.Errorln(log.ExchangeSys, err) + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", {{.Variable}}.Name, asset.Margin, err) } // Fill out the capabilities/features that the exchange supports diff --git a/docs/ADD_NEW_EXCHANGE.md b/docs/ADD_NEW_EXCHANGE.md index 41e5712d192..f90d260f1f3 100644 --- a/docs/ADD_NEW_EXCHANGE.md +++ b/docs/ADD_NEW_EXCHANGE.md @@ -156,6 +156,7 @@ Similar to the configs, spot support is inbuilt but other asset types will need ```go spot := currency.PairStore{ + AssetEnabled: true, RequestFormat: ¤cy.PairFormat{ Uppercase: true, Delimiter: "/", @@ -166,6 +167,7 @@ Similar to the configs, spot support is inbuilt but other asset types will need }, } futures := currency.PairStore{ + AssetEnabled: true, RequestFormat: ¤cy.PairFormat{ Uppercase: true, Delimiter: "-", @@ -176,14 +178,14 @@ Similar to the configs, spot support is inbuilt but other asset types will need }, } - err := f.StoreAssetPairFormat(asset.Spot, spot) + err := f.StoreAssetPairStore(asset.Spot, spot) if err != nil { - log.Errorln(log.ExchangeSys, err) + log.Errorf(log.ExchangeSys, "%s error storing `spot` default asset formats: %s", bi.Name, err) } - err = f.StoreAssetPairFormat(asset.Futures, futures) + err = f.StoreAssetPairStore(asset.Futures, futures) if err != nil { - log.Errorln(log.ExchangeSys, err) + log.Errorf(log.ExchangeSys, "%s error storing `futures` default asset formats: %s", bi.Name, err) } ``` diff --git a/engine/rpcserver_test.go b/engine/rpcserver_test.go index 1f687e7a6b2..9661d6a2d3e 100644 --- a/engine/rpcserver_test.go +++ b/engine/rpcserver_test.go @@ -1548,6 +1548,7 @@ func TestCheckVars(t *testing.T) { for _, a := range []asset.Item{asset.Spot, asset.Margin, asset.CoinMarginedFutures, asset.USDTMarginedFutures} { fmt := currency.PairStore{ + AssetEnabled: true, RequestFormat: ¤cy.PairFormat{Uppercase: true}, ConfigFormat: ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}, } @@ -1558,8 +1559,7 @@ func TestCheckVars(t *testing.T) { case asset.USDTMarginedFutures: fmt.ConfigFormat = ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter} } - require.NoError(t, b.StoreAssetPairFormat(a, fmt), "StoreAssetPairFormat must not error") - require.NoError(t, b.CurrencyPairs.SetAssetEnabled(a, true), "SetAssetEnabled must not error") + require.NoError(t, b.StoreAssetPairStore(a, fmt), "StoreAssetPairStore must not error") } err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT)) diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 475f274814d..87082747d7a 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -36,6 +36,29 @@ import ( "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) +var defaultAssetPairStores = map[asset.Item]currency.PairStore{ + asset.Spot: { + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true}, + ConfigFormat: ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}, + }, + asset.Margin: { + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true}, + ConfigFormat: ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}, + }, + asset.CoinMarginedFutures: { + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}, + ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}, + }, + asset.USDTMarginedFutures: { + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true}, + ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}, + }, +} + // SetDefaults sets the basic defaults for Binance func (b *Binance) SetDefaults() { b.Name = "Binance" @@ -45,60 +68,18 @@ func (b *Binance) SetDefaults() { b.API.CredentialsValidator.RequiresSecret = true b.SetValues() - fmt1 := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{Uppercase: true}, - ConfigFormat: ¤cy.PairFormat{ - Delimiter: currency.DashDelimiter, - Uppercase: true, - }, - } - coinFutures := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{ - Uppercase: true, - Delimiter: currency.UnderscoreDelimiter, - }, - ConfigFormat: ¤cy.PairFormat{ - Uppercase: true, - Delimiter: currency.UnderscoreDelimiter, - }, - } - usdtFutures := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{ - Uppercase: true, - }, - ConfigFormat: ¤cy.PairFormat{ - Uppercase: true, - Delimiter: currency.UnderscoreDelimiter, - }, - } - err := b.StoreAssetPairFormat(asset.Spot, fmt1) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - err = b.StoreAssetPairFormat(asset.Margin, fmt1) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - err = b.DisableAssetWebsocketSupport(asset.Margin) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - err = b.StoreAssetPairFormat(asset.CoinMarginedFutures, coinFutures) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - err = b.DisableAssetWebsocketSupport(asset.CoinMarginedFutures) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - err = b.StoreAssetPairFormat(asset.USDTMarginedFutures, usdtFutures) - if err != nil { - log.Errorln(log.ExchangeSys, err) + for a, ps := range defaultAssetPairStores { + if err := b.StoreAssetPairStore(a, ps); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", b.Name, a, err) + } } - err = b.DisableAssetWebsocketSupport(asset.USDTMarginedFutures) - if err != nil { - log.Errorln(log.ExchangeSys, err) + + for _, a := range []asset.Item{asset.Margin, asset.CoinMarginedFutures, asset.USDTMarginedFutures} { + if err := b.DisableAssetWebsocketSupport(a); err != nil { + log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", b.Name, a, err) + } } + b.Features = exchange.Features{ Supports: exchange.FeaturesSupported{ REST: true, @@ -196,6 +177,7 @@ func (b *Binance) SetDefaults() { }, } + var err error b.Requester, err = request.New(b.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), request.WithLimiter(GetRateLimits())) diff --git a/exchanges/binanceus/binanceus_wrapper.go b/exchanges/binanceus/binanceus_wrapper.go index d3992d4e73e..fe107c9281a 100644 --- a/exchanges/binanceus/binanceus_wrapper.go +++ b/exchanges/binanceus/binanceus_wrapper.go @@ -40,15 +40,15 @@ func (bi *Binanceus) SetDefaults() { bi.SetValues() fmt1 := currency.PairStore{ + AssetEnabled: true, RequestFormat: ¤cy.PairFormat{Uppercase: true}, ConfigFormat: ¤cy.PairFormat{ Delimiter: currency.DashDelimiter, Uppercase: true, }, } - err := bi.StoreAssetPairFormat(asset.Spot, fmt1) - if err != nil { - log.Errorln(log.ExchangeSys, err) + if err := bi.StoreAssetPairStore(asset.Spot, fmt1); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing `spot` default asset formats: %s", bi.Name, err) } bi.Features = exchange.Features{ @@ -122,6 +122,8 @@ func (bi *Binanceus) SetDefaults() { }, }, } + + var err error bi.Requester, err = request.New(bi.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), request.WithLimiter(GetRateLimit())) diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go index 04cba828676..a1ad35281f1 100644 --- a/exchanges/bitfinex/bitfinex_wrapper.go +++ b/exchanges/bitfinex/bitfinex_wrapper.go @@ -41,33 +41,23 @@ func (b *Bitfinex) SetDefaults() { b.API.CredentialsValidator.RequiresKey = true b.API.CredentialsValidator.RequiresSecret = true - fmt1 := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{Uppercase: true}, - ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}, - } - - fmt2 := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{Uppercase: true}, - ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: ":"}, - } - - err := b.StoreAssetPairFormat(asset.Spot, fmt1) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - err = b.StoreAssetPairFormat(asset.Margin, fmt2) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - err = b.StoreAssetPairFormat(asset.MarginFunding, fmt1) - if err != nil { - log.Errorln(log.ExchangeSys, err) + for _, a := range []asset.Item{asset.Spot, asset.Margin, asset.MarginFunding} { + ps := currency.PairStore{ + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true}, + ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}, + } + if a == asset.Margin { + ps.ConfigFormat.Delimiter = ":" + } + if err := b.StoreAssetPairStore(a, ps); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", b.Name, a, err) + } } // Margin WS Currently not fully implemented and causes subscription collisions with spot - err = b.DisableAssetWebsocketSupport(asset.Margin) - if err != nil { - log.Errorln(log.ExchangeSys, err) + if err := b.DisableAssetWebsocketSupport(asset.Margin); err != nil { + log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", b.Name, asset.Margin, err) } // TODO: Implement Futures and Securities asset types. @@ -162,6 +152,7 @@ func (b *Bitfinex) SetDefaults() { Subscriptions: defaultSubscriptions.Clone(), } + var err error b.Requester, err = request.New(b.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), request.WithLimiter(GetRateLimit())) diff --git a/exchanges/bitmex/bitmex_wrapper.go b/exchanges/bitmex/bitmex_wrapper.go index eea24d81326..3648430e884 100644 --- a/exchanges/bitmex/bitmex_wrapper.go +++ b/exchanges/bitmex/bitmex_wrapper.go @@ -42,37 +42,22 @@ func (b *Bitmex) SetDefaults() { b.API.CredentialsValidator.RequiresKey = true b.API.CredentialsValidator.RequiresSecret = true - configFmt := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter} - standardRequestFmt := ¤cy.PairFormat{Uppercase: true} - spotRequestFormat := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter} - - spot := currency.PairStore{RequestFormat: spotRequestFormat, ConfigFormat: configFmt} - err := b.StoreAssetPairFormat(asset.Spot, spot) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - - perp := currency.PairStore{RequestFormat: standardRequestFmt, ConfigFormat: configFmt} - err = b.StoreAssetPairFormat(asset.PerpetualContract, perp) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - - futures := currency.PairStore{RequestFormat: standardRequestFmt, ConfigFormat: configFmt} - err = b.StoreAssetPairFormat(asset.Futures, futures) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - - index := currency.PairStore{RequestFormat: standardRequestFmt, ConfigFormat: configFmt} - err = b.StoreAssetPairFormat(asset.Index, index) - if err != nil { - log.Errorln(log.ExchangeSys, err) + for _, a := range []asset.Item{asset.Spot, asset.PerpetualContract, asset.Futures, asset.Index} { + ps := currency.PairStore{ + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true}, + ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}, + } + if a == asset.Spot { + ps.RequestFormat = ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter} + } + if err := b.StoreAssetPairStore(a, ps); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", b.Name, a, err) + } } - err = b.DisableAssetWebsocketSupport(asset.Index) - if err != nil { - log.Errorln(log.ExchangeSys, err) + if err := b.DisableAssetWebsocketSupport(asset.Index); err != nil { + log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", b.Name, asset.Index, err) } b.Features = exchange.Features{ @@ -139,6 +124,7 @@ func (b *Bitmex) SetDefaults() { Subscriptions: defaultSubscriptions.Clone(), } + var err error b.Requester, err = request.New(b.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), request.WithLimiter(GetRateLimit())) diff --git a/exchanges/btse/btse_wrapper.go b/exchanges/btse/btse_wrapper.go index 72d25f42925..1e8324e43c5 100644 --- a/exchanges/btse/btse_wrapper.go +++ b/exchanges/btse/btse_wrapper.go @@ -45,33 +45,18 @@ func (b *BTSE) SetDefaults() { b.API.CredentialsValidator.RequiresKey = true b.API.CredentialsValidator.RequiresSecret = true - fmt1 := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{ - Uppercase: true, - Delimiter: currency.DashDelimiter, - }, - ConfigFormat: ¤cy.PairFormat{ - Uppercase: true, - Delimiter: currency.DashDelimiter, - }, - } - err := b.StoreAssetPairFormat(asset.Spot, fmt1) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - - fmt2 := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{ - Uppercase: true, - }, - ConfigFormat: ¤cy.PairFormat{ - Uppercase: true, - Delimiter: currency.DashDelimiter, - }, - } - err = b.StoreAssetPairFormat(asset.Futures, fmt2) - if err != nil { - log.Errorln(log.ExchangeSys, err) + for _, a := range []asset.Item{asset.Spot, asset.Futures} { + ps := currency.PairStore{ + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true}, + ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}, + } + if a == asset.Spot { + ps.RequestFormat.Delimiter = currency.DashDelimiter + } + if err := b.StoreAssetPairStore(a, ps); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", b.Name, a, err) + } } b.Features = exchange.Features{ @@ -143,6 +128,7 @@ func (b *BTSE) SetDefaults() { Subscriptions: defaultSubscriptions.Clone(), } + var err error b.Requester, err = request.New(b.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), request.WithLimiter(GetRateLimit())) diff --git a/exchanges/bybit/bybit_wrapper.go b/exchanges/bybit/bybit_wrapper.go index acb3ae66949..a64874be51b 100644 --- a/exchanges/bybit/bybit_wrapper.go +++ b/exchanges/bybit/bybit_wrapper.go @@ -61,15 +61,15 @@ func (by *Bybit) SetDefaults() { by.API.CredentialsValidator.RequiresSecret = true for _, n := range assetPairFmts { - ps := currency.PairStore{RequestFormat: n.reqFmt, ConfigFormat: n.cfgFmt} - if err := by.StoreAssetPairFormat(n.asset, ps); err != nil { - log.Errorf(log.ExchangeSys, "%v %v", n.asset, err) + ps := currency.PairStore{AssetEnabled: true, RequestFormat: n.reqFmt, ConfigFormat: n.cfgFmt} + if err := by.StoreAssetPairStore(n.asset, ps); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", by.Name, n.asset, err) } } for _, a := range []asset.Item{asset.CoinMarginedFutures, asset.USDTMarginedFutures, asset.USDCMarginedFutures, asset.Options} { if err := by.DisableAssetWebsocketSupport(a); err != nil { - log.Errorln(log.ExchangeSys, err) + log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", by.Name, a, err) } } diff --git a/exchanges/deribit/deribit_wrapper.go b/exchanges/deribit/deribit_wrapper.go index 38023875caa..67be25905cf 100644 --- a/exchanges/deribit/deribit_wrapper.go +++ b/exchanges/deribit/deribit_wrapper.go @@ -65,13 +65,12 @@ func (d *Deribit) SetDefaults() { dashFormat := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter} underscoreFormat := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter} - err := d.StoreAssetPairFormat(asset.Spot, currency.PairStore{RequestFormat: underscoreFormat, ConfigFormat: underscoreFormat}) - if err != nil { - log.Errorln(log.ExchangeSys, err) + if err := d.StoreAssetPairStore(asset.Spot, currency.PairStore{AssetEnabled: true, RequestFormat: underscoreFormat, ConfigFormat: underscoreFormat}); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", d.Name, asset.Spot, err) } - for _, assetType := range []asset.Item{asset.Futures, asset.Options, asset.OptionCombo, asset.FutureCombo} { - if err = d.StoreAssetPairFormat(assetType, currency.PairStore{RequestFormat: dashFormat, ConfigFormat: dashFormat}); err != nil { - log.Errorln(log.ExchangeSys, err) + for _, a := range []asset.Item{asset.Futures, asset.Options, asset.OptionCombo, asset.FutureCombo} { + if err := d.StoreAssetPairStore(a, currency.PairStore{AssetEnabled: true, RequestFormat: dashFormat, ConfigFormat: dashFormat}); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", d.Name, a, err) } } @@ -149,6 +148,8 @@ func (d *Deribit) SetDefaults() { }, }, } + + var err error d.Requester, err = request.New(d.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), request.WithLimiter(GetRateLimits()), diff --git a/exchanges/exchange.go b/exchanges/exchange.go index 5df91dd0891..5068deb5258 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -55,6 +55,7 @@ var ( ) var ( + errStoreAssetPairStore = errors.New("error storing asset pair store") errEndpointStringNotFound = errors.New("endpoint string not found") errConfigPairFormatRequiresDelimiter = errors.New("config pair format requires delimiter") errSetDefaultsNotCalled = errors.New("set defaults not called") @@ -990,26 +991,18 @@ func (b *Base) EnableRateLimiter() error { return b.Requester.EnableRateLimiter() } -// StoreAssetPairFormat initialises and stores a defined asset format -func (b *Base) StoreAssetPairFormat(a asset.Item, f currency.PairStore) error { +// StoreAssetPairStore initialises and stores a defined asset format +func (b *Base) StoreAssetPairStore(a asset.Item, f currency.PairStore) error { if a.String() == "" { - return fmt.Errorf("%s cannot add to pairs manager, no asset provided", - b.Name) - } - - if f.RequestFormat == nil { - return fmt.Errorf("%s cannot add to pairs manager, request pair format not provided", - b.Name) + return asset.ErrInvalidAsset } - if f.ConfigFormat == nil { - return fmt.Errorf("%s cannot add to pairs manager, config pair format not provided", - b.Name) + if f.RequestFormat == nil || f.ConfigFormat == nil { + return currency.ErrPairFormatIsNil } if f.ConfigFormat.Delimiter == "" { - return fmt.Errorf("exchange %s cannot set asset %s pair format %w", - b.Name, a, errConfigPairFormatRequiresDelimiter) + return errConfigPairFormatRequiresDelimiter } if b.CurrencyPairs.Pairs == nil { @@ -1017,6 +1010,7 @@ func (b *Base) StoreAssetPairFormat(a asset.Item, f currency.PairStore) error { } b.CurrencyPairs.Pairs[a] = &f + return nil } @@ -1453,9 +1447,7 @@ func getURLTypeFromString(ep string) (URL, error) { // check availability of asset type. func (b *Base) DisableAssetWebsocketSupport(aType asset.Item) error { if !b.SupportsAsset(aType) { - return fmt.Errorf("%s %w", - aType, - asset.ErrNotSupported) + return fmt.Errorf("%s %w", aType, asset.ErrNotSupported) } b.AssetWebsocketSupport.m.Lock() if b.AssetWebsocketSupport.unsupported == nil { diff --git a/exchanges/exchange_test.go b/exchanges/exchange_test.go index e555ca22098..b5e958b4b7e 100644 --- a/exchanges/exchange_test.go +++ b/exchanges/exchange_test.go @@ -1396,47 +1396,37 @@ func TestGetFormattedPairAndAssetType(t *testing.T) { } } -func TestStoreAssetPairFormat(t *testing.T) { +func TestStoreAssetPairStore(t *testing.T) { b := Base{ Config: &config.Exchange{Name: "kitties"}, } - err := b.StoreAssetPairFormat(asset.Empty, currency.PairStore{}) - if err == nil { - t.Error("error cannot be nil") - } + err := b.StoreAssetPairStore(asset.Empty, currency.PairStore{}) + assert.ErrorIs(t, err, asset.ErrInvalidAsset) - err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{}) - if err == nil { - t.Error("error cannot be nil") - } + err = b.StoreAssetPairStore(asset.Spot, currency.PairStore{}) + assert.ErrorIs(t, err, currency.ErrPairFormatIsNil) - err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{ - RequestFormat: ¤cy.PairFormat{Uppercase: true}}) - if err == nil { - t.Error("error cannot be nil") - } + err = b.StoreAssetPairStore(asset.Spot, currency.PairStore{RequestFormat: ¤cy.PairFormat{Uppercase: true}}) + assert.ErrorIs(t, err, currency.ErrPairFormatIsNil) - err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{ + err = b.StoreAssetPairStore(asset.Spot, currency.PairStore{ RequestFormat: ¤cy.PairFormat{Uppercase: true}, ConfigFormat: ¤cy.PairFormat{Uppercase: true}}) - if !errors.Is(err, errConfigPairFormatRequiresDelimiter) { - t.Fatalf("received: '%v' but expected: '%v'", err, errConfigPairFormatRequiresDelimiter) - } + assert.ErrorIs(t, err, errConfigPairFormatRequiresDelimiter) - err = b.StoreAssetPairFormat(asset.Futures, currency.PairStore{ + err = b.StoreAssetPairStore(asset.Futures, currency.PairStore{ RequestFormat: ¤cy.PairFormat{Uppercase: true}, ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}}) - if err != nil { - t.Error(err) - } + assert.NoError(t, err) + assert.False(t, b.CurrencyPairs.Pairs[asset.Futures].AssetEnabled, "StoreAssetPairStore should not magically enable AssetTypes") - err = b.StoreAssetPairFormat(asset.Futures, currency.PairStore{ + err = b.StoreAssetPairStore(asset.Futures, currency.PairStore{ + AssetEnabled: true, RequestFormat: ¤cy.PairFormat{Uppercase: true}, ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}}) - if err != nil { - t.Error(err) - } + assert.NoError(t, err) + assert.True(t, b.CurrencyPairs.Pairs[asset.Futures].AssetEnabled, "AssetEnabled should be respected") } func TestSetGlobalPairsManager(t *testing.T) { @@ -1796,7 +1786,7 @@ func TestFormatSymbol(t *testing.T) { Uppercase: true, }, } - err := b.StoreAssetPairFormat(asset.Spot, spotStore) + err := b.StoreAssetPairStore(asset.Spot, spotStore) if err != nil { t.Error(err) } @@ -1908,7 +1898,7 @@ func TestAssetWebsocketFunctionality(t *testing.T) { t.Fatalf("expected error: %v but received: %v", asset.ErrNotSupported, err) } - err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{ + err = b.StoreAssetPairStore(asset.Spot, currency.PairStore{ RequestFormat: ¤cy.PairFormat{ Uppercase: true, }, diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index 76c461cb196..26e99dda6af 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -41,43 +41,21 @@ func (h *HUOBI) SetDefaults() { h.API.CredentialsValidator.RequiresKey = true h.API.CredentialsValidator.RequiresSecret = true - fmt1 := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{Uppercase: false}, - ConfigFormat: ¤cy.PairFormat{ - Delimiter: currency.DashDelimiter, - Uppercase: true, - }, - } - coinFutures := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{ - Uppercase: true, - Delimiter: currency.DashDelimiter, - }, - ConfigFormat: ¤cy.PairFormat{ - Uppercase: true, - Delimiter: currency.DashDelimiter, - }, - } - futuresFormatting := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{ - Uppercase: true, - }, - ConfigFormat: ¤cy.PairFormat{ - Uppercase: true, - Delimiter: currency.DashDelimiter, - }, - } - err := h.StoreAssetPairFormat(asset.Spot, fmt1) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - err = h.StoreAssetPairFormat(asset.CoinMarginedFutures, coinFutures) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - err = h.StoreAssetPairFormat(asset.Futures, futuresFormatting) - if err != nil { - log.Errorln(log.ExchangeSys, err) + for _, a := range []asset.Item{asset.Spot, asset.CoinMarginedFutures, asset.Futures} { + ps := currency.PairStore{ + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true}, + ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}, + } + switch a { + case asset.Spot: + ps.RequestFormat.Uppercase = false + case asset.CoinMarginedFutures: + ps.RequestFormat.Delimiter = currency.DashDelimiter + } + if err := h.StoreAssetPairStore(a, ps); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", h.Name, a, err) + } } h.Features = exchange.Features{ @@ -165,6 +143,7 @@ func (h *HUOBI) SetDefaults() { Subscriptions: defaultSubscriptions.Clone(), } + var err error h.Requester, err = request.New(h.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), request.WithLimiter(GetRateLimit())) diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go index 610350c27f8..8bcfdc14d23 100644 --- a/exchanges/kraken/kraken_wrapper.go +++ b/exchanges/kraken/kraken_wrapper.go @@ -43,42 +43,22 @@ func (k *Kraken) SetDefaults() { k.API.CredentialsValidator.RequiresSecret = true k.API.CredentialsValidator.RequiresBase64DecodeSecret = true - pairStore := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{ - Uppercase: true, - Separator: ",", - }, - ConfigFormat: ¤cy.PairFormat{ - Uppercase: true, - Delimiter: currency.UnderscoreDelimiter, - Separator: ",", - }, - } - - futures := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{ - Delimiter: currency.UnderscoreDelimiter, - Uppercase: true, - }, - ConfigFormat: ¤cy.PairFormat{ - Uppercase: true, - Delimiter: currency.UnderscoreDelimiter, - }, - } - - err := k.StoreAssetPairFormat(asset.Spot, pairStore) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - - err = k.StoreAssetPairFormat(asset.Futures, futures) - if err != nil { - log.Errorln(log.ExchangeSys, err) + for _, a := range []asset.Item{asset.Spot, asset.Futures} { + ps := currency.PairStore{ + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true}, + ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}, + } + if a == asset.Futures { + ps.RequestFormat.Delimiter = currency.UnderscoreDelimiter + } + if err := k.StoreAssetPairStore(a, ps); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", k.Name, a, err) + } } - err = k.DisableAssetWebsocketSupport(asset.Futures) - if err != nil { - log.Errorln(log.ExchangeSys, err) + if err := k.DisableAssetWebsocketSupport(asset.Futures); err != nil { + log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", k.Name, asset.Futures, err) } k.Features = exchange.Features{ @@ -171,6 +151,7 @@ func (k *Kraken) SetDefaults() { Subscriptions: defaultSubscriptions.Clone(), } + var err error k.Requester, err = request.New(k.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), request.WithLimiter(request.NewBasicRateLimit(krakenRateInterval, krakenRequestRate, 1))) diff --git a/exchanges/kucoin/kucoin_wrapper.go b/exchanges/kucoin/kucoin_wrapper.go index 12a2bc42216..d8c1d2a2978 100644 --- a/exchanges/kucoin/kucoin_wrapper.go +++ b/exchanges/kucoin/kucoin_wrapper.go @@ -44,26 +44,21 @@ func (ku *Kucoin) SetDefaults() { ku.API.CredentialsValidator.RequiresSecret = true ku.API.CredentialsValidator.RequiresClientID = true - spot := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}, - ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}, - } - futures := currency.PairStore{ - RequestFormat: ¤cy.PairFormat{Uppercase: true}, - ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}, - } - err := ku.StoreAssetPairFormat(asset.Spot, spot) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - err = ku.StoreAssetPairFormat(asset.Margin, spot) - if err != nil { - log.Errorln(log.ExchangeSys, err) - } - err = ku.StoreAssetPairFormat(asset.Futures, futures) - if err != nil { - log.Errorln(log.ExchangeSys, err) + for _, a := range []asset.Item{asset.Spot, asset.Margin, asset.Futures} { + ps := currency.PairStore{ + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}, + ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}, + } + if a == asset.Futures { + ps.RequestFormat.Delimiter = "" + ps.ConfigFormat.Delimiter = currency.UnderscoreDelimiter + } + if err := ku.StoreAssetPairStore(a, ps); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", ku.Name, a, err) + } } + ku.Features = exchange.Features{ CurrencyTranslations: currency.NewTranslations(map[currency.Code]currency.Code{ currency.XBT: currency.BTC, @@ -151,6 +146,8 @@ func (ku *Kucoin) SetDefaults() { }, Subscriptions: defaultSubscriptions.Clone(), } + + var err error ku.Requester, err = request.New(ku.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), request.WithLimiter(GetRateLimit()))