mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
Config: AssetEnabled upgrade (#1735)
* Config: Move assetEnabled upgrade to Version management * Assets: Do not error on asset not enabled, or disabled This became more messy with Disabling something that's defaulted to disabled. Taking an idealogical stance against erroring that what you want to have done is already done. * CurrencyManager: Set AssetEnabled when StorePairs(enabled) * RPCServer: Fix tests expecting StoreAssetPairFormat to enable the asset Also assertifies * Bitfinex: Fix tests for MarginFunding subs * GCTWrapper: Improve TestMain clarity * BTSE: Add futures to testconfig * Exchanges: Rename StoreAssetPairStore Previously we were calling it "Format", but accepting everything from the PairStore. We were also defaulting to turning the Asset on. Now callers need to get their AssetEnabled set as they want it, so there's no magic This change also moves responsibility for error wrapping outside to the caller. * Config: AssetEnabled upgrade should respect assetTypes Previously we ignored the field and just turned on everything. I think that was because we couldn't get at the old value. In either case, we have the option to do better, and respect the assetEnabled value * Config: Improve exchange config version upgrade error messages
This commit is contained in:
@@ -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,
|
||||
},
|
||||
for a, ps := range defaultAssetPairStores {
|
||||
if err := b.SetAssetPairStore(a, ps); err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", b.Name, a, err)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
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()))
|
||||
|
||||
@@ -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.SetAssetPairStore(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()))
|
||||
|
||||
@@ -1148,15 +1148,23 @@ func TestGenerateSubscriptions(t *testing.T) {
|
||||
s := baseSub.Clone()
|
||||
s.Asset = a
|
||||
s.Pairs = currency.Pairs{p}
|
||||
prefix := "t"
|
||||
if a == asset.MarginFunding {
|
||||
prefix = "f"
|
||||
}
|
||||
switch s.Channel {
|
||||
case subscription.TickerChannel:
|
||||
s.QualifiedChannel = `{"channel":"ticker","symbol":"t` + p.String() + `"}`
|
||||
s.QualifiedChannel = `{"channel":"ticker","symbol":"` + prefix + p.String() + `"}`
|
||||
case subscription.CandlesChannel:
|
||||
s.QualifiedChannel = `{"channel":"candles","key":"trade:1m:t` + p.String() + `"}`
|
||||
if a == asset.MarginFunding {
|
||||
s.QualifiedChannel = `{"channel":"candles","key":"trade:1m:` + prefix + p.String() + `:p30"}`
|
||||
} else {
|
||||
s.QualifiedChannel = `{"channel":"candles","key":"trade:1m:` + prefix + p.String() + `"}`
|
||||
}
|
||||
case subscription.OrderbookChannel:
|
||||
s.QualifiedChannel = `{"channel":"book","len":100,"prec":"R0","symbol":"t` + p.String() + `"}`
|
||||
s.QualifiedChannel = `{"channel":"book","len":100,"prec":"R0","symbol":"` + prefix + p.String() + `"}`
|
||||
case subscription.AllTradesChannel:
|
||||
s.QualifiedChannel = `{"channel":"trades","symbol":"t` + p.String() + `"}`
|
||||
s.QualifiedChannel = `{"channel":"trades","symbol":"` + prefix + p.String() + `"}`
|
||||
}
|
||||
exp = append(exp, s)
|
||||
}
|
||||
|
||||
@@ -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.SetAssetPairStore(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()))
|
||||
|
||||
@@ -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)
|
||||
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.Delimiter = currency.UnderscoreDelimiter
|
||||
}
|
||||
if err := b.SetAssetPairStore(a, ps); err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", b.Name, a, 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)
|
||||
}
|
||||
|
||||
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()))
|
||||
|
||||
@@ -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.SetAssetPairStore(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()))
|
||||
|
||||
@@ -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.SetAssetPairStore(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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,13 +43,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.SetAssetPairStore(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.SetAssetPairStore(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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +127,8 @@ func (d *Deribit) SetDefaults() {
|
||||
},
|
||||
Subscriptions: defaultSubscriptions.Clone(),
|
||||
}
|
||||
|
||||
var err error
|
||||
d.Requester, err = request.New(d.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(GetRateLimits()),
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"unicode"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/key"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
@@ -58,6 +57,7 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
errSetAssetPairStore = 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")
|
||||
@@ -309,68 +309,56 @@ func (b *Base) SetCurrencyPairFormat() error {
|
||||
func (b *Base) SetConfigPairs() error {
|
||||
assetTypes := b.Config.CurrencyPairs.GetAssetTypes(false)
|
||||
exchangeAssets := b.CurrencyPairs.GetAssetTypes(false)
|
||||
for x := range assetTypes {
|
||||
if !exchangeAssets.Contains(assetTypes[x]) {
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"%s exchange asset type %s unsupported, please manually remove from configuration",
|
||||
b.Name,
|
||||
assetTypes[x])
|
||||
continue // If there are unsupported assets contained in config, skip.
|
||||
for _, a := range assetTypes {
|
||||
if !exchangeAssets.Contains(a) {
|
||||
log.Warnf(log.ExchangeSys, "%s exchange asset type %s unsupported, please manually remove from configuration", b.Name, a)
|
||||
continue
|
||||
}
|
||||
if !b.Config.CurrencyPairs.UseGlobalFormat {
|
||||
// TODO: Should be in SetCurrencyPairFormat. See #1748
|
||||
if err := b.setConfigPairFormatFromExchange(a); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cfgPS, err := b.Config.CurrencyPairs.Get(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := b.CurrencyPairs.StorePairs(a, cfgPS.Available, false); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := b.CurrencyPairs.StorePairs(a, cfgPS.Enabled, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var enabledAsset bool
|
||||
if b.Config.CurrencyPairs.IsAssetEnabled(assetTypes[x]) == nil {
|
||||
if b.Config.CurrencyPairs.IsAssetEnabled(a) == nil {
|
||||
enabledAsset = true
|
||||
}
|
||||
|
||||
err := b.CurrencyPairs.SetAssetEnabled(assetTypes[x], enabledAsset)
|
||||
// Suppress error when assets are enabled by default and they are being
|
||||
// enabled by config. A check for the inverse
|
||||
// e.g. currency.ErrAssetAlreadyDisabled is not needed.
|
||||
if err != nil && !errors.Is(err, currency.ErrAssetAlreadyEnabled) {
|
||||
// Must happen after StorePairs, which would have enabled the asset automatically
|
||||
if err := b.CurrencyPairs.SetAssetEnabled(a, enabledAsset); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
cfgPS, err := b.Config.CurrencyPairs.Get(assetTypes[x])
|
||||
if err != nil {
|
||||
// setConfigPairFormatFromExchange sets the config formats from the exchange's format
|
||||
// This deprecated behaviour will be removed, because config should not be backloaded from runtime
|
||||
func (b *Base) setConfigPairFormatFromExchange(a asset.Item) error {
|
||||
ps, err := b.CurrencyPairs.Get(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ps.ConfigFormat != nil {
|
||||
if err := b.Config.CurrencyPairs.StoreFormat(a, ps.ConfigFormat, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.Config.CurrencyPairs.UseGlobalFormat {
|
||||
err = b.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Available, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Enabled, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
exchPS, err := b.CurrencyPairs.Get(assetTypes[x])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if exchPS.ConfigFormat != nil {
|
||||
err = b.Config.CurrencyPairs.StoreFormat(assetTypes[x], exchPS.ConfigFormat, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if exchPS.RequestFormat != nil {
|
||||
err = b.Config.CurrencyPairs.StoreFormat(assetTypes[x], exchPS.RequestFormat, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = b.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Available, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Enabled, true)
|
||||
if err != nil {
|
||||
}
|
||||
if ps.RequestFormat != nil {
|
||||
if err := b.Config.CurrencyPairs.StoreFormat(a, ps.RequestFormat, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -533,8 +521,7 @@ func (b *Base) IsEnabled() bool {
|
||||
|
||||
// SetupDefaults sets the exchange settings based on the supplied config
|
||||
func (b *Base) SetupDefaults(exch *config.Exchange) error {
|
||||
err := exch.Validate()
|
||||
if err != nil {
|
||||
if err := exch.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -560,8 +547,7 @@ func (b *Base) SetupDefaults(exch *config.Exchange) error {
|
||||
exch.HTTPTimeout = DefaultHTTPTimeout
|
||||
}
|
||||
|
||||
err = b.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
if err != nil {
|
||||
if err := b.SetHTTPClientTimeout(exch.HTTPTimeout); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -569,8 +555,7 @@ func (b *Base) SetupDefaults(exch *config.Exchange) error {
|
||||
exch.CurrencyPairs = &b.CurrencyPairs
|
||||
a := exch.CurrencyPairs.GetAssetTypes(false)
|
||||
for i := range a {
|
||||
err = exch.CurrencyPairs.SetAssetEnabled(a[i], true)
|
||||
if err != nil && !errors.Is(err, currency.ErrAssetAlreadyEnabled) {
|
||||
if err := exch.CurrencyPairs.SetAssetEnabled(a[i], true); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -578,18 +563,15 @@ func (b *Base) SetupDefaults(exch *config.Exchange) error {
|
||||
|
||||
b.HTTPDebugging = exch.HTTPDebugging
|
||||
b.BypassConfigFormatUpgrades = exch.CurrencyPairs.BypassConfigFormatUpgrades
|
||||
err = b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
if err != nil {
|
||||
if err := b.SetHTTPClientUserAgent(exch.HTTPUserAgent); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = b.SetCurrencyPairFormat()
|
||||
if err != nil {
|
||||
if err := b.SetCurrencyPairFormat(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = b.SetConfigPairs()
|
||||
if err != nil {
|
||||
if err := b.SetConfigPairs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -599,27 +581,26 @@ func (b *Base) SetupDefaults(exch *config.Exchange) error {
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
}
|
||||
|
||||
err = b.SetAPIURL()
|
||||
if err != nil {
|
||||
if err := b.SetAPIURL(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b.SetAPICredentialDefaults()
|
||||
|
||||
err = b.SetClientProxyAddress(exch.ProxyAddress)
|
||||
if err != nil {
|
||||
if err := b.SetClientProxyAddress(exch.ProxyAddress); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b.BaseCurrencies = exch.BaseCurrencies
|
||||
|
||||
if exch.Orderbook.VerificationBypass {
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"%s orderbook verification has been bypassed via config.",
|
||||
b.Name)
|
||||
log.Warnf(log.ExchangeSys, "%s orderbook verification has been bypassed via config.", b.Name)
|
||||
}
|
||||
|
||||
b.CanVerifyOrderbook = !exch.Orderbook.VerificationBypass
|
||||
b.States = currencystate.NewCurrencyStates()
|
||||
return err
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPairs sets the exchange currency pairs for either enabledPairs or
|
||||
@@ -1004,30 +985,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 {
|
||||
// SetAssetPairStore initialises and stores a defined asset format
|
||||
func (b *Base) SetAssetPairStore(a asset.Item, f currency.PairStore) error {
|
||||
if a.String() == "" {
|
||||
return fmt.Errorf("%s cannot add to pairs manager, no asset provided",
|
||||
b.Name)
|
||||
return asset.ErrInvalidAsset
|
||||
}
|
||||
|
||||
if f.AssetEnabled == nil {
|
||||
f.AssetEnabled = convert.BoolPtr(true)
|
||||
}
|
||||
|
||||
if f.RequestFormat == nil {
|
||||
return fmt.Errorf("%s cannot add to pairs manager, request pair format not provided",
|
||||
b.Name)
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -1035,6 +1004,7 @@ func (b *Base) StoreAssetPairFormat(a asset.Item, f currency.PairStore) error {
|
||||
}
|
||||
|
||||
b.CurrencyPairs.Pairs[a] = &f
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1076,7 +1046,7 @@ func (b *Base) SetGlobalPairsManager(request, config *currency.PairFormat, asset
|
||||
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]].AssetEnabled = true
|
||||
b.CurrencyPairs.Pairs[assets[i]].ConfigFormat = config
|
||||
b.CurrencyPairs.Pairs[assets[i]].RequestFormat = request
|
||||
}
|
||||
@@ -1471,9 +1441,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 {
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/key"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
@@ -536,7 +535,7 @@ func TestLoadConfigPairs(t *testing.T) {
|
||||
},
|
||||
Pairs: map[asset.Item]*currency.PairStore{
|
||||
asset.Spot: {
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Enabled: pairs,
|
||||
Available: pairs,
|
||||
},
|
||||
@@ -913,7 +912,7 @@ func TestSetPairs(t *testing.T) {
|
||||
},
|
||||
Pairs: map[asset.Item]*currency.PairStore{
|
||||
asset.Spot: {
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -973,7 +972,7 @@ func TestUpdatePairs(t *testing.T) {
|
||||
CurrencyPairs: currency.PairsManager{
|
||||
Pairs: map[asset.Item]*currency.PairStore{
|
||||
asset.Spot: {
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
},
|
||||
},
|
||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
||||
@@ -1292,7 +1291,7 @@ func TestSupportsAsset(t *testing.T) {
|
||||
var b Base
|
||||
b.CurrencyPairs.Pairs = map[asset.Item]*currency.PairStore{
|
||||
asset.Spot: {
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
},
|
||||
}
|
||||
assert.True(t, b.SupportsAsset(asset.Spot), "Spot should be supported")
|
||||
@@ -1335,7 +1334,7 @@ func TestGetAssetType(t *testing.T) {
|
||||
}
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Enabled: currency.Pairs{
|
||||
currency.NewPair(currency.BTC, currency.USD),
|
||||
},
|
||||
@@ -1373,7 +1372,7 @@ func TestGetFormattedPairAndAssetType(t *testing.T) {
|
||||
b.CurrencyPairs.ConfigFormat = pFmt
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Enabled: currency.Pairs{
|
||||
currency.NewPair(currency.BTC, currency.USD),
|
||||
},
|
||||
@@ -1397,47 +1396,37 @@ func TestGetFormattedPairAndAssetType(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreAssetPairFormat(t *testing.T) {
|
||||
func TestSetAssetPairStore(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.SetAssetPairStore(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.SetAssetPairStore(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.SetAssetPairStore(asset.Spot, currency.PairStore{RequestFormat: ¤cy.PairFormat{Uppercase: true}})
|
||||
assert.ErrorIs(t, err, currency.ErrPairFormatIsNil)
|
||||
|
||||
err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{
|
||||
err = b.SetAssetPairStore(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.SetAssetPairStore(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, "SetAssetPairStore should not magically enable AssetTypes")
|
||||
|
||||
err = b.StoreAssetPairFormat(asset.Futures, currency.PairStore{
|
||||
err = b.SetAssetPairStore(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) {
|
||||
@@ -1518,7 +1507,7 @@ func TestBase_ValidateKline(t *testing.T) {
|
||||
CurrencyPairs: currency.PairsManager{
|
||||
Pairs: map[asset.Item]*currency.PairStore{
|
||||
asset.Spot: {
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Enabled: pairs,
|
||||
Available: availablePairs,
|
||||
},
|
||||
@@ -1797,7 +1786,7 @@ func TestFormatSymbol(t *testing.T) {
|
||||
Uppercase: true,
|
||||
},
|
||||
}
|
||||
err := b.StoreAssetPairFormat(asset.Spot, spotStore)
|
||||
err := b.SetAssetPairStore(asset.Spot, spotStore)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -1909,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.SetAssetPairStore(asset.Spot, currency.PairStore{
|
||||
RequestFormat: ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
},
|
||||
@@ -2122,14 +2111,14 @@ func TestGetPairAndAssetTypeRequestFormatted(t *testing.T) {
|
||||
CurrencyPairs: currency.PairsManager{
|
||||
Pairs: map[asset.Item]*currency.PairStore{
|
||||
asset.Spot: {
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Enabled: enabledPairs,
|
||||
Available: availablePairs,
|
||||
RequestFormat: ¤cy.PairFormat{Delimiter: "-", Uppercase: true},
|
||||
ConfigFormat: ¤cy.EMPTYFORMAT,
|
||||
},
|
||||
asset.PerpetualContract: {
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Enabled: enabledPairs,
|
||||
Available: availablePairs,
|
||||
RequestFormat: ¤cy.PairFormat{Delimiter: "_", Uppercase: true},
|
||||
@@ -2265,7 +2254,7 @@ func TestGetKlineRequest(t *testing.T) {
|
||||
|
||||
b.Features.Enabled.Kline.Intervals = kline.DeployExchangeIntervals(kline.IntervalCapacity{Interval: kline.OneDay, Capacity: 1439})
|
||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Enabled: []currency.Pair{pair},
|
||||
Available: []currency.Pair{pair},
|
||||
})
|
||||
@@ -2289,7 +2278,7 @@ func TestGetKlineRequest(t *testing.T) {
|
||||
assert.ErrorIs(t, err, currency.ErrPairFormatIsNil, "GetKlineRequest should return Format is Nil")
|
||||
|
||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Enabled: []currency.Pair{pair},
|
||||
Available: []currency.Pair{pair},
|
||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||
@@ -2316,7 +2305,7 @@ func TestGetKlineRequest(t *testing.T) {
|
||||
}
|
||||
|
||||
err = b.CurrencyPairs.Store(asset.Futures, ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Enabled: []currency.Pair{pair},
|
||||
Available: []currency.Pair{pair},
|
||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||
@@ -2442,7 +2431,7 @@ func TestGetKlineExtendedRequest(t *testing.T) {
|
||||
}
|
||||
|
||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Enabled: []currency.Pair{pair},
|
||||
Available: []currency.Pair{pair},
|
||||
})
|
||||
@@ -2454,7 +2443,7 @@ func TestGetKlineExtendedRequest(t *testing.T) {
|
||||
assert.ErrorIs(t, err, currency.ErrPairFormatIsNil, "GetKlineExtendedRequest should error correctly")
|
||||
|
||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Enabled: []currency.Pair{pair},
|
||||
Available: []currency.Pair{pair},
|
||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||
@@ -2573,7 +2562,7 @@ func TestEnsureOnePairEnabled(t *testing.T) {
|
||||
Pairs: map[asset.Item]*currency.PairStore{
|
||||
asset.Futures: {},
|
||||
asset.Spot: {
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Available: []currency.Pair{
|
||||
currency.NewPair(currency.BTC, currency.USDT),
|
||||
},
|
||||
@@ -2646,7 +2635,7 @@ func TestMatchSymbolWithAvailablePairs(t *testing.T) {
|
||||
b := Base{Name: "test"}
|
||||
whatIWant := currency.NewPair(currency.BTC, currency.USDT)
|
||||
err := b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Available: []currency.Pair{whatIWant}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -2682,7 +2671,7 @@ func TestMatchSymbolCheckEnabled(t *testing.T) {
|
||||
whatIWant := currency.NewPair(currency.BTC, currency.USDT)
|
||||
availButNoEnabled := currency.NewPair(currency.BTC, currency.AUD)
|
||||
err := b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Available: []currency.Pair{whatIWant, availButNoEnabled},
|
||||
Enabled: []currency.Pair{whatIWant},
|
||||
})
|
||||
@@ -2741,7 +2730,7 @@ func TestIsPairEnabled(t *testing.T) {
|
||||
whatIWant := currency.NewPair(currency.BTC, currency.USDT)
|
||||
availButNoEnabled := currency.NewPair(currency.BTC, currency.AUD)
|
||||
err := b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
Available: []currency.Pair{whatIWant, availButNoEnabled},
|
||||
Enabled: []currency.Pair{whatIWant},
|
||||
})
|
||||
@@ -3130,3 +3119,20 @@ func TestGetTradingRequirements(t *testing.T) {
|
||||
requirements = (&Base{Features: Features{TradingRequirements: protocol.TradingRequirements{ClientOrderID: true}}}).GetTradingRequirements()
|
||||
require.NotEmpty(t, requirements)
|
||||
}
|
||||
|
||||
func TestSetConfigPairFormatFromExchange(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Base{Config: &config.Exchange{CurrencyPairs: ¤cy.PairsManager{}}}
|
||||
err := b.setConfigPairFormatFromExchange(asset.Spot)
|
||||
assert.ErrorIs(t, err, asset.ErrNotSupported, "setConfigPairFormatFromExchange should error correctly without pairs")
|
||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||
Enabled: currency.Pairs{btcusdPair},
|
||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "🐋"},
|
||||
RequestFormat: ¤cy.PairFormat{Delimiter: "🦥"},
|
||||
})
|
||||
require.NoError(t, err, "CurrencyPairs.Store must not error")
|
||||
err = b.setConfigPairFormatFromExchange(asset.Spot)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "🐋", b.Config.CurrencyPairs.Pairs[asset.Spot].ConfigFormat.Delimiter, "ConfigFormat should be correct and have a blow hole")
|
||||
assert.Equal(t, "🦥", b.Config.CurrencyPairs.Pairs[asset.Spot].RequestFormat.Delimiter, "RequestFormat should be correct and kinda lazy")
|
||||
}
|
||||
|
||||
@@ -41,47 +41,25 @@ 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.SetAssetPairStore(a, ps); err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", h.Name, a, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, a := range []asset.Item{asset.Futures, asset.CoinMarginedFutures} {
|
||||
if err = h.DisableAssetWebsocketSupport(a); err != nil {
|
||||
if err := h.DisableAssetWebsocketSupport(a); err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", h.Name, a, err)
|
||||
}
|
||||
}
|
||||
@@ -171,6 +149,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()))
|
||||
|
||||
@@ -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: ",",
|
||||
},
|
||||
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.SetAssetPairStore(a, ps); err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", k.Name, a, err)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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)))
|
||||
|
||||
@@ -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.SetAssetPairStore(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()))
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
var errValidationCheckFailed = errors.New("validation check failed")
|
||||
|
||||
func TestSubmit_Validate(t *testing.T) {
|
||||
func TestSubmitValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
testPair := currency.NewPair(currency.BTC, currency.LTC)
|
||||
tester := []struct {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/bitstamp"
|
||||
@@ -21,7 +20,7 @@ func TestSimulate(t *testing.T) {
|
||||
},
|
||||
Pairs: map[asset.Item]*currency.PairStore{
|
||||
asset.Spot: {
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
AssetEnabled: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package sharedtestvalues
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -11,6 +10,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
@@ -154,32 +154,26 @@ func SetupCurrencyPairsForExchangeAsset(t *testing.T, exch exchange.IBotExchange
|
||||
return
|
||||
}
|
||||
b := exch.GetBase()
|
||||
|
||||
err := b.CurrencyPairs.SetAssetEnabled(a, true)
|
||||
if err != nil && !errors.Is(err, currency.ErrAssetAlreadyEnabled) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err, "SetAssetEnabled must not error")
|
||||
|
||||
availPairs, err := b.CurrencyPairs.GetPairs(a, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err, "GetPairs must not error")
|
||||
|
||||
apLen := len(availPairs)
|
||||
enabledPairs, err := b.CurrencyPairs.GetPairs(a, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err, "GetPairs must not error")
|
||||
|
||||
epLen := len(enabledPairs)
|
||||
availPairs = availPairs.Add(cp...)
|
||||
enabledPairs = enabledPairs.Add(cp...)
|
||||
if len(availPairs) != apLen {
|
||||
err = b.CurrencyPairs.StorePairs(a, availPairs, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err, "StorePairs must not error")
|
||||
}
|
||||
if len(enabledPairs) != epLen {
|
||||
err = b.CurrencyPairs.StorePairs(a, enabledPairs, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err, "StorePairs must not error")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user