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:
Gareth Kirwan
2025-03-17 17:47:37 +07:00
committed by GitHub
parent 2a11c94dc4
commit 16d2d9f35a
41 changed files with 717 additions and 884 deletions

View File

@@ -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 {