diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 70447817..4a1bcb6d 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -39,6 +39,7 @@ gam-phon | https://github.com/gam-phon if1live | https://github.com/if1live lozdog245 | https://github.com/lozdog245 MarkDzulko | https://github.com/MarkDzulko +soxipy | https://github.com/soxipy blombard | https://github.com/blombard cavapoo2 | https://github.com/cavapoo2 CodeLingoTeam | https://github.com/CodeLingoTeam @@ -54,6 +55,5 @@ m1kola | https://github.com/m1kola mattkanwisher | https://github.com/mattkanwisher merkeld | https://github.com/merkeld mKurrels | https://github.com/mKurrels -soxipy | https://github.com/soxipy starit | https://github.com/starit zeldrinn | https://github.com/zeldrinn diff --git a/README.md b/README.md index 9180d1be..d2a397d2 100644 --- a/README.md +++ b/README.md @@ -160,11 +160,11 @@ Binaries will be published once the codebase reaches a stable condition. | [shazbert](https://github.com/shazbert) | 362 | | [dependabot[bot]](https://github.com/apps/dependabot) | 361 | | [gloriousCode](https://github.com/gloriousCode) | 237 | -| [gbjk](https://github.com/gbjk) | 119 | +| [gbjk](https://github.com/gbjk) | 121 | | [dependabot-preview[bot]](https://github.com/apps/dependabot-preview) | 88 | | [xtda](https://github.com/xtda) | 47 | | [lrascao](https://github.com/lrascao) | 27 | -| [Beadko](https://github.com/Beadko) | 21 | +| [Beadko](https://github.com/Beadko) | 22 | | [Rots](https://github.com/Rots) | 15 | | [vazha](https://github.com/vazha) | 15 | | [ydm](https://github.com/ydm) | 15 | @@ -195,6 +195,7 @@ Binaries will be published once the codebase reaches a stable condition. | [if1live](https://github.com/if1live) | 2 | | [lozdog245](https://github.com/lozdog245) | 2 | | [MarkDzulko](https://github.com/MarkDzulko) | 2 | +| [soxipy](https://github.com/soxipy) | 2 | | [blombard](https://github.com/blombard) | 1 | | [cavapoo2](https://github.com/cavapoo2) | 1 | | [CodeLingoTeam](https://github.com/CodeLingoTeam) | 1 | @@ -210,6 +211,5 @@ Binaries will be published once the codebase reaches a stable condition. | [mattkanwisher](https://github.com/mattkanwisher) | 1 | | [merkeld](https://github.com/merkeld) | 1 | | [mKurrels](https://github.com/mKurrels) | 1 | -| [soxipy](https://github.com/soxipy) | 2 | | [starit](https://github.com/starit) | 1 | | [zeldrinn](https://github.com/zeldrinn) | 1 | diff --git a/backtester/btcli/main.go b/backtester/btcli/main.go index a4042cf2..2a221f53 100644 --- a/backtester/btcli/main.go +++ b/backtester/btcli/main.go @@ -36,7 +36,7 @@ var ( const defaultTimeout = time.Second * 30 -func jsonOutput(in interface{}) { +func jsonOutput(in any) { j, err := json.MarshalIndent(in, "", " ") if err != nil { return diff --git a/backtester/common/common_types.go b/backtester/common/common_types.go index e7c25ca6..c9370b0f 100644 --- a/backtester/common/common_types.go +++ b/backtester/common/common_types.go @@ -52,7 +52,7 @@ type Event interface { GetReasons() []string GetClosePrice() decimal.Decimal AppendReason(string) - AppendReasonf(string, ...interface{}) + AppendReasonf(string, ...any) } // custom subloggers for backtester use diff --git a/backtester/config/strategyconfig_test.go b/backtester/config/strategyconfig_test.go index 9fbf7717..c88c637b 100644 --- a/backtester/config/strategyconfig_test.go +++ b/backtester/config/strategyconfig_test.go @@ -362,7 +362,7 @@ func TestPrintSettings(t *testing.T) { Goal: "To demonstrate rendering of settings", StrategySettings: StrategySettings{ Name: dca, - CustomSettings: map[string]interface{}{ + CustomSettings: map[string]any{ "dca-dummy1": 30.0, "dca-dummy2": 30.0, "dca-dummy3": 30.0, @@ -963,7 +963,7 @@ func TestGenerateConfigForRSIAPICustomSettings(t *testing.T) { Goal: "To demonstrate the RSI strategy using API candle data and custom settings", StrategySettings: StrategySettings{ Name: "rsi", - CustomSettings: map[string]interface{}{ + CustomSettings: map[string]any{ "rsi-low": 30.0, "rsi-high": 70.0, "rsi-period": 14, @@ -1206,7 +1206,7 @@ func TestGenerateConfigForTop2Bottom2(t *testing.T) { Name: top2bottom2.Name, SimultaneousSignalProcessing: true, - CustomSettings: map[string]interface{}{ + CustomSettings: map[string]any{ "mfi-low": 32, "mfi-high": 68, "mfi-period": 14, diff --git a/backtester/config/strategyconfig_types.go b/backtester/config/strategyconfig_types.go index 48ffd7f7..56ea8455 100644 --- a/backtester/config/strategyconfig_types.go +++ b/backtester/config/strategyconfig_types.go @@ -67,8 +67,8 @@ type StrategySettings struct { // If true, won't track USD values against currency pair // bool language is opposite to encourage use by default - DisableUSDTracking bool `json:"disable-usd-tracking"` - CustomSettings map[string]interface{} `json:"custom-settings,omitempty"` + DisableUSDTracking bool `json:"disable-usd-tracking"` + CustomSettings map[string]any `json:"custom-settings,omitempty"` } // ExchangeLevelFunding allows the portfolio manager to access diff --git a/backtester/config/strategyconfigbuilder/main.go b/backtester/config/strategyconfigbuilder/main.go index 6c048a7e..1f29cb10 100644 --- a/backtester/config/strategyconfigbuilder/main.go +++ b/backtester/config/strategyconfigbuilder/main.go @@ -554,8 +554,8 @@ func parseStratName(name string, strategiesToUse []string) (string, error) { return "", errors.New("unrecognised strategy") } -func customSettingsLoop(reader *bufio.Reader) map[string]interface{} { - resp := make(map[string]interface{}) +func customSettingsLoop(reader *bufio.Reader) map[string]any { + resp := make(map[string]any) customSettingField := "loopTime!" for customSettingField != "" { fmt.Println("Enter a custom setting name. Enter nothing to stop") diff --git a/backtester/data/data_test.go b/backtester/data/data_test.go index 792bcfc1..33249f3c 100644 --- a/backtester/data/data_test.go +++ b/backtester/data/data_test.go @@ -808,7 +808,7 @@ func (f fakeEvent) GetUnderlyingPair() currency.Pair { return f.Pair() } -func (f fakeEvent) AppendReasonf(string, ...interface{}) {} +func (f fakeEvent) AppendReasonf(string, ...any) {} func (f fakeEvent) GetBase() *event.Base { return &event.Base{} diff --git a/backtester/engine/backtest_test.go b/backtester/engine/backtest_test.go index cf3df497..f2070a64 100644 --- a/backtester/engine/backtest_test.go +++ b/backtester/engine/backtest_test.go @@ -92,7 +92,7 @@ func TestSetupFromConfig(t *testing.T) { cfg.StrategySettings = config.StrategySettings{ Name: dollarcostaverage.Name, - CustomSettings: map[string]interface{}{ + CustomSettings: map[string]any{ "hello": "moto", }, } @@ -166,7 +166,7 @@ func TestLoadDataAPI(t *testing.T) { }, StrategySettings: config.StrategySettings{ Name: dollarcostaverage.Name, - CustomSettings: map[string]interface{}{ + CustomSettings: map[string]any{ "hello": "moto", }, }, @@ -222,7 +222,7 @@ func TestLoadDataCSV(t *testing.T) { }, StrategySettings: config.StrategySettings{ Name: dollarcostaverage.Name, - CustomSettings: map[string]interface{}{ + CustomSettings: map[string]any{ "hello": "moto", }, }, @@ -289,7 +289,7 @@ func TestLoadDataDatabase(t *testing.T) { }, StrategySettings: config.StrategySettings{ Name: dollarcostaverage.Name, - CustomSettings: map[string]interface{}{ + CustomSettings: map[string]any{ "hello": "moto", }, }, @@ -367,7 +367,7 @@ func TestLoadDataLive(t *testing.T) { }, StrategySettings: config.StrategySettings{ Name: dollarcostaverage.Name, - CustomSettings: map[string]interface{}{ + CustomSettings: map[string]any{ "hello": "moto", }, }, diff --git a/backtester/engine/fakeinterfaces_test.go b/backtester/engine/fakeinterfaces_test.go index d0895e97..7dcf5010 100644 --- a/backtester/engine/fakeinterfaces_test.go +++ b/backtester/engine/fakeinterfaces_test.go @@ -307,7 +307,7 @@ func (f fakeStrat) SupportsSimultaneousProcessing() bool { func (f fakeStrat) SetSimultaneousProcessing(bool) {} -func (f fakeStrat) SetCustomSettings(map[string]interface{}) error { +func (f fakeStrat) SetCustomSettings(map[string]any) error { return nil } diff --git a/backtester/engine/grpcserver.go b/backtester/engine/grpcserver.go index 22111568..2cee1ca4 100644 --- a/backtester/engine/grpcserver.go +++ b/backtester/engine/grpcserver.go @@ -358,7 +358,7 @@ func (s *GRPCServer) ExecuteStrategyFromConfig(_ context.Context, request *btrpc } } - customSettings := make(map[string]interface{}, len(request.Config.StrategySettings.CustomSettings)) + customSettings := make(map[string]any, len(request.Config.StrategySettings.CustomSettings)) for i := range request.Config.StrategySettings.CustomSettings { customSettings[request.Config.StrategySettings.CustomSettings[i].KeyField] = request.Config.StrategySettings.CustomSettings[i].KeyValue } diff --git a/backtester/engine/taskmanager.go b/backtester/engine/taskmanager.go index 33674eca..7b5a6394 100644 --- a/backtester/engine/taskmanager.go +++ b/backtester/engine/taskmanager.go @@ -3,6 +3,7 @@ package engine import ( "errors" "fmt" + "slices" "github.com/gofrs/uuid" gctcommon "github.com/thrasher-corp/gocryptotrader/common" @@ -185,7 +186,7 @@ func (r *TaskManager) ClearTask(id uuid.UUID) error { if r.tasks[i].IsRunning() { return fmt.Errorf("%w %v, currently running. Stop it first", errCannotClear, r.tasks[i].MetaData.ID) } - r.tasks = append(r.tasks[:i], r.tasks[i+1:]...) + r.tasks = slices.Delete(r.tasks, i, i+1) return nil } return fmt.Errorf("%s %w", id, errTaskNotFound) @@ -208,7 +209,7 @@ func (r *TaskManager) ClearAllTasks() (clearedRuns, remainingRuns []*TaskSummary remainingRuns = append(remainingRuns, run) } else { clearedRuns = append(clearedRuns, run) - r.tasks = append(r.tasks[:i], r.tasks[i+1:]...) + r.tasks = slices.Delete(r.tasks, i, i+1) i-- } } diff --git a/backtester/eventhandlers/statistics/statistics_types.go b/backtester/eventhandlers/statistics/statistics_types.go index f1724a74..0861673d 100644 --- a/backtester/eventhandlers/statistics/statistics_types.go +++ b/backtester/eventhandlers/statistics/statistics_types.go @@ -173,7 +173,7 @@ type CurrencyPairStatistic struct { Events []DataAtOffset `json:"-"` - MaxDrawdown Swing `json:"max-drawdown,omitempty"` + MaxDrawdown Swing `json:"max-drawdown"` HighestCommittedFunds ValueAtTime `json:"highest-committed-funds"` GeometricRatios *Ratios `json:"geometric-ratios"` ArithmeticRatios *Ratios `json:"arithmetic-ratios"` diff --git a/backtester/eventhandlers/strategies/binancecashandcarry/binancecashandcarry.go b/backtester/eventhandlers/strategies/binancecashandcarry/binancecashandcarry.go index 7c7e519c..abf2f969 100644 --- a/backtester/eventhandlers/strategies/binancecashandcarry/binancecashandcarry.go +++ b/backtester/eventhandlers/strategies/binancecashandcarry/binancecashandcarry.go @@ -278,7 +278,7 @@ func sortSignals(d []data.Handler) ([]cashCarrySignals, error) { } // SetCustomSettings can override default settings -func (s *Strategy) SetCustomSettings(customSettings map[string]interface{}) error { +func (s *Strategy) SetCustomSettings(customSettings map[string]any) error { for k, v := range customSettings { switch k { case openShortDistancePercentageString: diff --git a/backtester/eventhandlers/strategies/binancecashandcarry/binancecashandcarry_test.go b/backtester/eventhandlers/strategies/binancecashandcarry/binancecashandcarry_test.go index bc7243a9..3da764fc 100644 --- a/backtester/eventhandlers/strategies/binancecashandcarry/binancecashandcarry_test.go +++ b/backtester/eventhandlers/strategies/binancecashandcarry/binancecashandcarry_test.go @@ -58,7 +58,7 @@ func TestSetCustomSettings(t *testing.T) { t.Errorf("received: %v, expected: %v", err, nil) } float14 := float64(14) - mappalopalous := make(map[string]interface{}) + mappalopalous := make(map[string]any) mappalopalous[openShortDistancePercentageString] = float14 mappalopalous[closeShortDistancePercentageString] = float14 diff --git a/backtester/eventhandlers/strategies/dollarcostaverage/dollarcostaverage.go b/backtester/eventhandlers/strategies/dollarcostaverage/dollarcostaverage.go index b42557d2..bb7bcf6e 100644 --- a/backtester/eventhandlers/strategies/dollarcostaverage/dollarcostaverage.go +++ b/backtester/eventhandlers/strategies/dollarcostaverage/dollarcostaverage.go @@ -87,7 +87,7 @@ func (s *Strategy) OnSimultaneousSignals(d []data.Handler, _ funding.IFundingTra } // SetCustomSettings not required for DCA -func (s *Strategy) SetCustomSettings(_ map[string]interface{}) error { +func (s *Strategy) SetCustomSettings(_ map[string]any) error { return base.ErrCustomSettingsUnsupported } diff --git a/backtester/eventhandlers/strategies/rsi/rsi.go b/backtester/eventhandlers/strategies/rsi/rsi.go index 4afc15d3..8b6faa27 100644 --- a/backtester/eventhandlers/strategies/rsi/rsi.go +++ b/backtester/eventhandlers/strategies/rsi/rsi.go @@ -135,7 +135,7 @@ func (s *Strategy) OnSimultaneousSignals(d []data.Handler, _ funding.IFundingTra } // SetCustomSettings allows a user to modify the RSI limits in their config -func (s *Strategy) SetCustomSettings(customSettings map[string]interface{}) error { +func (s *Strategy) SetCustomSettings(customSettings map[string]any) error { for k, v := range customSettings { switch k { case rsiHighKey: diff --git a/backtester/eventhandlers/strategies/rsi/rsi_test.go b/backtester/eventhandlers/strategies/rsi/rsi_test.go index 75218683..3dcc522e 100644 --- a/backtester/eventhandlers/strategies/rsi/rsi_test.go +++ b/backtester/eventhandlers/strategies/rsi/rsi_test.go @@ -44,7 +44,7 @@ func TestSetCustomSettings(t *testing.T) { t.Errorf("received: %v, expected: %v", err, nil) } float14 := float64(14) - mappalopalous := make(map[string]interface{}) + mappalopalous := make(map[string]any) mappalopalous[rsiPeriodKey] = float14 mappalopalous[rsiLowKey] = float14 mappalopalous[rsiHighKey] = float14 diff --git a/backtester/eventhandlers/strategies/strategies_test.go b/backtester/eventhandlers/strategies/strategies_test.go index d17a7bfd..5f199360 100644 --- a/backtester/eventhandlers/strategies/strategies_test.go +++ b/backtester/eventhandlers/strategies/strategies_test.go @@ -137,7 +137,7 @@ func (s *customStrategy) createSignal(_ data.Handler) (*signal.Signal, error) { return nil, nil } -func (s *customStrategy) SetCustomSettings(map[string]interface{}) error { +func (s *customStrategy) SetCustomSettings(map[string]any) error { return nil } diff --git a/backtester/eventhandlers/strategies/strategies_types.go b/backtester/eventhandlers/strategies/strategies_types.go index 203b9d35..9666d9b5 100644 --- a/backtester/eventhandlers/strategies/strategies_types.go +++ b/backtester/eventhandlers/strategies/strategies_types.go @@ -25,7 +25,7 @@ type Handler interface { UsingSimultaneousProcessing() bool SupportsSimultaneousProcessing() bool SetSimultaneousProcessing(bool) - SetCustomSettings(map[string]interface{}) error + SetCustomSettings(map[string]any) error SetDefaults() CloseAllPositions([]holdings.Holding, []data.Event) ([]signal.Event, error) } diff --git a/backtester/eventhandlers/strategies/top2bottom2/top2bottom2.go b/backtester/eventhandlers/strategies/top2bottom2/top2bottom2.go index 99a15f22..79ce147a 100644 --- a/backtester/eventhandlers/strategies/top2bottom2/top2bottom2.go +++ b/backtester/eventhandlers/strategies/top2bottom2/top2bottom2.go @@ -211,7 +211,7 @@ func (s *Strategy) selectTopAndBottomPerformers(mfiFundEvents []mfiFundEvent, re } // SetCustomSettings allows a user to modify the MFI limits in their config -func (s *Strategy) SetCustomSettings(customSettings map[string]interface{}) error { +func (s *Strategy) SetCustomSettings(customSettings map[string]any) error { for k, v := range customSettings { switch k { case mfiHighKey: diff --git a/backtester/eventhandlers/strategies/top2bottom2/top2bottom2_test.go b/backtester/eventhandlers/strategies/top2bottom2/top2bottom2_test.go index 7d02462d..99d34230 100644 --- a/backtester/eventhandlers/strategies/top2bottom2/top2bottom2_test.go +++ b/backtester/eventhandlers/strategies/top2bottom2/top2bottom2_test.go @@ -51,7 +51,7 @@ func TestSetCustomSettings(t *testing.T) { t.Errorf("received: %v, expected: %v", err, nil) } float14 := float64(14) - mappalopalous := make(map[string]interface{}) + mappalopalous := make(map[string]any) mappalopalous[mfiPeriodKey] = float14 mappalopalous[mfiLowKey] = float14 mappalopalous[mfiHighKey] = float14 diff --git a/backtester/eventtypes/event/event.go b/backtester/eventtypes/event/event.go index a2cce633..0db60aee 100644 --- a/backtester/eventtypes/event/event.go +++ b/backtester/eventtypes/event/event.go @@ -62,7 +62,7 @@ func (b *Base) AppendReason(y string) { // AppendReasonf adds reasoning for a decision being made // but with formatting -func (b *Base) AppendReasonf(y string, addons ...interface{}) { +func (b *Base) AppendReasonf(y string, addons ...any) { y = fmt.Sprintf(y, addons...) b.Reasons = append(b.Reasons, y) } diff --git a/backtester/funding/funding_test.go b/backtester/funding/funding_test.go index 06925d96..6af3b677 100644 --- a/backtester/funding/funding_test.go +++ b/backtester/funding/funding_test.go @@ -1016,22 +1016,22 @@ var leet = decimal.NewFromInt(1337) // caring about the response, or dealing with import cycles type fakeEvent struct{} -func (f *fakeEvent) GetHighPrice() decimal.Decimal { return leet } -func (f *fakeEvent) GetLowPrice() decimal.Decimal { return leet } -func (f *fakeEvent) GetOpenPrice() decimal.Decimal { return leet } -func (f *fakeEvent) GetVolume() decimal.Decimal { return leet } -func (f *fakeEvent) GetOffset() int64 { return 0 } -func (f *fakeEvent) SetOffset(int64) {} -func (f *fakeEvent) IsEvent() bool { return true } -func (f *fakeEvent) GetTime() time.Time { return time.Now() } -func (f *fakeEvent) Pair() currency.Pair { return pair } -func (f *fakeEvent) GetExchange() string { return exchName } -func (f *fakeEvent) GetInterval() gctkline.Interval { return gctkline.OneMin } -func (f *fakeEvent) GetAssetType() asset.Item { return asset.Spot } -func (f *fakeEvent) AppendReason(string) {} -func (f *fakeEvent) GetClosePrice() decimal.Decimal { return elite } -func (f *fakeEvent) AppendReasonf(_ string, _ ...interface{}) {} -func (f *fakeEvent) GetBase() *event.Base { return &event.Base{} } -func (f *fakeEvent) GetUnderlyingPair() currency.Pair { return pair } -func (f *fakeEvent) GetConcatReasons() string { return "" } -func (f *fakeEvent) GetReasons() []string { return nil } +func (f *fakeEvent) GetHighPrice() decimal.Decimal { return leet } +func (f *fakeEvent) GetLowPrice() decimal.Decimal { return leet } +func (f *fakeEvent) GetOpenPrice() decimal.Decimal { return leet } +func (f *fakeEvent) GetVolume() decimal.Decimal { return leet } +func (f *fakeEvent) GetOffset() int64 { return 0 } +func (f *fakeEvent) SetOffset(int64) {} +func (f *fakeEvent) IsEvent() bool { return true } +func (f *fakeEvent) GetTime() time.Time { return time.Now() } +func (f *fakeEvent) Pair() currency.Pair { return pair } +func (f *fakeEvent) GetExchange() string { return exchName } +func (f *fakeEvent) GetInterval() gctkline.Interval { return gctkline.OneMin } +func (f *fakeEvent) GetAssetType() asset.Item { return asset.Spot } +func (f *fakeEvent) AppendReason(string) {} +func (f *fakeEvent) GetClosePrice() decimal.Decimal { return elite } +func (f *fakeEvent) AppendReasonf(_ string, _ ...any) {} +func (f *fakeEvent) GetBase() *event.Base { return &event.Base{} } +func (f *fakeEvent) GetUnderlyingPair() currency.Pair { return pair } +func (f *fakeEvent) GetConcatReasons() string { return "" } +func (f *fakeEvent) GetReasons() []string { return nil } diff --git a/backtester/funding/trackingcurrencies/trackingcurrencies.go b/backtester/funding/trackingcurrencies/trackingcurrencies.go index 7a61ee33..4c66f23d 100644 --- a/backtester/funding/trackingcurrencies/trackingcurrencies.go +++ b/backtester/funding/trackingcurrencies/trackingcurrencies.go @@ -3,6 +3,7 @@ package trackingcurrencies import ( "errors" "fmt" + "slices" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/engine" @@ -101,12 +102,9 @@ func CreateUSDTrackingPairs(tp []TrackingPair, em *engine.ExchangeManager) ([]Tr // CurrencyIsUSDTracked checks if the currency passed in // tracks against USD value, ie is in rankedUSDs func CurrencyIsUSDTracked(code currency.Code) bool { - for i := range rankedUSDs { - if code.Equal(rankedUSDs[i]) { - return true - } - } - return false + return slices.ContainsFunc(rankedUSDs, func(c currency.Code) bool { + return c.Equal(code) + }) } // pairContainsUSD is a simple check to ensure that the currency pair diff --git a/backtester/plugins/strategies/example/example-strategy.go b/backtester/plugins/strategies/example/example-strategy.go index e4e240f3..161393c6 100644 --- a/backtester/plugins/strategies/example/example-strategy.go +++ b/backtester/plugins/strategies/example/example-strategy.go @@ -81,7 +81,7 @@ func (s *CustomStrategy) createSignal(d data.Handler) (*signal.Signal, error) { } // SetCustomSettings can override default settings -func (s *CustomStrategy) SetCustomSettings(map[string]interface{}) error { +func (s *CustomStrategy) SetCustomSettings(map[string]any) error { return base.ErrCustomSettingsUnsupported } diff --git a/backtester/plugins/strategies/loader_test.go b/backtester/plugins/strategies/loader_test.go index b7b22197..cb19793f 100644 --- a/backtester/plugins/strategies/loader_test.go +++ b/backtester/plugins/strategies/loader_test.go @@ -59,7 +59,7 @@ func (s *CustomStrategy) createSignal(_ data.Handler) (*signal.Signal, error) { return nil, nil } -func (s *CustomStrategy) SetCustomSettings(map[string]interface{}) error { +func (s *CustomStrategy) SetCustomSettings(map[string]any) error { return nil } diff --git a/cmd/apichecker/apicheck.go b/cmd/apichecker/apicheck.go index 4278fdd6..11f9b907 100644 --- a/cmd/apichecker/apicheck.go +++ b/cmd/apichecker/apicheck.go @@ -10,6 +10,7 @@ import ( "net/url" "os" "regexp" + "slices" "strconv" "strings" "sync" @@ -301,19 +302,16 @@ func checkExistingExchanges(exchName string) bool { // checkMissingExchanges checks if any supported exchanges are missing api checker functionality func checkMissingExchanges() []string { - tempArray := make([]string, len(usageData.Exchanges)) - for x := range usageData.Exchanges { - tempArray[x] = usageData.Exchanges[x].Name + exchanges := make([]string, len(usageData.Exchanges)) + for i, exch := range usageData.Exchanges { + exchanges[i] = exch.Name } - supportedExchs := exchange.Exchanges - for z := 0; z < len(supportedExchs); { - if common.StringSliceContainsInsensitive(tempArray, supportedExchs[z]) { - supportedExchs = append(supportedExchs[:z], supportedExchs[z+1:]...) - continue - } - z++ - } - return supportedExchs + + supportedExchs := slices.Clone(exchange.Exchanges) + + return slices.DeleteFunc(supportedExchs, func(exchName string) bool { + return common.StringSliceContainsInsensitive(exchanges, exchName) + }) } // readFileData reads the file data from the given json file @@ -461,8 +459,6 @@ func checkChangeLog(htmlData *HTMLScrapingData) (string, error) { dataStrings, err = htmlScrapeBitfinex(htmlData) case pathBitmex: dataStrings, err = htmlScrapeBitmex(htmlData) - case pathANX: - dataStrings, err = htmlScrapeANX(htmlData) case pathPoloniex: dataStrings, err = htmlScrapePoloniex(htmlData) case pathBTCMarkets: @@ -513,7 +509,7 @@ func checkChangeLog(htmlData *HTMLScrapingData) (string, error) { } // addExch appends exchange data to updates.json for future api checks -func addExch(exchName, checkType string, data interface{}, isUpdate bool) error { +func addExch(exchName, checkType string, data any, isUpdate bool) error { var file []byte if !isUpdate { if checkExistingExchanges(exchName) { @@ -554,7 +550,7 @@ func addExch(exchName, checkType string, data interface{}, isUpdate bool) error } // fillData fills exchange data based on the given checkType -func fillData(exchName, checkType string, data interface{}) (ExchangeInfo, error) { +func fillData(exchName, checkType string, data any) (ExchangeInfo, error) { switch checkType { case github: tempData, ok := data.(GithubData) @@ -743,27 +739,13 @@ func htmlScrapeHitBTC(htmlData *HTMLScrapingData) ([]string, error) { if err != nil { return nil, err } - aBody := string(a) + r, err := regexp.Compile(htmlData.RegExp) if err != nil { return nil, err } - str := r.FindAllString(aBody, -1) - var resp []string - for x := range str { - tempStr := strings.Replace(str[x], "section-v-", "", 1) - var repeat bool - for y := range resp { - if tempStr == resp[y] { - repeat = true - break - } - } - if !repeat { - resp = append(resp, tempStr) - } - } - return resp, nil + + return r.FindAllString(string(a), -1), nil } // htmlScrapeBTCMarkets gets the check string for BTCMarkets exchange @@ -844,41 +826,6 @@ loop: return resp, nil } -// htmlScrapeANX gets the check string for BTCMarkets exchange -func htmlScrapeANX(htmlData *HTMLScrapingData) ([]string, error) { - temp, err := sendHTTPGetRequest(htmlData.Path, nil) - if err != nil { - return nil, err - } - defer temp.Body.Close() - - a, err := io.ReadAll(temp.Body) - if err != nil { - return nil, err - } - aBody := string(a) - r, err := regexp.Compile(htmlData.RegExp) - if err != nil { - return nil, err - } - str := r.FindAllString(aBody, -1) - var resp []string - for x := range str { - tempStr := strings.Replace(str[x], "section-v-", "", 1) - var repeat bool - for y := range resp { - if tempStr == resp[y] { - repeat = true - break - } - } - if !repeat { - resp = append(resp, tempStr) - } - } - return resp, nil -} - // htmlScrapeExmo gets the check string for Exmo Exchange func htmlScrapeExmo(htmlData *HTMLScrapingData) ([]string, error) { header := map[string]string{ @@ -1098,7 +1045,7 @@ func trelloCreateNewCheck(newCheckName string) error { if err != nil { return err } - var resp interface{} + var resp any params := url.Values{} params.Set("name", newName) return sendAuthReq(http.MethodPost, @@ -1180,7 +1127,7 @@ func nameStateChanges(currentName, currentState string) (string, error) { // trelloUpdateCheckItem updates a check item for trello func trelloUpdateCheckItem(checkItemID, name, state string) error { - var resp interface{} + var resp any params := url.Values{} newName, err := nameStateChanges(name, state) if err != nil { @@ -1217,7 +1164,7 @@ func updateFile(name string) error { } // SendGetReq sends get req -func sendGetReq(path string, result interface{}) error { +func sendGetReq(path string, result any) error { var requester *request.Requester var err error if strings.Contains(path, "github") { @@ -1244,7 +1191,7 @@ func sendGetReq(path string, result interface{}) error { } // sendAuthReq sends auth req -func sendAuthReq(method, path string, result interface{}) error { +func sendAuthReq(method, path string, result any) error { requester, err := request.New("Apichecker", common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), request.WithLimiter(request.NewBasicRateLimit(time.Second*10, 100, 1))) @@ -1292,7 +1239,7 @@ func trelloCreateNewList() error { if trelloBoardID == "" { return errors.New("trelloBoardID not set, cannot create a new list") } - var resp interface{} + var resp any listName := createList if configData.CreateListName != "" { listName = configData.CreateListName @@ -1327,7 +1274,7 @@ func trelloDeleteCheckItem(checkitemID string) error { if checkitemID == "" { return errors.New("checkitemID cannot be empty") } - var resp interface{} + var resp any return sendAuthReq(http.MethodDelete, fmt.Sprintf(pathDeleteCheckitems, trelloChecklistID, checkitemID, apiKey, apiToken), &resp) @@ -1344,7 +1291,7 @@ func trelloCreateNewCard() error { if trelloListID == "" { return errors.New("trelloListID not set, cannot create a new checklist") } - var resp interface{} + var resp any cardName := createCard if configData.CreateCardName != "" { cardName = configData.CreateCardName @@ -1385,7 +1332,7 @@ func trelloCreateNewChecklist() error { if !areAPIKeysSet() || (trelloCardID == "") { return errors.New("apikeys or trelloCardID not set, cannot create a new checklist") } - var resp interface{} + var resp any checklistName := createChecklist if configData.CreateChecklistName != "" { checklistName = configData.CreateChecklistName @@ -1540,22 +1487,14 @@ func htmlScrapeBitfinex(htmlData *HTMLScrapingData) ([]string, error) { if err != nil { return nil, err } - str := r.FindAllString(string(a), -1) - var resp []string - for x := range str { - tempStr := strings.Replace(str[x], "section-v-", "", 1) - var repeat bool - for y := range resp { - if tempStr == resp[y] { - repeat = true - break - } - } - if !repeat { - resp = append(resp, tempStr) - } + matches := r.FindAllString(string(a), -1) + results := make([]string, 0, len(matches)) + for _, match := range matches { + s := strings.Replace(match, "section-v-", "", 1) + results = append(results, s) } - return resp, nil + slices.Sort(results) + return slices.Clip(slices.Compact(results)), nil } // htmlScrapeBinance gets checkstring for binance exchange diff --git a/cmd/apichecker/apicheck_test.go b/cmd/apichecker/apicheck_test.go index 3e33f768..fd870f54 100644 --- a/cmd/apichecker/apicheck_test.go +++ b/cmd/apichecker/apicheck_test.go @@ -5,6 +5,7 @@ import ( "reflect" "testing" + "github.com/stretchr/testify/require" gctfile "github.com/thrasher-corp/gocryptotrader/common/file" "github.com/thrasher-corp/gocryptotrader/encoding/json" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" @@ -221,15 +222,10 @@ func TestHTMLScrapeCoinbasepro(t *testing.T) { func TestHTMLScrapeBitfinex(t *testing.T) { t.Parallel() - data := HTMLScrapingData{ - DateFormat: "2006-01-02", - RegExp: `section-v-(2\d{3}-\d{1,2}-\d{1,2})`, - Path: "https://docs.bitfinex.com/docs/changelog", - } - _, err := htmlScrapeBitfinex(&data) - if err != nil { - t.Error(err) - } + data := HTMLScrapingData{DateFormat: "2006-01-02", RegExp: `section-v-(2\d{3}-\d{1,2}-\d{1,2})`, Path: "https://docs.bitfinex.com/docs/changelog"} + r, err := htmlScrapeBitfinex(&data) + require.NoError(t, err, "htmlScrapeBitfinex must not error") + require.NotEmpty(t, r, "htmlScrapeBitfinex must return a non empty result") } func TestHTMLScrapeBitmex(t *testing.T) { @@ -251,13 +247,10 @@ func TestHTMLScrapeBitmex(t *testing.T) { func TestHTMLScrapeHitBTC(t *testing.T) { t.Parallel() - data := HTMLScrapingData{ - RegExp: `newest version \d{1}.\d{1}`, - Path: "https://api.hitbtc.com/", - } - if _, err := htmlScrapeHitBTC(&data); err != nil { - t.Error(err) - } + data := HTMLScrapingData{RegExp: `newest version \d{1}.\d{1}`, Path: "https://api.hitbtc.com/"} + r, err := htmlScrapeHitBTC(&data) + require.NoError(t, err, "htmlScrapeHitBTC must not error") + require.NotEmpty(t, r, "htmlScrapeHitBTC must return a non empty result") } func TestHTMLScrapeBTSE(t *testing.T) { @@ -296,17 +289,6 @@ func TestHTMLScrapeBitflyer(t *testing.T) { } } -func TestHTMLScrapeANX(t *testing.T) { - t.Parallel() - data := HTMLScrapingData{ - RegExp: `ANX Exchange API v\d{1}`, - Path: "https://anxv3.docs.apiary.io/#reference/quickstart-catalog", - } - if _, err := htmlScrapeANX(&data); err != nil { - t.Error(err) - } -} - func TestHTMLPoloniex(t *testing.T) { t.Parallel() data := HTMLScrapingData{ diff --git a/cmd/documentation/documentation.go b/cmd/documentation/documentation.go index fa4543cb..6cd22a5b 100644 --- a/cmd/documentation/documentation.go +++ b/cmd/documentation/documentation.go @@ -9,6 +9,8 @@ import ( "net/http" "os" "path/filepath" + "slices" + "sort" "strings" "text/template" "time" @@ -313,6 +315,10 @@ func main() { }, }...) + sort.Slice(contributors, func(i, j int) bool { + return contributors[i].Contributions > contributors[j].Contributions + }) + if verbose { fmt.Println("Contributor List Fetched") for i := range contributors { @@ -391,16 +397,6 @@ func GetConfiguration() (Config, error) { return c, nil } -// IsExcluded returns if the file path is included in the exclusion list -func IsExcluded(path string, exclusion []string) bool { - for i := range exclusion { - if path == exclusion[i] { - return true - } - } - return false -} - // GetProjectDirectoryTree uses filepath walk functions to get each individual // directory name and path to match templates with func GetProjectDirectoryTree(c *Config) ([]string, error) { @@ -423,7 +419,7 @@ func GetProjectDirectoryTree(c *Config) ([]string, error) { } if info.IsDir() { // Bypass what is contained in config.json directory exclusion - if IsExcluded(info.Name(), c.Exclusions.Directories) { + if slices.Contains(c.Exclusions.Directories, info.Name()) { if verbose { fmt.Println("Excluding Directory:", info.Name()) } @@ -559,7 +555,7 @@ func UpdateDocumentation(details DocumentationDetails) { name = strings.Join(temp, " ") } - if IsExcluded(name, details.Config.Exclusions.Files) { + if slices.Contains(details.Config.Exclusions.Files, name) { if verbose { fmt.Println("Excluding file:", name) } diff --git a/cmd/exchange_wrapper_issues/main.go b/cmd/exchange_wrapper_issues/main.go index 6fb7983b..497c2114 100644 --- a/cmd/exchange_wrapper_issues/main.go +++ b/cmd/exchange_wrapper_issues/main.go @@ -357,10 +357,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}), + SentParams: jsonifyInterface([]any{p, assetTypes[i]}), Function: "UpdateTicker", Error: msg, - Response: jsonifyInterface([]interface{}{updateTickerResponse}), + Response: jsonifyInterface([]any{updateTickerResponse}), }) var GetCachedTickerResponse *ticker.Price @@ -371,10 +371,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}), + SentParams: jsonifyInterface([]any{p, assetTypes[i]}), Function: "GetCachedTicker", Error: msg, - Response: jsonifyInterface([]interface{}{GetCachedTickerResponse}), + Response: jsonifyInterface([]any{GetCachedTickerResponse}), }) var updateOrderbookResponse *orderbook.Base @@ -385,10 +385,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}), + SentParams: jsonifyInterface([]any{p, assetTypes[i]}), Function: "UpdateOrderbook", Error: msg, - Response: jsonifyInterface([]interface{}{updateOrderbookResponse}), + Response: jsonifyInterface([]any{updateOrderbookResponse}), }) var GetCachedOrderbookResponse *orderbook.Base @@ -399,10 +399,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}), + SentParams: jsonifyInterface([]any{p, assetTypes[i]}), Function: "GetCachedOrderbook", Error: msg, - Response: jsonifyInterface([]interface{}{GetCachedOrderbookResponse}), + Response: jsonifyInterface([]any{GetCachedOrderbookResponse}), }) var fetchTradablePairsResponse []currency.Pair @@ -413,10 +413,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{assetTypes[i]}), + SentParams: jsonifyInterface([]any{assetTypes[i]}), Function: "FetchTradablePairs", Error: msg, - Response: jsonifyInterface([]interface{}{fetchTradablePairsResponse}), + Response: jsonifyInterface([]any{fetchTradablePairsResponse}), }) // r6 err = e.UpdateTradablePairs(context.TODO(), false) @@ -426,10 +426,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{false}), + SentParams: jsonifyInterface([]any{false}), Function: "UpdateTradablePairs", Error: msg, - Response: jsonifyInterface([]interface{}{nil}), + Response: jsonifyInterface([]any{nil}), }) var getHistoricTradesResponse []trade.Data @@ -440,10 +440,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{p, assetTypes[i], time.Now().Add(-time.Hour), time.Now()}), + SentParams: jsonifyInterface([]any{p, assetTypes[i], time.Now().Add(-time.Hour), time.Now()}), Function: "GetHistoricTrades", Error: msg, - Response: jsonifyInterface([]interface{}{getHistoricTradesResponse}), + Response: jsonifyInterface([]any{getHistoricTradesResponse}), }) var getRecentTradesResponse []trade.Data @@ -454,10 +454,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}), + SentParams: jsonifyInterface([]any{p, assetTypes[i]}), Function: "GetRecentTrades", Error: msg, - Response: jsonifyInterface([]interface{}{getRecentTradesResponse}), + Response: jsonifyInterface([]any{getRecentTradesResponse}), }) var getHistoricCandlesResponse *kline.Item @@ -472,7 +472,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) Function: "GetHistoricCandles", Error: msg, Response: getHistoricCandlesResponse, - SentParams: jsonifyInterface([]interface{}{p, assetTypes[i], startTime, endTime, kline.OneDay}), + SentParams: jsonifyInterface([]any{p, assetTypes[i], startTime, endTime, kline.OneDay}), }) var getHistoricCandlesExtendedResponse *kline.Item @@ -486,7 +486,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) Function: "GetHistoricCandlesExtended", Error: msg, Response: getHistoricCandlesExtendedResponse, - SentParams: jsonifyInterface([]interface{}{p, assetTypes[i], startTime, endTime, kline.OneDay}), + SentParams: jsonifyInterface([]any{p, assetTypes[i], startTime, endTime, kline.OneDay}), }) var getServerTimeResponse time.Time @@ -500,7 +500,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) Function: "GetServerTime", Error: msg, Response: getServerTimeResponse, - SentParams: jsonifyInterface([]interface{}{assetTypes[i]}), + SentParams: jsonifyInterface([]any{assetTypes[i]}), }) err = e.UpdateOrderExecutionLimits(context.TODO(), assetTypes[i]) @@ -511,10 +511,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{assetTypes[i]}), + SentParams: jsonifyInterface([]any{assetTypes[i]}), Function: "UpdateOrderExecutionLimits", Error: msg, - Response: jsonifyInterface([]interface{}{""}), + Response: jsonifyInterface([]any{""}), }) fundingRateRequest := &fundingrate.HistoricalRatesRequest{ @@ -532,10 +532,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{fundingRateRequest}), + SentParams: jsonifyInterface([]any{fundingRateRequest}), Function: "GetFundingRates", Error: msg, - Response: jsonifyInterface([]interface{}{fundingRateResponse}), + Response: jsonifyInterface([]any{fundingRateResponse}), }) var isPerpetualFutures bool @@ -546,10 +546,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{assetTypes[i], p}), + SentParams: jsonifyInterface([]any{assetTypes[i], p}), Function: "IsPerpetualFutureCurrency", Error: msg, - Response: jsonifyInterface([]interface{}{isPerpetualFutures}), + Response: jsonifyInterface([]any{isPerpetualFutures}), }) } @@ -563,7 +563,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ Function: "GetCachedAccountInfo", Error: msg, - Response: jsonifyInterface([]interface{}{GetCachedAccountInfoResponse}), + Response: jsonifyInterface([]any{GetCachedAccountInfoResponse}), }) var getFundingHistoryResponse []exchange.FundingHistory @@ -576,7 +576,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ Function: "GetAccountFundingHistory", Error: msg, - Response: jsonifyInterface([]interface{}{getFundingHistoryResponse}), + Response: jsonifyInterface([]any{getFundingHistoryResponse}), }) feeType := exchange.FeeBuilder{ @@ -593,10 +593,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{feeType}), + SentParams: jsonifyInterface([]any{feeType}), Function: "GetFeeByType-Trade", Error: msg, - Response: jsonifyInterface([]interface{}{getFeeByTypeResponse}), + Response: jsonifyInterface([]any{getFeeByTypeResponse}), }) s := &order.Submit{ @@ -617,10 +617,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{*s}), + SentParams: jsonifyInterface([]any{*s}), Function: "SubmitOrder", Error: msg, - Response: jsonifyInterface([]interface{}{submitOrderResponse}), + Response: jsonifyInterface([]any{submitOrderResponse}), }) modifyRequest := order.Modify{ @@ -639,7 +639,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{modifyRequest}), + SentParams: jsonifyInterface([]any{modifyRequest}), Function: "ModifyOrder", Error: msg, Response: modifyOrderResponse, @@ -658,10 +658,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{cancelRequest}), + SentParams: jsonifyInterface([]any{cancelRequest}), Function: "CancelOrder", Error: msg, - Response: jsonifyInterface([]interface{}{nil}), + Response: jsonifyInterface([]any{nil}), }) var request []order.Cancel @@ -680,10 +680,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{cancelRequest}), + SentParams: jsonifyInterface([]any{cancelRequest}), Function: "CancelBatchOrders", Error: msg, - Response: jsonifyInterface([]interface{}{CancelBatchOrdersResponse}), + Response: jsonifyInterface([]any{CancelBatchOrdersResponse}), }) var cancellAllOrdersResponse order.CancelAllResponse @@ -694,10 +694,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{cancelRequest}), + SentParams: jsonifyInterface([]any{cancelRequest}), Function: "CancelAllOrders", Error: msg, - Response: jsonifyInterface([]interface{}{cancellAllOrdersResponse}), + Response: jsonifyInterface([]any{cancellAllOrdersResponse}), }) var r15 *order.Detail @@ -708,10 +708,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{config.OrderSubmission.OrderID, p, assetTypes[i]}), + SentParams: jsonifyInterface([]any{config.OrderSubmission.OrderID, p, assetTypes[i]}), Function: "GetOrderInfo", Error: msg, - Response: jsonifyInterface([]interface{}{r15}), + Response: jsonifyInterface([]any{r15}), }) historyRequest := order.MultiOrderRequest{ @@ -730,10 +730,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{historyRequest}), + SentParams: jsonifyInterface([]any{historyRequest}), Function: "GetOrderHistory", Error: msg, - Response: jsonifyInterface([]interface{}{getOrderHistoryResponse}), + Response: jsonifyInterface([]any{getOrderHistoryResponse}), }) orderRequest := order.MultiOrderRequest{ @@ -752,10 +752,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{orderRequest}), + SentParams: jsonifyInterface([]any{orderRequest}), Function: "GetActiveOrders", Error: msg, - Response: jsonifyInterface([]interface{}{getActiveOrdersResponse}), + Response: jsonifyInterface([]any{getActiveOrdersResponse}), }) var getDepositAddressResponse *deposit.Address @@ -766,7 +766,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{p.Base, ""}), + SentParams: jsonifyInterface([]any{p.Base, ""}), Function: "GetDepositAddress", Error: msg, Response: getDepositAddressResponse, @@ -786,10 +786,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{feeType}), + SentParams: jsonifyInterface([]any{feeType}), Function: "GetFeeByType-Crypto-Withdraw", Error: msg, - Response: jsonifyInterface([]interface{}{GetFeeByTypeResponse}), + Response: jsonifyInterface([]any{GetFeeByTypeResponse}), }) withdrawRequest := withdraw.Request{ @@ -811,7 +811,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{withdrawRequest}), + SentParams: jsonifyInterface([]any{withdrawRequest}), Function: "WithdrawCryptocurrencyFunds", Error: msg, Response: withdrawCryptocurrencyFundsResponse, @@ -833,10 +833,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{feeType}), + SentParams: jsonifyInterface([]any{feeType}), Function: "GetFeeByType-FIAT-Withdraw", Error: msg, - Response: jsonifyInterface([]interface{}{getFeeByTypeFiatResponse}), + Response: jsonifyInterface([]any{getFeeByTypeFiatResponse}), }) withdrawRequestFiat := withdraw.Request{ @@ -876,7 +876,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{withdrawRequestFiat}), + SentParams: jsonifyInterface([]any{withdrawRequestFiat}), Function: "WithdrawFiatFunds", Error: msg, Response: withdrawFiatFundsResponse, @@ -889,7 +889,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{withdrawRequestFiat}), + SentParams: jsonifyInterface([]any{withdrawRequestFiat}), Function: "WithdrawFiatFundsToInternationalBank", Error: msg, Response: withdrawFiatFundsInternationalResponse, @@ -913,7 +913,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{marginRateHistoryRequest}), + SentParams: jsonifyInterface([]any{marginRateHistoryRequest}), Function: "GetMarginRatesHistory", Error: msg, Response: marginRateHistoryResponse, @@ -931,10 +931,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{positionSummaryRequest}), + SentParams: jsonifyInterface([]any{positionSummaryRequest}), Function: "GetFuturesPositionSummary", Error: msg, - Response: jsonifyInterface([]interface{}{positionSummaryResponse}), + Response: jsonifyInterface([]any{positionSummaryResponse}), }) calculatePNLRequest := &futures.PNLCalculatorRequest{ @@ -957,10 +957,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{calculatePNLRequest}), + SentParams: jsonifyInterface([]any{calculatePNLRequest}), Function: "CalculatePNL", Error: msg, - Response: jsonifyInterface([]interface{}{calculatePNLResponse}), + Response: jsonifyInterface([]any{calculatePNLResponse}), }) collateralCalculator := &futures.CollateralCalculator{ @@ -980,10 +980,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{collateralCalculator}), + SentParams: jsonifyInterface([]any{collateralCalculator}), Function: "ScaleCollateral", Error: msg, - Response: jsonifyInterface([]interface{}{scaleCollateralResponse}), + Response: jsonifyInterface([]any{scaleCollateralResponse}), }) totalCollateralCalculator := &futures.TotalCollateralCalculator{ @@ -997,10 +997,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{totalCollateralCalculator}), + SentParams: jsonifyInterface([]any{totalCollateralCalculator}), Function: "CalculateTotalCollateral", Error: msg, - Response: jsonifyInterface([]interface{}{calculateTotalCollateralResponse}), + Response: jsonifyInterface([]any{calculateTotalCollateralResponse}), }) var futuresPositionsResponse []futures.PositionResponse @@ -1016,10 +1016,10 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.ErrorCount++ } responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{futuresPositionsRequest}), + SentParams: jsonifyInterface([]any{futuresPositionsRequest}), Function: "GetFuturesPositionOrders", Error: msg, - Response: jsonifyInterface([]interface{}{futuresPositionsResponse}), + Response: jsonifyInterface([]any{futuresPositionsResponse}), }) response = append(response, responseContainer) @@ -1027,7 +1027,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) return response } -func jsonifyInterface(params []interface{}) json.RawMessage { +func jsonifyInterface(params []any) json.RawMessage { response, _ := json.MarshalIndent(params, "", " ") return response } diff --git a/cmd/exchange_wrapper_issues/types.go b/cmd/exchange_wrapper_issues/types.go index 66a50050..770667f0 100644 --- a/cmd/exchange_wrapper_issues/types.go +++ b/cmd/exchange_wrapper_issues/types.go @@ -57,7 +57,7 @@ type ExchangeAssetPairResponses struct { type EndpointResponse struct { Function string `json:"function"` Error string `json:"error"` - Response interface{} `json:"response"` + Response any `json:"response"` SentParams json.RawMessage `json:"sentParams"` } diff --git a/cmd/exchange_wrapper_standards/exchange_wrapper_standards_test.go b/cmd/exchange_wrapper_standards/exchange_wrapper_standards_test.go index d6d10853..8e6f8116 100644 --- a/cmd/exchange_wrapper_standards/exchange_wrapper_standards_test.go +++ b/cmd/exchange_wrapper_standards/exchange_wrapper_standards_test.go @@ -170,6 +170,17 @@ func isUnacceptableError(t *testing.T, err error) error { return err } +var validWrapperParams = []reflect.Type{ + assetParam, + orderSubmitParam, + orderModifyParam, + orderCancelParam, + orderCancelsParam, + pairKeySliceParam, + getOrdersRequestParam, + latestRateRequest, +} + func executeExchangeWrapperTests(ctx context.Context, t *testing.T, exch exchange.IBotExchange, assetParams []assetPair) { t.Helper() iExchange := reflect.TypeOf(&exch).Elem() @@ -184,15 +195,11 @@ func executeExchangeWrapperTests(ctx context.Context, t *testing.T, exch exchang var assetLen int for y := range method.Type().NumIn() { input := method.Type().In(y) - for _, t := range []reflect.Type{ - assetParam, orderSubmitParam, orderModifyParam, orderCancelParam, orderCancelsParam, pairKeySliceParam, getOrdersRequestParam, latestRateRequest, - } { - if input.AssignableTo(t) { - // this allows wrapper functions that support assets types - // to be tested with all supported assets - assetLen = len(assetParams) - 1 - break - } + if slices.ContainsFunc(validWrapperParams, func(t reflect.Type) bool { + return input.AssignableTo(t) + }) { + assetLen = len(assetParams) - 1 + break } } tt := time.Now() @@ -239,7 +246,7 @@ func CallExchangeMethod(t *testing.T, methodToCall reflect.Value, methodValues [ continue } if isUnacceptableError(t, err) != nil { - literalInputs := make([]interface{}, len(methodValues)) + literalInputs := make([]any, len(methodValues)) for j := range methodValues { if methodValues[j].Kind() == reflect.Ptr { // dereference pointers just to add a bit more clarity @@ -699,12 +706,7 @@ func isFiat(t *testing.T, c string) bool { currency.ZCAD.Item.Lower, currency.ZJPY.Item.Lower, } - for i := range fiats { - if fiats[i] == c { - return true - } - } - return false + return slices.Contains(fiats, c) } // disruptFormatting adds in an unused delimiter and strange casing features to diff --git a/cmd/gctcli/main.go b/cmd/gctcli/main.go index 6da2e8e1..59249ff9 100644 --- a/cmd/gctcli/main.go +++ b/cmd/gctcli/main.go @@ -35,7 +35,7 @@ var ( const defaultTimeout = time.Second * 30 -func jsonOutput(in interface{}) { +func jsonOutput(in any) { j, err := json.MarshalIndent(in, "", " ") if err != nil { return diff --git a/cmd/gctcli/orderbook.go b/cmd/gctcli/orderbook.go index 573f8aa8..8255f02f 100644 --- a/cmd/gctcli/orderbook.go +++ b/cmd/gctcli/orderbook.go @@ -371,7 +371,6 @@ func getOrderbook(c *cli.Context) error { var ( exchangeName, pair, assetType string - depthLimit int64 exchangeStyle bool err error ) @@ -407,12 +406,15 @@ func getOrderbook(c *cli.Context) error { } } - if c.IsSet("depthlimit") { - depthLimit = c.Int64("depthlimit") - } else if c.Args().Get(4) != "" { - depthLimit, err = strconv.ParseInt(c.Args().Get(4), 10, 64) - if err != nil { + const depthCeiling uint64 = 100 // The maximum the depth can be regardless of user entry + depthLimit := depthCeiling + if d := c.Uint64("depthlimit"); d > 0 && d < depthCeiling { + depthLimit = d + } else if d := c.Args().Get(4); d != "" { + if du, err := strconv.ParseUint(d, 10, 64); err != nil { return err + } else if du > 0 && du < depthCeiling { + depthLimit = du } } @@ -449,20 +451,9 @@ func getOrderbook(c *cli.Context) error { } if exchangeStyle { - var maxLen, bidLen, askLen int64 - bidLen = int64(len(result.Bids) - 1) - askLen = int64(len(result.Asks) - 1) - if bidLen >= askLen { - maxLen = bidLen - } else { - maxLen = askLen - } - if depthLimit > 0 && depthLimit < maxLen { - maxLen = depthLimit - } - if maxLen > 100 { - maxLen = 100 - } + bidLen := uint64(len(result.Bids) - 1) //nolint:gosec // Can fit in uint64 + askLen := uint64(len(result.Asks) - 1) //nolint:gosec // Can fit in uint64 + maxLen := min(max(bidLen, askLen), depthLimit) renderOrderbookExchangeStyle(result, exchangeName, assetType, maxLen, askLen, bidLen) } else { jsonOutput(result) @@ -516,7 +507,6 @@ func getOrderbookStream(c *cli.Context) error { var ( exchangeName, pair, assetType string - depthLimit int64 exchangeStyle bool err error ) @@ -552,12 +542,15 @@ func getOrderbookStream(c *cli.Context) error { } } - if c.IsSet("depthlimit") { - depthLimit = c.Int64("depthlimit") - } else if c.Args().Get(4) != "" { - depthLimit, err = strconv.ParseInt(c.Args().Get(4), 10, 64) - if err != nil { + const depthCeiling uint64 = 50 // The maximum the depth can be regardless of user entry + depthLimit := depthCeiling + if d := c.Uint64("depthlimit"); d > 0 && d < depthCeiling { + depthLimit = d + } else if d := c.Args().Get(4); d != "" { + if du, err := strconv.ParseUint(d, 10, 64); err != nil { return err + } else if du > 0 && du < depthCeiling { + depthLimit = du } } @@ -610,21 +603,9 @@ func getOrderbookStream(c *cli.Context) error { continue } - bidLen := int64(len(resp.Bids) - 1) - askLen := int64(len(resp.Asks) - 1) - - var maxLen int64 - if bidLen >= askLen { - maxLen = bidLen - } else { - maxLen = askLen - } - if depthLimit > 0 && depthLimit < maxLen { - maxLen = depthLimit - } - if maxLen > 50 { - maxLen = 50 - } + bidLen := uint64(len(resp.Bids) - 1) //nolint:gosec // Can fit in uint64 + askLen := uint64(len(resp.Asks) - 1) //nolint:gosec // Can fit in uint64 + maxLen := min(max(bidLen, askLen), depthLimit) if exchangeStyle { renderOrderbookExchangeStyle(resp, exchangeName, assetType, maxLen, askLen, bidLen) @@ -660,7 +641,7 @@ func getOrderbookStream(c *cli.Context) error { } } -func renderOrderbookExchangeStyle(resp *gctrpc.OrderbookResponse, exchangeName, assetType string, maxLen, askLen, bidLen int64) { +func renderOrderbookExchangeStyle(resp *gctrpc.OrderbookResponse, exchangeName, assetType string, maxLen, askLen, bidLen uint64) { maxLen-- // ensure we get the 0 index at the correct max length upperBase := strings.ToUpper(resp.Pair.Base) upperQuote := strings.ToUpper(resp.Pair.Quote) @@ -670,16 +651,17 @@ func renderOrderbookExchangeStyle(resp *gctrpc.OrderbookResponse, exchangeName, fmt.Printf("%sPrice(%v)\t\tAmount(%s)\n", grayText, upperQuote, upperBase) - for i := maxLen; i >= 0; i-- { + for i := uint64(0); i <= maxLen; i++ { + j := maxLen - i var askAmount, askPrice float64 - if i <= askLen { - askAmount = resp.Asks[i].Amount - askPrice = resp.Asks[i].Price + if j <= askLen { + askAmount = resp.Asks[j].Amount + askPrice = resp.Asks[j].Price } fmt.Printf(printFmt, redText, askPrice, askAmount) } fmt.Println() - for i := int64(0); i <= maxLen; i++ { + for i := uint64(0); i <= maxLen; i++ { var bidAmount, bidPrice float64 if i <= bidLen { bidAmount = resp.Bids[i].Amount diff --git a/cmd/websocket_client/main.go b/cmd/websocket_client/main.go index 24929bf0..274f4a55 100644 --- a/cmd/websocket_client/main.go +++ b/cmd/websocket_client/main.go @@ -26,7 +26,7 @@ type WebsocketEvent struct { Exchange string `json:"exchange,omitempty"` AssetType string `json:"assetType,omitempty"` Event string - Data interface{} + Data any } // WebsocketAuth is the struct used for a websocket auth request @@ -37,9 +37,9 @@ type WebsocketAuth struct { // WebsocketEventResponse is the struct used for websocket event responses type WebsocketEventResponse struct { - Event string `json:"event"` - Data interface{} `json:"data"` - Error string `json:"error"` + Event string `json:"event"` + Data any `json:"data"` + Error string `json:"error"` } // WebsocketOrderbookTickerRequest is a struct used for ticker and orderbook @@ -51,7 +51,7 @@ type WebsocketOrderbookTickerRequest struct { } // SendWebsocketEvent sends a websocket event message -func SendWebsocketEvent(event string, reqData interface{}, result *WebsocketEventResponse) error { +func SendWebsocketEvent(event string, reqData any, result *WebsocketEventResponse) error { req := WebsocketEvent{ Event: event, } diff --git a/common/cache/cache.go b/common/cache/cache.go index 038141aa..2c859dd3 100644 --- a/common/cache/cache.go +++ b/common/cache/cache.go @@ -8,35 +8,35 @@ func New(capacity uint64) *LRUCache { } // Add new entry to Cache return true if entry removed -func (l *LRUCache) Add(k, v interface{}) { +func (l *LRUCache) Add(k, v any) { l.m.Lock() l.lru.Add(k, v) l.m.Unlock() } // Get looks up a key's value from the cache. -func (l *LRUCache) Get(key interface{}) (value interface{}) { +func (l *LRUCache) Get(key any) (value any) { l.m.Lock() defer l.m.Unlock() return l.lru.Get(key) } // GetOldest looks up old key's value from the cache. -func (l *LRUCache) getOldest() (key, value interface{}) { +func (l *LRUCache) getOldest() (key, value any) { l.m.Lock() defer l.m.Unlock() return l.lru.getOldest() } // getNewest looks up a key's value from the cache. -func (l *LRUCache) getNewest() (key, value interface{}) { +func (l *LRUCache) getNewest() (key, value any) { l.m.Lock() defer l.m.Unlock() return l.lru.getNewest() } // ContainsOrAdd checks if cache contains key if not adds to cache -func (l *LRUCache) ContainsOrAdd(key, value interface{}) bool { +func (l *LRUCache) ContainsOrAdd(key, value any) bool { l.m.Lock() defer l.m.Unlock() if l.lru.Contains(key) { @@ -47,14 +47,14 @@ func (l *LRUCache) ContainsOrAdd(key, value interface{}) bool { } // Contains checks if cache contains key -func (l *LRUCache) Contains(key interface{}) bool { +func (l *LRUCache) Contains(key any) bool { l.m.Lock() defer l.m.Unlock() return l.lru.Contains(key) } // Remove entry from cache -func (l *LRUCache) Remove(key interface{}) bool { +func (l *LRUCache) Remove(key any) bool { l.m.Lock() defer l.m.Unlock() return l.lru.Remove(key) diff --git a/common/cache/cache_types.go b/common/cache/cache_types.go index 64605340..7aa43122 100644 --- a/common/cache/cache_types.go +++ b/common/cache/cache_types.go @@ -15,11 +15,11 @@ type LRUCache struct { type LRU struct { Cap uint64 l *list.List - items map[interface{}]*list.Element + items map[any]*list.Element } // item holds key/value for the cache type item struct { - key interface{} - value interface{} + key any + value any } diff --git a/common/cache/lru.go b/common/cache/lru.go index 812b7adf..173dc0f6 100644 --- a/common/cache/lru.go +++ b/common/cache/lru.go @@ -16,12 +16,12 @@ func NewLRUCache(capacity uint64) *LRU { return &LRU{ Cap: capacity, l: list.New(), - items: make(map[interface{}]*list.Element), + items: make(map[any]*list.Element), } } // Add adds a value to the cache -func (l *LRU) Add(key, value interface{}) { +func (l *LRU) Add(key, value any) { if f, o := l.items[key]; o { l.l.MoveToFront(f) if v, ok := f.Value.(*item); ok { @@ -39,7 +39,7 @@ func (l *LRU) Add(key, value interface{}) { } // Get returns keys value from cache if found -func (l *LRU) Get(key interface{}) interface{} { +func (l *LRU) Get(key any) any { if i, f := l.items[key]; f { l.l.MoveToFront(i) if v, ok := i.Value.(*item); ok { @@ -50,7 +50,7 @@ func (l *LRU) Get(key interface{}) interface{} { } // GetOldest returns the oldest entry -func (l *LRU) getOldest() (key, value interface{}) { +func (l *LRU) getOldest() (key, value any) { if x := l.l.Back(); x != nil { if v, ok := x.Value.(*item); ok { return v.key, v.value @@ -60,7 +60,7 @@ func (l *LRU) getOldest() (key, value interface{}) { } // GetNewest returns the newest entry -func (l *LRU) getNewest() (key, value interface{}) { +func (l *LRU) getNewest() (key, value any) { if x := l.l.Front(); x != nil { if v, ok := x.Value.(*item); ok { return v.key, v.value @@ -70,13 +70,13 @@ func (l *LRU) getNewest() (key, value interface{}) { } // Contains check if key is in cache this does not update LRU -func (l *LRU) Contains(key interface{}) (f bool) { +func (l *LRU) Contains(key any) (f bool) { _, f = l.items[key] return } // Remove removes key from the cache, if the key was removed. -func (l *LRU) Remove(key interface{}) bool { +func (l *LRU) Remove(key any) bool { if i, f := l.items[key]; f { l.removeElement(i) return true diff --git a/common/common.go b/common/common.go index 79d11951..81728731 100644 --- a/common/common.go +++ b/common/common.go @@ -594,7 +594,7 @@ func GenerateRandomString(length uint, characters ...string) (string, error) { // GetTypeAssertError returns additional information for when an assertion failure // occurs. // fieldDescription is an optional way to return what the affected field was for -func GetTypeAssertError(required string, received interface{}, fieldDescription ...string) error { +func GetTypeAssertError(required string, received any, fieldDescription ...string) error { var description string if len(fieldDescription) > 0 { description = " for: " + strings.Join(fieldDescription, ", ") diff --git a/common/convert/convert.go b/common/convert/convert.go index ba6fb24d..1417fdd2 100644 --- a/common/convert/convert.go +++ b/common/convert/convert.go @@ -11,7 +11,7 @@ import ( ) // FloatFromString format -func FloatFromString(raw interface{}) (float64, error) { +func FloatFromString(raw any) (float64, error) { str, ok := raw.(string) if !ok { return 0, fmt.Errorf("unable to parse, value not string: %T", raw) @@ -24,7 +24,7 @@ func FloatFromString(raw interface{}) (float64, error) { } // IntFromString format -func IntFromString(raw interface{}) (int, error) { +func IntFromString(raw any) (int, error) { str, ok := raw.(string) if !ok { return 0, fmt.Errorf("unable to parse, value not string: %T", raw) @@ -37,7 +37,7 @@ func IntFromString(raw interface{}) (int, error) { } // Int64FromString format -func Int64FromString(raw interface{}) (int64, error) { +func Int64FromString(raw any) (int64, error) { str, ok := raw.(string) if !ok { return 0, fmt.Errorf("unable to parse, value not string: %T", raw) @@ -50,7 +50,7 @@ func Int64FromString(raw interface{}) (int64, error) { } // TimeFromUnixTimestampFloat format -func TimeFromUnixTimestampFloat(raw interface{}) (time.Time, error) { +func TimeFromUnixTimestampFloat(raw any) (time.Time, error) { ts, ok := raw.(float64) if !ok { return time.Time{}, fmt.Errorf("unable to parse, value not float64: %T", raw) @@ -167,7 +167,7 @@ func numberToHumanFriendlyString(str string, dec uint, decPoint, thousandsSep st } // InterfaceToFloat64OrZeroValue returns the type assertion value or variable zero value -func InterfaceToFloat64OrZeroValue(r interface{}) float64 { +func InterfaceToFloat64OrZeroValue(r any) float64 { if v, ok := r.(float64); ok { return v } @@ -175,7 +175,7 @@ func InterfaceToFloat64OrZeroValue(r interface{}) float64 { } // InterfaceToIntOrZeroValue returns the type assertion value or variable zero value -func InterfaceToIntOrZeroValue(r interface{}) int { +func InterfaceToIntOrZeroValue(r any) int { if v, ok := r.(int); ok { return v } @@ -183,7 +183,7 @@ func InterfaceToIntOrZeroValue(r interface{}) int { } // InterfaceToStringOrZeroValue returns the type assertion value or variable zero value -func InterfaceToStringOrZeroValue(r interface{}) string { +func InterfaceToStringOrZeroValue(r any) string { if v, ok := r.(string); ok { return v } diff --git a/common/convert/convert_test.go b/common/convert/convert_test.go index 934025e0..fd0627f6 100644 --- a/common/convert/convert_test.go +++ b/common/convert/convert_test.go @@ -196,7 +196,7 @@ func TestNumberToHumanFriendlyString(t *testing.T) { } func TestInterfaceToFloat64OrZeroValue(t *testing.T) { - var x interface{} + var x any if r := InterfaceToFloat64OrZeroValue(x); r != 0 { t.Errorf("expected 0, got: %v", r) } @@ -207,7 +207,7 @@ func TestInterfaceToFloat64OrZeroValue(t *testing.T) { } func TestInterfaceToIntOrZeroValue(t *testing.T) { - var x interface{} + var x any if r := InterfaceToIntOrZeroValue(x); r != 0 { t.Errorf("expected 0, got: %v", r) } @@ -218,7 +218,7 @@ func TestInterfaceToIntOrZeroValue(t *testing.T) { } func TestInterfaceToStringOrZeroValue(t *testing.T) { - var x interface{} + var x any if r := InterfaceToStringOrZeroValue(x); r != "" { t.Errorf("expected empty string, got: %v", r) } diff --git a/communications/smsglobal/smsglobal.go b/communications/smsglobal/smsglobal.go index b03b00cd..a0fdf51e 100644 --- a/communications/smsglobal/smsglobal.go +++ b/communications/smsglobal/smsglobal.go @@ -7,6 +7,7 @@ import ( "flag" "net/http" "net/url" + "slices" "strings" "github.com/thrasher-corp/gocryptotrader/common" @@ -137,7 +138,7 @@ func (s *SMSGlobal) RemoveContact(contact Contact) error { for x := range s.Contacts { if s.Contacts[x].Name == contact.Name && s.Contacts[x].Number == contact.Number { - s.Contacts = append(s.Contacts[:x], s.Contacts[x+1:]...) + s.Contacts = slices.Delete(s.Contacts, x, x+1) return nil } } diff --git a/communications/telegram/telegram.go b/communications/telegram/telegram.go index 1ddee6dd..ad51cff5 100644 --- a/communications/telegram/telegram.go +++ b/communications/telegram/telegram.go @@ -274,7 +274,7 @@ func (t *Telegram) SendMessage(text string, chatID int64) error { } // SendHTTPRequest sends an authenticated HTTP request -func (t *Telegram) SendHTTPRequest(path string, data []byte, result interface{}) error { +func (t *Telegram) SendHTTPRequest(path string, data []byte, result any) error { headers := make(map[string]string) headers["content-type"] = "application/json" diff --git a/communications/telegram/telegram_types.go b/communications/telegram/telegram_types.go index f3fd1284..5b385501 100644 --- a/communications/telegram/telegram_types.go +++ b/communications/telegram/telegram_types.go @@ -21,14 +21,14 @@ type GetUpdateResponse struct { Result []struct { UpdateID int64 `json:"update_id"` Message MessageType `json:"message"` - EditedMessage interface{} `json:"edited_message"` - ChannelPost interface{} `json:"channel_post"` - EditedChannelPost interface{} `json:"edited_channel_post"` - InlineQuery interface{} `json:"inline_query"` - ChosenInlineResult interface{} `json:"chosen_inline_result"` - CallbackQuery interface{} `json:"callback_query"` - ShippingQuery interface{} `json:"shipping_query"` - PreCheckoutQuery interface{} `json:"pre_checkout_query"` + EditedMessage any `json:"edited_message"` + ChannelPost any `json:"channel_post"` + EditedChannelPost any `json:"edited_channel_post"` + InlineQuery any `json:"inline_query"` + ChosenInlineResult any `json:"chosen_inline_result"` + CallbackQuery any `json:"callback_query"` + ShippingQuery any `json:"shipping_query"` + PreCheckoutQuery any `json:"pre_checkout_query"` } `json:"result"` } @@ -50,7 +50,7 @@ type MessageType struct { ForwardFromMessageID int64 `json:"forward_from_message_id"` ForwardSignature string `json:"forward_signature"` ForwardDate int64 `json:"forward_date"` - ReplyToMessage interface{} `json:"reply_to_message"` + ReplyToMessage any `json:"reply_to_message"` EditDate int64 `json:"edit_date"` MediaGroupID string `json:"media_group_id"` AuthorSignature string `json:"author_signature"` diff --git a/config/config.go b/config/config.go index 5127632f..4bf5be05 100644 --- a/config/config.go +++ b/config/config.go @@ -1719,9 +1719,10 @@ func SetConfig(c *Config) { func (c *Config) RemoveExchange(exchName string) bool { m.Lock() defer m.Unlock() + for x := range c.Exchanges { if strings.EqualFold(c.Exchanges[x].Name, exchName) { - c.Exchanges = append(c.Exchanges[:x], c.Exchanges[x+1:]...) + c.Exchanges = slices.Delete(c.Exchanges, x, x+1) return true } } diff --git a/config/config_test.go b/config/config_test.go index fc8075bf..8fb4fd63 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -1369,8 +1369,7 @@ func TestCheckExchangeConfigValues(t *testing.T) { } // Make a sneaky copy for bank account testing - //nolint: gocritic - cpy := append(cfg.Exchanges[:0:0], cfg.Exchanges...) + cpy := slices.Clone(cfg.Exchanges) // Test empty exchange name for an enabled exchange cfg.Exchanges[0].Enabled = true diff --git a/config/config_types.go b/config/config_types.go index 460b6ff1..40bc7eaf 100644 --- a/config/config_types.go +++ b/config/config_types.go @@ -299,9 +299,9 @@ type BankTransaction struct { // FeaturesSupportedConfig stores the exchanges supported features type FeaturesSupportedConfig struct { REST bool `json:"restAPI"` - RESTCapabilities protocol.Features `json:"restCapabilities,omitempty"` + RESTCapabilities protocol.Features `json:"restCapabilities,omitzero"` Websocket bool `json:"websocketAPI"` - WebsocketCapabilities protocol.Features `json:"websocketCapabilities,omitempty"` + WebsocketCapabilities protocol.Features `json:"websocketCapabilities,omitzero"` } // FeaturesEnabledConfig stores the exchanges enabled features diff --git a/currency/coinmarketcap/coinmarketcap.go b/currency/coinmarketcap/coinmarketcap.go index 8d1c94ab..e6bcea3e 100644 --- a/currency/coinmarketcap/coinmarketcap.go +++ b/currency/coinmarketcap/coinmarketcap.go @@ -682,7 +682,7 @@ func (c *Coinmarketcap) GetPriceConversion(amount float64, currencyID int64, atH } // SendHTTPRequest sends a valid HTTP request -func (c *Coinmarketcap) SendHTTPRequest(method, endpoint string, v url.Values, result interface{}) error { +func (c *Coinmarketcap) SendHTTPRequest(method, endpoint string, v url.Values, result any) error { headers := make(map[string]string) headers["Accept"] = "application/json" headers["X-CMC_PRO_API_KEY"] = c.APIkey diff --git a/currency/coinmarketcap/coinmarketcap_types.go b/currency/coinmarketcap/coinmarketcap_types.go index bf010dc9..10012476 100644 --- a/currency/coinmarketcap/coinmarketcap_types.go +++ b/currency/coinmarketcap/coinmarketcap_types.go @@ -112,23 +112,23 @@ type OHLC struct { // CryptoCurrencyInfo defines cryptocurrency information type CryptoCurrencyInfo map[string]struct { - ID int `json:"id"` - Name string `json:"name"` - Symbol string `json:"symbol"` - Category string `json:"category"` - Slug string `json:"slug"` - Logo string `json:"logo"` - Tags []string `json:"tags"` - Platform interface{} `json:"platform"` + ID int `json:"id"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Category string `json:"category"` + Slug string `json:"slug"` + Logo string `json:"logo"` + Tags []string `json:"tags"` + Platform any `json:"platform"` Urls struct { - Website []string `json:"website"` - Explorer []string `json:"explorer"` - SourceCode []string `json:"source_code"` - MessageBoard []string `json:"message_board"` - Chat []interface{} `json:"chat"` - Announcement []interface{} `json:"announcement"` - Reddit []string `json:"reddit"` - Twitter []string `json:"twitter"` + Website []string `json:"website"` + Explorer []string `json:"explorer"` + SourceCode []string `json:"source_code"` + MessageBoard []string `json:"message_board"` + Chat []any `json:"chat"` + Announcement []any `json:"announcement"` + Reddit []string `json:"reddit"` + Twitter []string `json:"twitter"` } `json:"urls"` } @@ -170,19 +170,19 @@ type CryptocurrencyHistoricalListings struct { // CryptocurrencyLatestListings defines latest cryptocurrency listing data type CryptocurrencyLatestListings struct { - ID int `json:"id"` - Name string `json:"name"` - Symbol string `json:"symbol"` - Slug string `json:"slug"` - CmcRank int `json:"cmc_rank"` - NumMarketPairs int `json:"num_market_pairs"` - CirculatingSupply float64 `json:"circulating_supply"` - TotalSupply float64 `json:"total_supply"` - MaxSupply float64 `json:"max_supply"` - LastUpdated time.Time `json:"last_updated"` - DateAdded time.Time `json:"date_added"` - Tags []string `json:"tags"` - Platform interface{} `json:"platform"` + ID int `json:"id"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Slug string `json:"slug"` + CmcRank int `json:"cmc_rank"` + NumMarketPairs int `json:"num_market_pairs"` + CirculatingSupply float64 `json:"circulating_supply"` + TotalSupply float64 `json:"total_supply"` + MaxSupply float64 `json:"max_supply"` + LastUpdated time.Time `json:"last_updated"` + DateAdded time.Time `json:"date_added"` + Tags []string `json:"tags"` + Platform any `json:"platform"` Quote struct { USD Currency `json:"USD"` BTC Currency `json:"BTC"` @@ -240,12 +240,12 @@ type CryptocurrencyOHLCHistorical struct { // CryptocurrencyOHLCLatest defines open high low close latest data type CryptocurrencyOHLCLatest map[string]struct { - ID int `json:"id"` - Name string `json:"name"` - Symbol string `json:"symbol"` - LastUpdated time.Time `json:"last_updated"` - TimeOpen time.Time `json:"time_open"` - TimeClose interface{} `json:"time_close"` + ID int `json:"id"` + Name string `json:"name"` + Symbol string `json:"symbol"` + LastUpdated time.Time `json:"last_updated"` + TimeOpen time.Time `json:"time_open"` + TimeClose any `json:"time_close"` Quote struct { USD OHLC `json:"USD"` } `json:"quote"` @@ -253,19 +253,19 @@ type CryptocurrencyOHLCLatest map[string]struct { // CryptocurrencyLatestQuotes defines latest cryptocurrency quotation data type CryptocurrencyLatestQuotes map[string]struct { - ID int `json:"id"` - Name string `json:"name"` - Symbol string `json:"symbol"` - Slug string `json:"slug"` - CirculatingSupply float64 `json:"circulating_supply"` - TotalSupply float64 `json:"total_supply"` - MaxSupply float64 `json:"max_supply"` - DateAdded time.Time `json:"date_added"` - NumMarketPairs int `json:"num_market_pairs"` - CmcRank int `json:"cmc_rank"` - LastUpdated time.Time `json:"last_updated"` - Tags []string `json:"tags"` - Platform interface{} `json:"platform"` + ID int `json:"id"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Slug string `json:"slug"` + CirculatingSupply float64 `json:"circulating_supply"` + TotalSupply float64 `json:"total_supply"` + MaxSupply float64 `json:"max_supply"` + DateAdded time.Time `json:"date_added"` + NumMarketPairs int `json:"num_market_pairs"` + CmcRank int `json:"cmc_rank"` + LastUpdated time.Time `json:"last_updated"` + Tags []string `json:"tags"` + Platform any `json:"platform"` Quote struct { USD Currency `json:"USD"` } `json:"quote"` @@ -288,11 +288,11 @@ type CryptocurrencyHistoricalQuotes struct { // ExchangeInfo defines exchange information type ExchangeInfo map[string]struct { Urls struct { - Website []string `json:"website"` - Twitter []string `json:"twitter"` - Blog []interface{} `json:"blog"` - Chat []string `json:"chat"` - Fee []string `json:"fee"` + Website []string `json:"website"` + Twitter []string `json:"twitter"` + Blog []any `json:"blog"` + Chat []string `json:"chat"` + Fee []string `json:"fee"` } `json:"urls"` Logo string `json:"logo"` ID int `json:"id"` diff --git a/currency/currency_types.go b/currency/currency_types.go index 97575ed8..7647bacc 100644 --- a/currency/currency_types.go +++ b/currency/currency_types.go @@ -64,13 +64,13 @@ type FXSettings struct { // File defines a full currency file generated by the currency storage // analysis system type File struct { - LastMainUpdate interface{} `json:"lastMainUpdate"` - Cryptocurrency []*Item `json:"cryptocurrencies"` - FiatCurrency []*Item `json:"fiatCurrencies"` - UnsetCurrency []*Item `json:"unsetCurrencies"` - Contracts []*Item `json:"contracts"` - Token []*Item `json:"tokens"` - Stable []*Item `json:"stableCurrencies"` + LastMainUpdate any `json:"lastMainUpdate"` + Cryptocurrency []*Item `json:"cryptocurrencies"` + FiatCurrency []*Item `json:"fiatCurrencies"` + UnsetCurrency []*Item `json:"unsetCurrencies"` + Contracts []*Item `json:"contracts"` + Token []*Item `json:"tokens"` + Stable []*Item `json:"stableCurrencies"` } // Const here are packaged defined delimiters diff --git a/currency/forexprovider/base/base_interface.go b/currency/forexprovider/base/base_interface.go index aa001615..724b27bc 100644 --- a/currency/forexprovider/base/base_interface.go +++ b/currency/forexprovider/base/base_interface.go @@ -3,6 +3,7 @@ package base import ( "errors" "fmt" + "maps" "strings" "sync" @@ -101,9 +102,7 @@ func (f *FXHandler) GetCurrencyData(baseCurrency string, currencies []string) (m err) } - for key, val := range rateNew { - rates[key] = val - } + maps.Copy(rates, rateNew) return rates, nil } @@ -125,9 +124,7 @@ func (f *FXHandler) backupGetRate(base string, currencies []string) (map[string] continue } - for k, v := range newRate { - rate[k] = v - } + maps.Copy(rate, newRate) if len(shunt) != 0 { continue @@ -142,9 +139,7 @@ func (f *FXHandler) backupGetRate(base string, currencies []string) (map[string] continue } - for k, v := range newRate { - rate[k] = v - } + maps.Copy(rate, newRate) if len(shunt) != 0 { continue diff --git a/currency/forexprovider/currencyconverterapi/currencyconverterapi.go b/currency/forexprovider/currencyconverterapi/currencyconverterapi.go index 39fa8a7f..a03f6a07 100644 --- a/currency/forexprovider/currencyconverterapi/currencyconverterapi.go +++ b/currency/forexprovider/currencyconverterapi/currencyconverterapi.go @@ -149,7 +149,7 @@ func (c *CurrencyConverter) GetCountries() (map[string]CountryItem, error) { // SendHTTPRequest sends a HTTP request, if account is not free it automatically // upgrades request to SSL. -func (c *CurrencyConverter) SendHTTPRequest(endPoint string, values url.Values, result interface{}) error { +func (c *CurrencyConverter) SendHTTPRequest(endPoint string, values url.Values, result any) error { var path string var auth request.AuthType if c.APIKey == "" || c.APIKey == defaultAPIKey { diff --git a/currency/forexprovider/currencylayer/currencylayer.go b/currency/forexprovider/currencylayer/currencylayer.go index fb8dad49..2cd72eeb 100644 --- a/currency/forexprovider/currencylayer/currencylayer.go +++ b/currency/forexprovider/currencylayer/currencylayer.go @@ -141,7 +141,7 @@ func (c *CurrencyLayer) Convert(from, to, date string, amount float64) (float64, // QueryTimeFrame returns historical exchange rates for a time-period. // (maximum range: 365 days) -func (c *CurrencyLayer) QueryTimeFrame(startDate, endDate, baseCurrency string, currencies []string) (map[string]interface{}, error) { +func (c *CurrencyLayer) QueryTimeFrame(startDate, endDate, baseCurrency string, currencies []string) (map[string]any, error) { if c.APIKeyLvl >= AccountPro { return nil, errors.New("insufficient API privileges, upgrade to basic to use this function") } @@ -193,7 +193,7 @@ func (c *CurrencyLayer) QueryCurrencyChange(startDate, endDate, baseCurrency str // SendHTTPRequest sends a HTTP request, if account is not free it automatically // upgrades request to SSL. -func (c *CurrencyLayer) SendHTTPRequest(endPoint string, values url.Values, result interface{}) error { +func (c *CurrencyLayer) SendHTTPRequest(endPoint string, values url.Values, result any) error { var path string values.Set("access_key", c.APIKey) diff --git a/currency/forexprovider/currencylayer/currencylayer_types.go b/currency/forexprovider/currencylayer/currencylayer_types.go index 6d6351fa..a6d5b439 100644 --- a/currency/forexprovider/currencylayer/currencylayer_types.go +++ b/currency/forexprovider/currencylayer/currencylayer_types.go @@ -92,15 +92,15 @@ type ConversionRate struct { // TimeFrame is a response type holding exchange rates for a time period type TimeFrame struct { - Success bool `json:"success"` - Error Error `json:"error"` - Terms string `json:"terms"` - Privacy string `json:"privacy"` - Timeframe bool `json:"timeframe"` - StartDate string `json:"start_date"` - EndDate string `json:"end_date"` - Source string `json:"source"` - Quotes map[string]interface{} `json:"quotes"` + Success bool `json:"success"` + Error Error `json:"error"` + Terms string `json:"terms"` + Privacy string `json:"privacy"` + Timeframe bool `json:"timeframe"` + StartDate string `json:"start_date"` + EndDate string `json:"end_date"` + Source string `json:"source"` + Quotes map[string]any `json:"quotes"` } // ChangeRate is the response type that holds rate change data. diff --git a/currency/forexprovider/exchangeratesapi.io/exchangeratesapi.go b/currency/forexprovider/exchangeratesapi.io/exchangeratesapi.go index 77bca6d8..7a1cbb7f 100644 --- a/currency/forexprovider/exchangeratesapi.io/exchangeratesapi.go +++ b/currency/forexprovider/exchangeratesapi.io/exchangeratesapi.go @@ -254,7 +254,7 @@ func (e *ExchangeRates) GetSupportedCurrencies() ([]string, error) { } // SendHTTPRequest sends a HTTPS request to the desired endpoint and returns the result -func (e *ExchangeRates) SendHTTPRequest(endPoint string, values url.Values, result interface{}) error { +func (e *ExchangeRates) SendHTTPRequest(endPoint string, values url.Values, result any) error { if e.APIKey == "" { return errors.New("api key must be set") } diff --git a/currency/forexprovider/fixer.io/fixer.go b/currency/forexprovider/fixer.io/fixer.go index 50f12979..78594755 100644 --- a/currency/forexprovider/fixer.io/fixer.go +++ b/currency/forexprovider/fixer.io/fixer.go @@ -168,7 +168,7 @@ func (f *Fixer) ConvertCurrency(from, to, date string, amount float64) (float64, // GetTimeSeriesData returns daily historical exchange rate data between two // specified dates for all available or a specific set of currencies. -func (f *Fixer) GetTimeSeriesData(startDate, endDate, baseCurrency string, symbols []string) (map[string]interface{}, error) { +func (f *Fixer) GetTimeSeriesData(startDate, endDate, baseCurrency string, symbols []string) (map[string]any, error) { if f.APIKeyLvl < fixerAPIProfessional { return nil, errors.New("insufficient API privileges, upgrade to professional to use this function") } @@ -219,7 +219,7 @@ func (f *Fixer) GetFluctuationData(startDate, endDate, baseCurrency string, symb } // SendOpenHTTPRequest sends a typical get request -func (f *Fixer) SendOpenHTTPRequest(endpoint string, v url.Values, result interface{}) error { +func (f *Fixer) SendOpenHTTPRequest(endpoint string, v url.Values, result any) error { if v == nil { v = url.Values{} } diff --git a/currency/forexprovider/fixer.io/fixer_types.go b/currency/forexprovider/fixer.io/fixer_types.go index 41115508..4532c415 100644 --- a/currency/forexprovider/fixer.io/fixer_types.go +++ b/currency/forexprovider/fixer.io/fixer_types.go @@ -59,13 +59,13 @@ type Conversion struct { // TimeSeries holds timeseries data type TimeSeries struct { - Success bool `json:"success"` - Error RespError `json:"error"` - Timeseries bool `json:"timeseries"` - StartDate string `json:"start_date"` - EndDate string `json:"end_date"` - Base string `json:"base"` - Rates map[string]interface{} `json:"rates"` + Success bool `json:"success"` + Error RespError `json:"error"` + Timeseries bool `json:"timeseries"` + StartDate string `json:"start_date"` + EndDate string `json:"end_date"` + Base string `json:"base"` + Rates map[string]any `json:"rates"` } // Fluctuation holds fluctuation data diff --git a/currency/forexprovider/openexchangerates/openexchangerates.go b/currency/forexprovider/openexchangerates/openexchangerates.go index 67f113cb..2f2e2cd5 100644 --- a/currency/forexprovider/openexchangerates/openexchangerates.go +++ b/currency/forexprovider/openexchangerates/openexchangerates.go @@ -122,7 +122,7 @@ func (o *OXR) GetSupportedCurrencies() ([]string, error) { // GetTimeSeries returns historical exchange rates for a given time period, // where available. -func (o *OXR) GetTimeSeries(baseCurrency, startDate, endDate string, symbols []string, prettyPrint, showAlternative bool) (map[string]interface{}, error) { +func (o *OXR) GetTimeSeries(baseCurrency, startDate, endDate string, symbols []string, prettyPrint, showAlternative bool) (map[string]any, error) { if o.APIKeyLvl < APIEnterpriseAccess { return nil, errors.New("upgrade account, insufficient access") } @@ -170,7 +170,7 @@ func (o *OXR) ConvertCurrency(amount float64, from, to string) (float64, error) // GetOHLC returns historical Open, High Low, Close (OHLC) and Average exchange // rates for a given time period, ranging from 1 month to 1 minute, where // available. -func (o *OXR) GetOHLC(startTime, period, baseCurrency string, symbols []string, prettyPrint bool) (map[string]interface{}, error) { +func (o *OXR) GetOHLC(startTime, period, baseCurrency string, symbols []string, prettyPrint bool) (map[string]any, error) { if o.APIKeyLvl < APIUnlimitedAccess { return nil, errors.New("upgrade account, insufficient access") } @@ -213,7 +213,7 @@ func (o *OXR) GetUsageStats(prettyPrint bool) (Usage, error) { } // SendHTTPRequest sends a HTTP request -func (o *OXR) SendHTTPRequest(endpoint string, values url.Values, result interface{}) error { +func (o *OXR) SendHTTPRequest(endpoint string, values url.Values, result any) error { headers := make(map[string]string) headers["Authorization"] = "Token " + o.APIKey path := APIURL + endpoint + "?" + values.Encode() diff --git a/currency/forexprovider/openexchangerates/openexchangerates_types.go b/currency/forexprovider/openexchangerates/openexchangerates_types.go index af9ddfd1..5e57eb2c 100644 --- a/currency/forexprovider/openexchangerates/openexchangerates_types.go +++ b/currency/forexprovider/openexchangerates/openexchangerates_types.go @@ -69,16 +69,16 @@ type Historical struct { // TimeSeries holds historic rate data type TimeSeries struct { - Disclaimer string `json:"disclaimer"` - License string `json:"license"` - StartDate string `json:"start_date"` - EndDate string `json:"end_date"` - Base string `json:"base"` - Rates map[string]interface{} `json:"rates"` - Error bool `json:"error"` - Status int `json:"status"` - Message string `json:"message"` - Description string `json:"description"` + Disclaimer string `json:"disclaimer"` + License string `json:"license"` + StartDate string `json:"start_date"` + EndDate string `json:"end_date"` + Base string `json:"base"` + Rates map[string]any `json:"rates"` + Error bool `json:"error"` + Status int `json:"status"` + Message string `json:"message"` + Description string `json:"description"` } // Convert holds historic rate data @@ -104,16 +104,16 @@ type Convert struct { // OHLC holds open high low close values type OHLC struct { - Disclaimer string `json:"disclaimer"` - License string `json:"license"` - StartDate string `json:"start_date"` - EndDate string `json:"end_date"` - Base string `json:"base"` - Rates map[string]interface{} `json:"rates"` - Error bool `json:"error"` - Status int `json:"status"` - Message string `json:"message"` - Description string `json:"description"` + Disclaimer string `json:"disclaimer"` + License string `json:"license"` + StartDate string `json:"start_date"` + EndDate string `json:"end_date"` + Base string `json:"base"` + Rates map[string]any `json:"rates"` + Error bool `json:"error"` + Status int `json:"status"` + Message string `json:"message"` + Description string `json:"description"` } // Usage holds usage statistical data diff --git a/currency/mock_provider_test.go b/currency/mock_provider_test.go index 9f874da6..eeea2113 100644 --- a/currency/mock_provider_test.go +++ b/currency/mock_provider_test.go @@ -33,7 +33,7 @@ func (m *MockProvider) GetSupportedCurrencies() ([]string, error) { func (m *MockProvider) GetRates(baseCurrency, symbols string) (map[string]float64, error) { c := map[string]float64{} - for _, s := range strings.Split(symbols, ",") { + for s := range strings.SplitSeq(symbols, ",") { // The year is 2027; The USD is nearly worthless. The world reserve currency is eggs. c[baseCurrency+s] = 1 / (1 + rand.Float64()) //nolint:gosec // Doesn't need to be a strong random number } diff --git a/currency/pair.go b/currency/pair.go index 1a396a6d..3355731f 100644 --- a/currency/pair.go +++ b/currency/pair.go @@ -124,10 +124,7 @@ func (f *PairFormat) clone() *PairFormat { func MatchPairsWithNoDelimiter(currencyPair string, pairs Pairs, pairFmt PairFormat) (Pair, error) { for i := range pairs { fPair := pairs[i].Format(pairFmt) - maxLen := 6 - if len(currencyPair) < maxLen { - maxLen = len(currencyPair) - } + maxLen := min(len(currencyPair), 6) for j := 1; j <= maxLen; j++ { if fPair.Base.String() == currencyPair[0:j] && fPair.Quote.String() == currencyPair[j:] { diff --git a/currency/pair_types.go b/currency/pair_types.go index a1086d48..636f1cc2 100644 --- a/currency/pair_types.go +++ b/currency/pair_types.go @@ -5,8 +5,8 @@ package currency // is a delimiter present in the string, otherwise it will return an error. type Pair struct { Delimiter string `json:"delimiter,omitempty"` - Base Code `json:"base,omitempty"` - Quote Code `json:"quote,omitempty"` + Base Code `json:"base"` + Quote Code `json:"quote"` } // Pairs defines a list of pairs diff --git a/database/database_types.go b/database/database_types.go index 79d3d614..25c9298f 100644 --- a/database/database_types.go +++ b/database/database_types.go @@ -75,10 +75,10 @@ type IDatabase interface { // without giving the receiver access to all functionality type ISQL interface { BeginTx(context.Context, *sql.TxOptions) (*sql.Tx, error) - Exec(string, ...interface{}) (sql.Result, error) - Query(string, ...interface{}) (*sql.Rows, error) - QueryRow(string, ...interface{}) *sql.Row - ExecContext(context.Context, string, ...interface{}) (sql.Result, error) - QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) - QueryRowContext(context.Context, string, ...interface{}) *sql.Row + Exec(string, ...any) (sql.Result, error) + Query(string, ...any) (*sql.Rows, error) + QueryRow(string, ...any) *sql.Row + ExecContext(context.Context, string, ...any) (sql.Result, error) + QueryContext(context.Context, string, ...any) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...any) *sql.Row } diff --git a/database/repository/audit/audit.go b/database/repository/audit/audit.go index d93e562a..4a484272 100644 --- a/database/repository/audit/audit.go +++ b/database/repository/audit/audit.go @@ -61,7 +61,7 @@ func Event(id, msgtype, message string) { } // GetEvent () returns list of order events matching query -func GetEvent(startTime, endTime time.Time, order string, limit int) (interface{}, error) { +func GetEvent(startTime, endTime time.Time, order string, limit int) (any, error) { if database.DB.SQL == nil { return nil, database.ErrDatabaseSupportDisabled } diff --git a/database/repository/audit/audit_test.go b/database/repository/audit/audit_test.go index e2c2fe1f..e4db7a3b 100644 --- a/database/repository/audit/audit_test.go +++ b/database/repository/audit/audit_test.go @@ -36,7 +36,7 @@ func TestAudit(t *testing.T) { config *database.Config runner func(t *testing.T) closer func(dbConn *database.Instance) error - output interface{} + output any }{ { "SQLite-Write", diff --git a/database/repository/script/script_test.go b/database/repository/script/script_test.go index 1d7f6cf2..aacf3522 100644 --- a/database/repository/script/script_test.go +++ b/database/repository/script/script_test.go @@ -48,7 +48,7 @@ func TestScript(t *testing.T) { config *database.Config runner func() closer func(dbConn *database.Instance) error - output interface{} + output any }{ { "SQLite-Write", diff --git a/database/repository/trade/trade.go b/database/repository/trade/trade.go index 6d4433ab..cf0118d4 100644 --- a/database/repository/trade/trade.go +++ b/database/repository/trade/trade.go @@ -309,7 +309,7 @@ func getInRangeSQLite(exchangeName, assetType, base, quote string, startDate, en if err != nil { return nil, err } - wheres := map[string]interface{}{ + wheres := map[string]any{ "exchange_name_id": exchangeUUID, "asset": strings.ToLower(assetType), "base": strings.ToUpper(base), @@ -351,7 +351,7 @@ func getInRangePostgres(exchangeName, assetType, base, quote string, startDate, if err != nil { return nil, err } - wheres := map[string]interface{}{ + wheres := map[string]any{ "exchange_name_id": exchangeUUID, "asset": strings.ToLower(assetType), "base": strings.ToUpper(base), @@ -414,7 +414,7 @@ func DeleteTrades(trades ...Data) error { } func deleteTradesSQLite(ctx context.Context, tx *sql.Tx, trades ...Data) error { - tradeIDs := make([]interface{}, len(trades)) + tradeIDs := make([]any, len(trades)) for i := range trades { tradeIDs[i] = trades[i].ID } @@ -424,7 +424,7 @@ func deleteTradesSQLite(ctx context.Context, tx *sql.Tx, trades ...Data) error { } func deleteTradesPostgres(ctx context.Context, tx *sql.Tx, trades ...Data) error { - tradeIDs := make([]interface{}, len(trades)) + tradeIDs := make([]any, len(trades)) for i := range trades { tradeIDs[i] = trades[i].ID } @@ -433,7 +433,7 @@ func deleteTradesPostgres(ctx context.Context, tx *sql.Tx, trades ...Data) error return err } -func generateQuery(clauses map[string]interface{}, start, end time.Time, isSQLite bool) []qm.QueryMod { +func generateQuery(clauses map[string]any, start, end time.Time, isSQLite bool) []qm.QueryMod { query := []qm.QueryMod{ qm.OrderBy("timestamp"), } diff --git a/database/repository/withdraw/withdraw.go b/database/repository/withdraw/withdraw.go index df4252a8..3f0b6447 100644 --- a/database/repository/withdraw/withdraw.go +++ b/database/repository/withdraw/withdraw.go @@ -276,7 +276,7 @@ func generateWhereQuery(columns, id []string, limit int) []qm.QueryMod { return queries } -func generateWhereBetweenQuery(column string, start, end interface{}, limit int) []qm.QueryMod { +func generateWhereBetweenQuery(column string, start, end any, limit int) []qm.QueryMod { return []qm.QueryMod{ qm.Limit(limit), qm.Where(column+" BETWEEN ? AND ?", start, end), diff --git a/database/repository/withdraw/withdraw_test.go b/database/repository/withdraw/withdraw_test.go index 1caa4ff3..805fb123 100644 --- a/database/repository/withdraw/withdraw_test.go +++ b/database/repository/withdraw/withdraw_test.go @@ -60,7 +60,7 @@ func TestWithdraw(t *testing.T) { config *database.Config runner func(t *testing.T) closer func(dbConn *database.Instance) error - output interface{} + output any }{ { "SQLite-Write", diff --git a/database/testhelpers/test_helpers_test.go b/database/testhelpers/test_helpers_test.go index c1151b77..9285edef 100644 --- a/database/testhelpers/test_helpers_test.go +++ b/database/testhelpers/test_helpers_test.go @@ -35,7 +35,7 @@ func TestDatabaseConnect(t *testing.T) { name string config *database.Config closer func(dbConn *database.Instance) error - output interface{} + output any }{ { "SQLite", diff --git a/dispatch/dispatch.go b/dispatch/dispatch.go index d8722494..2f460060 100644 --- a/dispatch/dispatch.go +++ b/dispatch/dispatch.go @@ -39,16 +39,16 @@ func init() { // NewDispatcher creates a new Dispatcher for relaying data. func NewDispatcher() *Dispatcher { return &Dispatcher{ - routes: make(map[uuid.UUID][]chan interface{}), + routes: make(map[uuid.UUID][]chan any), outbound: sync.Pool{ New: getChan, }, } } -func getChan() interface{} { +func getChan() any { // Create unbuffered channel for data pass - return make(chan interface{}) + return make(chan any) } // Start starts the dispatch system by spawning workers and allocating memory @@ -202,7 +202,7 @@ func (d *Dispatcher) relayer() { } // publish relays data to the subscribed subsystems -func (d *Dispatcher) publish(id uuid.UUID, data interface{}) error { +func (d *Dispatcher) publish(id uuid.UUID, data any) error { if d == nil { return errDispatcherNotInitialized } @@ -235,7 +235,7 @@ func (d *Dispatcher) publish(id uuid.UUID, data interface{}) error { // Subscribe subscribes a system and returns a communication chan, this does not // ensure initial push. -func (d *Dispatcher) subscribe(id uuid.UUID) (chan interface{}, error) { +func (d *Dispatcher) subscribe(id uuid.UUID) (chan any, error) { if d == nil { return nil, errDispatcherNotInitialized } @@ -258,7 +258,7 @@ func (d *Dispatcher) subscribe(id uuid.UUID) (chan interface{}, error) { } // Get an unused channel from the channel pool - ch, ok := d.outbound.Get().(chan interface{}) + ch, ok := d.outbound.Get().(chan any) if !ok { return nil, errTypeAssertionFailure } @@ -269,7 +269,7 @@ func (d *Dispatcher) subscribe(id uuid.UUID) (chan interface{}, error) { } // Unsubscribe unsubs a routine from the dispatcher -func (d *Dispatcher) unsubscribe(id uuid.UUID, usedChan chan interface{}) error { +func (d *Dispatcher) unsubscribe(id uuid.UUID, usedChan chan any) error { if d == nil { return errDispatcherNotInitialized } diff --git a/dispatch/dispatch_test.go b/dispatch/dispatch_test.go index 0902742a..0b221e35 100644 --- a/dispatch/dispatch_test.go +++ b/dispatch/dispatch_test.go @@ -93,7 +93,7 @@ func TestSubscribe(t *testing.T) { _, err = d.subscribe(nonEmptyUUID) assert.ErrorIs(t, err, errDispatcherUUIDNotFoundInRouteList, "subscribe should error correctly") - d.outbound.New = func() interface{} { return "omg" } + d.outbound.New = func() any { return "omg" } _, err = d.subscribe(id) assert.ErrorIs(t, err, errTypeAssertionFailure, "subscribe should error correctly") @@ -119,19 +119,19 @@ func TestUnsubscribe(t *testing.T) { assert.ErrorIs(t, err, errChannelIsNil, "unsubscribe should error correctly") // will return nil if not running - err = d.unsubscribe(nonEmptyUUID, make(chan interface{})) + err = d.unsubscribe(nonEmptyUUID, make(chan any)) assert.NoError(t, err, "unsubscribe should not error") err = d.start(0, 0) require.NoError(t, err, "start should not error") - err = d.unsubscribe(nonEmptyUUID, make(chan interface{})) + err = d.unsubscribe(nonEmptyUUID, make(chan any)) assert.ErrorIs(t, err, errDispatcherUUIDNotFoundInRouteList, "unsubscribe should error correctly") id, err := d.getNewID(uuid.NewV4) require.NoError(t, err, "getNewID should not error") - err = d.unsubscribe(id, make(chan interface{})) + err = d.unsubscribe(id, make(chan any)) assert.ErrorIs(t, err, errChannelNotFoundInUUIDRef, "unsubscribe should error correctly") ch, err := d.subscribe(id) @@ -169,8 +169,8 @@ func TestPublish(t *testing.T) { assert.ErrorIs(t, err, errNoData, "publish should error correctly") // demonstrate job limit error - d.routes[nonEmptyUUID] = []chan interface{}{ - make(chan interface{}), + d.routes[nonEmptyUUID] = []chan any{ + make(chan any), } for range 200 { if err = d.publish(nonEmptyUUID, "test"); err != nil { diff --git a/dispatch/dispatch_types.go b/dispatch/dispatch_types.go index 02e947c4..2f65651f 100644 --- a/dispatch/dispatch_types.go +++ b/dispatch/dispatch_types.go @@ -28,7 +28,7 @@ type Dispatcher struct { // channels, a relayer will be given a unique id through its job channel, // then publish the data across the full registered channels for that uuid. // See relayer() method below. - routes map[uuid.UUID][]chan interface{} + routes map[uuid.UUID][]chan any // routesMtx protects the routes variable ensuring acceptable read/write access routesMtx sync.Mutex @@ -61,7 +61,7 @@ type Dispatcher struct { // job defines a relaying job associated with a ticket which allows routing to // routines that require specific data type job struct { - Data interface{} + Data any ID uuid.UUID } @@ -75,7 +75,7 @@ type Mux struct { // Pipe defines an outbound object to the desired routine type Pipe struct { // Channel to get all our lovely information - c chan interface{} + c chan any // ID to tracked system id uuid.UUID // Reference to multiplexer diff --git a/dispatch/mux.go b/dispatch/mux.go index 6bb451ec..8ac7bc95 100644 --- a/dispatch/mux.go +++ b/dispatch/mux.go @@ -43,7 +43,7 @@ func (m *Mux) Subscribe(id uuid.UUID) (Pipe, error) { } // Unsubscribe returns channel to the pool for the full signature set -func (m *Mux) Unsubscribe(id uuid.UUID, ch chan interface{}) error { +func (m *Mux) Unsubscribe(id uuid.UUID, ch chan any) error { if m == nil { return errMuxIsNil } @@ -52,7 +52,7 @@ func (m *Mux) Unsubscribe(id uuid.UUID, ch chan interface{}) error { // Publish takes in a persistent memory address and dispatches changes to // required pipes. -func (m *Mux) Publish(data interface{}, ids ...uuid.UUID) error { +func (m *Mux) Publish(data any, ids ...uuid.UUID) error { if m == nil { return errMuxIsNil } @@ -91,6 +91,6 @@ func (p *Pipe) Release() error { } // Channel returns the Pipe's channel -func (p *Pipe) Channel() <-chan interface{} { +func (p *Pipe) Channel() <-chan any { return p.c } diff --git a/docs/ADD_NEW_EXCHANGE.md b/docs/ADD_NEW_EXCHANGE.md index 94a4bbb4..d34f4061 100644 --- a/docs/ADD_NEW_EXCHANGE.md +++ b/docs/ADD_NEW_EXCHANGE.md @@ -309,7 +309,7 @@ This will generate a readme file for the exchange which can be found in the new ```go // SendHTTPRequest sends an unauthenticated HTTP request -func (f *FTX) SendHTTPRequest(ctx context.Context, path string, result interface{}) error { +func (f *FTX) SendHTTPRequest(ctx context.Context, path string, result any) error { // This is used to generate the *http.Request, used in conjunction with the // generate functionality below. item := &request.Item{ @@ -414,7 +414,7 @@ Ensure each endpoint is implemented and has an associated test to improve test c Authenticated request function is created based on the way the exchange documentation specifies: https://docs.ftx.com/#authentication ```go // SendAuthHTTPRequest sends an authenticated request -func (f *FTX) SendAuthHTTPRequest(ctx context.Context, method, path string, data, result interface{}) error { +func (f *FTX) SendAuthHTTPRequest(ctx context.Context, method, path string, data, result any) error { // A potential example below of closing over authenticated variables which may // be required to regenerate on every request between each attempt after rate // limiting. This is for when signatures are based on timestamps/nonces that are @@ -553,12 +553,12 @@ type PlaceOrder struct { } ``` -For `POST` or `DELETE` requests, params are sent through a map[string]interface{}: +For `POST` or `DELETE` requests, params are sent through a map[string]any: ```go // Order places an order func (f *FTX) Order(ctx context.Context, marketName, side, orderType, reduceOnly, ioc, postOnly, clientID string, price, size float64) (PlaceOrder, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["market"] = marketName req["side"] = side req["price"] = price @@ -863,14 +863,14 @@ type WsResponseData struct { ResponseType string `json:"type"` Channel string `json:"channel"` Market string `json:"market"` - Data interface{} `json:"data"` + Data any `json:"data"` } ``` - Unmarshall the raw data into the main type: ```go - var result map[string]interface{} + var result map[string]any err := json.Unmarshal(respRaw, &result) if err != nil { return err diff --git a/encoding/json/benchmark_test.go b/encoding/json/benchmark_test.go index 21164743..c3d12a1b 100644 --- a/encoding/json/benchmark_test.go +++ b/encoding/json/benchmark_test.go @@ -7,6 +7,6 @@ import "testing" func BenchmarkUnmarshal(b *testing.B) { b.ReportAllocs() for b.Loop() { - _ = Unmarshal([]byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`), &map[string]interface{}{}) + _ = Unmarshal([]byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`), &map[string]any{}) } } diff --git a/engine/apiserver.go b/engine/apiserver.go index 487baad1..c5b8c8ca 100644 --- a/engine/apiserver.go +++ b/engine/apiserver.go @@ -207,7 +207,7 @@ func restLogger(inner http.Handler, name string) http.Handler { } // writeResponse outputs a JSON response of the response interface -func writeResponse(w http.ResponseWriter, response interface{}) error { +func writeResponse(w http.ResponseWriter, response any) error { w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) return json.NewEncoder(w).Encode(response) @@ -466,7 +466,7 @@ func (h *websocketHub) run() { } // SendWebsocketMessage sends a websocket event to the client -func (c *websocketClient) SendWebsocketMessage(evt interface{}) error { +func (c *websocketClient) SendWebsocketMessage(evt any) error { data, err := json.Marshal(evt) if err != nil { log.Errorf(log.APIServerMgr, "websocket: failed to send message: %s\n", err) @@ -667,7 +667,7 @@ func (m *apiServerManager) WebsocketClientHandler(w http.ResponseWriter, r *http go client.write() } -func wsAuth(client *websocketClient, data interface{}) error { +func wsAuth(client *websocketClient, data any) error { d, ok := data.([]byte) if !ok { return common.GetTypeAssertError("[]byte", data) @@ -722,7 +722,7 @@ func wsAuth(client *websocketClient, data interface{}) error { return nil } -func wsGetConfig(client *websocketClient, _ interface{}) error { +func wsGetConfig(client *websocketClient, _ any) error { wsResp := WebsocketEventResponse{ Event: "GetConfig", Data: config.GetConfig(), @@ -730,7 +730,7 @@ func wsGetConfig(client *websocketClient, _ interface{}) error { return client.SendWebsocketMessage(wsResp) } -func wsSaveConfig(client *websocketClient, data interface{}) error { +func wsSaveConfig(client *websocketClient, data any) error { d, ok := data.([]byte) if !ok { return common.GetTypeAssertError("[]byte", data) @@ -774,7 +774,7 @@ func wsSaveConfig(client *websocketClient, data interface{}) error { return client.SendWebsocketMessage(wsResp) } -func wsGetAccountInfo(client *websocketClient, _ interface{}) error { +func wsGetAccountInfo(client *websocketClient, _ any) error { accountInfo := getAllActiveAccounts(client.exchangeManager) wsResp := WebsocketEventResponse{ Event: "GetAccountInfo", @@ -783,7 +783,7 @@ func wsGetAccountInfo(client *websocketClient, _ interface{}) error { return client.SendWebsocketMessage(wsResp) } -func wsGetTickers(client *websocketClient, _ interface{}) error { +func wsGetTickers(client *websocketClient, _ any) error { wsResp := WebsocketEventResponse{ Event: "GetTickers", } @@ -791,7 +791,7 @@ func wsGetTickers(client *websocketClient, _ interface{}) error { return client.SendWebsocketMessage(wsResp) } -func wsGetTicker(client *websocketClient, data interface{}) error { +func wsGetTicker(client *websocketClient, data any) error { d, ok := data.([]byte) if !ok { return common.GetTypeAssertError("[]byte", data) @@ -843,7 +843,7 @@ func wsGetTicker(client *websocketClient, data interface{}) error { return client.SendWebsocketMessage(wsResp) } -func wsGetOrderbooks(client *websocketClient, _ interface{}) error { +func wsGetOrderbooks(client *websocketClient, _ any) error { wsResp := WebsocketEventResponse{ Event: "GetOrderbooks", } @@ -851,7 +851,7 @@ func wsGetOrderbooks(client *websocketClient, _ interface{}) error { return client.SendWebsocketMessage(wsResp) } -func wsGetOrderbook(client *websocketClient, data interface{}) error { +func wsGetOrderbook(client *websocketClient, data any) error { d, ok := data.([]byte) if !ok { return common.GetTypeAssertError("[]byte", data) @@ -897,7 +897,7 @@ func wsGetOrderbook(client *websocketClient, data interface{}) error { return client.SendWebsocketMessage(WebsocketEventResponse{Event: "GetOrderbook", Data: ob}) } -func wsGetExchangeRates(client *websocketClient, _ interface{}) error { +func wsGetExchangeRates(client *websocketClient, _ any) error { wsResp := WebsocketEventResponse{ Event: "GetExchangeRates", } @@ -911,7 +911,7 @@ func wsGetExchangeRates(client *websocketClient, _ interface{}) error { return client.SendWebsocketMessage(wsResp) } -func wsGetPortfolio(client *websocketClient, _ interface{}) error { +func wsGetPortfolio(client *websocketClient, _ any) error { wsResp := WebsocketEventResponse{ Event: "GetPortfolio", } diff --git a/engine/apiserver_test.go b/engine/apiserver_test.go index b0836ca3..c4051313 100644 --- a/engine/apiserver_test.go +++ b/engine/apiserver_test.go @@ -243,7 +243,7 @@ func TestGetAllActiveAccounts(t *testing.T) { } } -func makeHTTPGetRequest(t *testing.T, response interface{}) *http.Response { +func makeHTTPGetRequest(t *testing.T, response any) *http.Response { t.Helper() w := httptest.NewRecorder() diff --git a/engine/apiserver_types.go b/engine/apiserver_types.go index fa5d7e65..95276646 100644 --- a/engine/apiserver_types.go +++ b/engine/apiserver_types.go @@ -88,14 +88,14 @@ type WebsocketEvent struct { Exchange string `json:"exchange,omitempty"` AssetType string `json:"assetType,omitempty"` Event string - Data interface{} + Data any } // WebsocketEventResponse is the struct used for websocket event responses type WebsocketEventResponse struct { - Event string `json:"event"` - Data interface{} `json:"data"` - Error string `json:"error"` + Event string `json:"event"` + Data any `json:"data"` + Error string `json:"error"` } // WebsocketOrderbookTickerRequest is a struct used for ticker and orderbook @@ -164,5 +164,5 @@ var wsHandlers = map[string]wsCommandHandler{ type wsCommandHandler struct { authRequired bool - handler func(client *websocketClient, data interface{}) error + handler func(client *websocketClient, data any) error } diff --git a/engine/depositaddress.go b/engine/depositaddress.go index 6ba292b8..3f25d258 100644 --- a/engine/depositaddress.go +++ b/engine/depositaddress.go @@ -3,6 +3,8 @@ package engine import ( "errors" "fmt" + "maps" + "slices" "strings" "sync" @@ -97,9 +99,9 @@ func (m *DepositAddressManager) GetDepositAddressesByExchange(exchName string) ( return nil, ErrDepositAddressNotFound } - cpy := make(map[string][]deposit.Address, len(r)) - for k, v := range r { - cpy[k] = v + cpy := maps.Clone(r) + for k, v := range cpy { + cpy[k] = slices.Clone(v) } return cpy, nil } diff --git a/engine/engine_test.go b/engine/engine_test.go index aa620d0c..90abae83 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -327,7 +327,7 @@ func TestRegisterWebsocketDataHandler(t *testing.T) { } e = &Engine{WebsocketRoutineManager: &WebsocketRoutineManager{}} - err = e.RegisterWebsocketDataHandler(func(_ string, _ interface{}) error { return nil }, false) + err = e.RegisterWebsocketDataHandler(func(_ string, _ any) error { return nil }, false) if !errors.Is(err, nil) { t.Fatalf("received: '%v' but expected: '%v'", err, nil) } diff --git a/engine/event_manager.go b/engine/event_manager.go index 94ac6873..b924fbc8 100644 --- a/engine/event_manager.go +++ b/engine/event_manager.go @@ -3,6 +3,7 @@ package engine import ( "errors" "fmt" + "slices" "strings" "sync/atomic" "time" @@ -147,7 +148,7 @@ func (m *eventManager) Remove(eventID int64) bool { defer m.m.Unlock() for i := range m.events { if m.events[i].ID == eventID { - m.events = append(m.events[:i], m.events[i+1:]...) + m.events = slices.Delete(m.events, i, i+1) return true } } diff --git a/engine/rpcserver.go b/engine/rpcserver.go index a3c20f62..4b2699b6 100644 --- a/engine/rpcserver.go +++ b/engine/rpcserver.go @@ -2542,7 +2542,7 @@ func (s *RPCServer) GCTScriptStatus(_ context.Context, _ *gctrpc.GCTScriptStatus Status: fmt.Sprintf("%v of %v virtual machines running", gctscript.VMSCount.Len(), s.gctScriptManager.GetMaxVirtualMachines()), } - gctscript.AllVMSync.Range(func(_, v interface{}) bool { + gctscript.AllVMSync.Range(func(_, v any) bool { vm, ok := v.(*gctscript.VM) if !ok { log.Errorf(log.GRPCSys, "%v", common.GetTypeAssertError("*gctscript.VM", v)) diff --git a/engine/rpcserver_test.go b/engine/rpcserver_test.go index fd553560..97ded0fc 100644 --- a/engine/rpcserver_test.go +++ b/engine/rpcserver_test.go @@ -1216,8 +1216,8 @@ func (d *dummyServer) SetHeader(metadata.MD) error { return nil } func (d *dummyServer) SendHeader(metadata.MD) error { return nil } func (d *dummyServer) SetTrailer(metadata.MD) {} func (d *dummyServer) Context() context.Context { return context.Background() } -func (d *dummyServer) SendMsg(_ interface{}) error { return nil } -func (d *dummyServer) RecvMsg(_ interface{}) error { return nil } +func (d *dummyServer) SendMsg(_ any) error { return nil } +func (d *dummyServer) RecvMsg(_ any) error { return nil } func TestGetHistoricTrades(t *testing.T) { engerino := RPCTestSetup(t) diff --git a/engine/sync_manager.go b/engine/sync_manager.go index 6c20a21d..ccbd8dda 100644 --- a/engine/sync_manager.go +++ b/engine/sync_manager.go @@ -30,6 +30,7 @@ const ( SyncItemOrderbook SyncItemTrade SyncManagerName = "exchange_syncer" + minSyncInterval = time.Second ) var ( @@ -452,10 +453,7 @@ func (m *SyncManager) worker() { } defer cleanup() - interval := greatestCommonDivisor(m.config.TimeoutWebsocket, m.config.TimeoutREST) - if interval > time.Second { - interval = time.Second - } + interval := min(greatestCommonDivisor(m.config.TimeoutWebsocket, m.config.TimeoutREST), minSyncInterval) t := time.NewTicker(interval) for { @@ -905,7 +903,7 @@ func (m *SyncManager) WaitForInitialSync() error { return nil } -func relayWebsocketEvent(result interface{}, event, assetType, exchangeName string) { +func relayWebsocketEvent(result any, event, assetType, exchangeName string) { evt := WebsocketEvent{ Data: result, Event: event, diff --git a/engine/websocketroutine_manager.go b/engine/websocketroutine_manager.go index 4f445db0..e595f076 100644 --- a/engine/websocketroutine_manager.go +++ b/engine/websocketroutine_manager.go @@ -194,7 +194,7 @@ func (m *WebsocketRoutineManager) websocketDataReceiver(ws *stream.Websocket) er // websocketDataHandler is the default central point for exchange websocket // implementations to send processed data which will then pass that to an // appropriate handler. -func (m *WebsocketRoutineManager) websocketDataHandler(exchName string, data interface{}) error { +func (m *WebsocketRoutineManager) websocketDataHandler(exchName string, data any) error { switch d := data.(type) { case string: log.Infoln(log.WebsocketMgr, d) diff --git a/engine/websocketroutine_manager_test.go b/engine/websocketroutine_manager_test.go index 1d3f6302..de7d4f48 100644 --- a/engine/websocketroutine_manager_test.go +++ b/engine/websocketroutine_manager_test.go @@ -275,8 +275,8 @@ func TestRegisterWebsocketDataHandlerWithFunctionality(t *testing.T) { } // externally defined capture device - dataChan := make(chan interface{}) - fn := func(_ string, data interface{}) error { + dataChan := make(chan any) + fn := func(_ string, data any) error { switch data.(type) { case string: dataChan <- data @@ -295,7 +295,7 @@ func TestRegisterWebsocketDataHandlerWithFunctionality(t *testing.T) { } mock := stream.NewWebsocket() - mock.ToRoutine = make(chan interface{}) + mock.ToRoutine = make(chan any) m.state = readyState err = m.websocketDataReceiver(mock) if err != nil { diff --git a/engine/websocketroutine_manager_types.go b/engine/websocketroutine_manager_types.go index 0aa4236e..586d400b 100644 --- a/engine/websocketroutine_manager_types.go +++ b/engine/websocketroutine_manager_types.go @@ -39,4 +39,4 @@ type WebsocketRoutineManager struct { // WebsocketDataHandler defines a function signature for a function that handles // data coming from websocket connections. -type WebsocketDataHandler func(service string, incoming interface{}) error +type WebsocketDataHandler func(service string, incoming any) error diff --git a/exchanges/alert/alert.go b/exchanges/alert/alert.go index 35abaab7..93aa5211 100644 --- a/exchanges/alert/alert.go +++ b/exchanges/alert/alert.go @@ -21,7 +21,7 @@ const ( var ( // pool is a silent shared pool between all notice instances for alerting // external routines waiting on a state change. - pool = sync.Pool{New: func() interface{} { return make(chan bool) }} + pool = sync.Pool{New: func() any { return make(chan bool) }} preAllocBufferSize = PreAllocCommsDefaultBuffer mu sync.RWMutex diff --git a/exchanges/alphapoint/alphapoint.go b/exchanges/alphapoint/alphapoint.go index f24443b8..2e105887 100644 --- a/exchanges/alphapoint/alphapoint.go +++ b/exchanges/alphapoint/alphapoint.go @@ -50,7 +50,7 @@ type Alphapoint struct { // GetTicker returns current ticker information from Alphapoint for a selected // currency pair ie "BTCUSD" func (a *Alphapoint) GetTicker(ctx context.Context, currencyPair string) (Ticker, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["productPair"] = currencyPair response := Ticker{} @@ -76,7 +76,7 @@ func (a *Alphapoint) GetTicker(ctx context.Context, currencyPair string) (Ticker // 0 (default: 0) // Count: specifies the number of trades to return (default: 10) func (a *Alphapoint) GetTrades(ctx context.Context, currencyPair string, startIndex, count int) (Trades, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["ins"] = currencyPair req["startIndex"] = startIndex req["Count"] = count @@ -98,7 +98,7 @@ func (a *Alphapoint) GetTrades(ctx context.Context, currencyPair string, startIn // StartDate - specifies the starting time in epoch time, type is long // EndDate - specifies the end time in epoch time, type is long func (a *Alphapoint) GetTradesByDate(ctx context.Context, currencyPair string, startDate, endDate int64) (Trades, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["ins"] = currencyPair req["startDate"] = startDate req["endDate"] = endDate @@ -122,7 +122,7 @@ func (a *Alphapoint) GetTradesByDate(ctx context.Context, currencyPair string, s // GetOrderbook fetches the current orderbook for a given currency pair // CurrencyPair - trade pair (ex: “BTCUSD”) func (a *Alphapoint) GetOrderbook(ctx context.Context, currencyPair string) (Orderbook, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["productPair"] = currencyPair response := Orderbook{} @@ -180,7 +180,7 @@ func (a *Alphapoint) CreateAccount(ctx context.Context, firstName, lastName, ema ) } - req := make(map[string]interface{}) + req := make(map[string]any) req["firstname"] = firstName req["lastname"] = lastName req["email"] = email @@ -207,7 +207,7 @@ func (a *Alphapoint) GetUserInfo(ctx context.Context) (UserInfo, error) { exchange.RestSpot, http.MethodPost, alphapointUserInfo, - map[string]interface{}{}, + map[string]any{}, &response) if err != nil { return UserInfo{}, err @@ -257,7 +257,7 @@ func (a *Alphapoint) SetUserInfo(ctx context.Context, firstName, lastName, cell2 }, } - req := make(map[string]interface{}) + req := make(map[string]any) req["userInfoKVP"] = userInfoKVPs err := a.SendAuthenticatedHTTPRequest(ctx, @@ -284,7 +284,7 @@ func (a *Alphapoint) GetAccountInformation(ctx context.Context) (AccountInfo, er exchange.RestSpot, http.MethodPost, alphapointAccountInfo, - map[string]interface{}{}, + map[string]any{}, &response, ) if err != nil { @@ -301,7 +301,7 @@ func (a *Alphapoint) GetAccountInformation(ctx context.Context) (AccountInfo, er // StartIndex - Starting index, if less than 0 then start from the beginning // Count - Returns last trade, (Default: 30) func (a *Alphapoint) GetAccountTrades(ctx context.Context, currencyPair string, startIndex, count int) (Trades, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["ins"] = currencyPair req["startIndex"] = startIndex req["count"] = count @@ -331,7 +331,7 @@ func (a *Alphapoint) GetDepositAddresses(ctx context.Context) ([]DepositAddresse exchange.RestSpot, http.MethodPost, alphapointDepositAddresses, - map[string]interface{}{}, + map[string]any{}, &response, ) if err != nil { @@ -349,7 +349,7 @@ func (a *Alphapoint) GetDepositAddresses(ctx context.Context) ([]DepositAddresse // amount - Amount (ex: “.011”) // address - Withdraw address func (a *Alphapoint) WithdrawCoins(ctx context.Context, symbol, product, address string, amount float64) error { - req := make(map[string]interface{}) + req := make(map[string]any) req["ins"] = symbol req["product"] = product req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) @@ -388,7 +388,7 @@ func (a *Alphapoint) convertOrderTypeToOrderTypeNumber(orderType string) (orderT // price - Price in USD func (a *Alphapoint) CreateOrder(ctx context.Context, symbol, side, orderType string, quantity, price float64) (int64, error) { orderTypeNumber := a.convertOrderTypeToOrderTypeNumber(orderType) - req := make(map[string]interface{}) + req := make(map[string]any) req["ins"] = symbol req["side"] = side req["orderType"] = orderTypeNumber @@ -421,7 +421,7 @@ func (a *Alphapoint) CreateOrder(ctx context.Context, symbol, side, orderType st // be modified to the lowest ask price. “1” means "Execute now", which will // convert a limit order into a market order. func (a *Alphapoint) ModifyExistingOrder(ctx context.Context, symbol string, orderID, action int64) (int64, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["ins"] = symbol req["serverOrderId"] = orderID req["modifyAction"] = action @@ -447,7 +447,7 @@ func (a *Alphapoint) ModifyExistingOrder(ctx context.Context, symbol string, ord // symbol - Instrument code (ex: “BTCUSD”) // OrderID - Order id (ex: 1000) func (a *Alphapoint) CancelExistingOrder(ctx context.Context, orderID int64, omsid string) (int64, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["OrderId"] = orderID req["OMSId"] = omsid response := Response{} @@ -471,7 +471,7 @@ func (a *Alphapoint) CancelExistingOrder(ctx context.Context, orderID int64, oms // CancelAllExistingOrders cancels all open orders by symbol. // symbol - Instrument code (ex: “BTCUSD”) func (a *Alphapoint) CancelAllExistingOrders(ctx context.Context, omsid string) error { - req := make(map[string]interface{}) + req := make(map[string]any) req["OMSId"] = omsid response := Response{} @@ -499,7 +499,7 @@ func (a *Alphapoint) GetOrders(ctx context.Context) ([]OpenOrders, error) { exchange.RestSpot, http.MethodPost, alphapointOpenOrders, - map[string]interface{}{}, + map[string]any{}, &response, ) if err != nil { @@ -517,7 +517,7 @@ func (a *Alphapoint) GetOrders(ctx context.Context) ([]OpenOrders, error) { // quantity - Quantity // price - Price in USD func (a *Alphapoint) GetOrderFee(ctx context.Context, symbol, side string, quantity, price float64) (float64, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["ins"] = symbol req["side"] = side req["qty"] = strconv.FormatFloat(quantity, 'f', -1, 64) @@ -541,7 +541,7 @@ func (a *Alphapoint) GetOrderFee(ctx context.Context, symbol, side string, quant } // SendHTTPRequest sends an unauthenticated HTTP request -func (a *Alphapoint) SendHTTPRequest(_ context.Context, ep exchange.URL, method, path string, data map[string]interface{}, result interface{}) error { +func (a *Alphapoint) SendHTTPRequest(_ context.Context, ep exchange.URL, method, path string, data map[string]any, result any) error { endpoint, err := a.API.Endpoints.GetURL(ep) if err != nil { return err @@ -572,7 +572,7 @@ func (a *Alphapoint) SendHTTPRequest(_ context.Context, ep exchange.URL, method, } // SendAuthenticatedHTTPRequest sends an authenticated request -func (a *Alphapoint) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, data map[string]interface{}, result interface{}) error { +func (a *Alphapoint) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, data map[string]any, result any) error { creds, err := a.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/asset/asset.go b/exchanges/asset/asset.go index d492bc1a..7aa6a891 100644 --- a/exchanges/asset/asset.go +++ b/exchanges/asset/asset.go @@ -3,6 +3,7 @@ package asset import ( "errors" "fmt" + "slices" "strings" "github.com/thrasher-corp/gocryptotrader/encoding/json" @@ -144,14 +145,7 @@ func (a Items) Strings() []string { // Contains returns whether or not the supplied asset exists // in the list of Items func (a Items) Contains(i Item) bool { - if i.IsValid() { - for x := range a { - if a[x] == i { - return true - } - } - } - return false + return slices.Contains(a, i) } // JoinToString joins an asset type array and converts it to a string diff --git a/exchanges/binance/binance.go b/exchanges/binance/binance.go index cedecd44..47adf431 100644 --- a/exchanges/binance/binance.go +++ b/exchanges/binance/binance.go @@ -26,9 +26,7 @@ import ( // Binance is the overarching type across the Binance package type Binance struct { exchange.Base - // Valid string list that is required by the exchange - validLimits []int - obm *orderbookManager + obm *orderbookManager } const ( @@ -124,10 +122,6 @@ func (b *Binance) GetExchangeInfo(ctx context.Context) (ExchangeInfo, error) { // symbol: string of currency pair // limit: returned limit amount func (b *Binance) GetOrderBook(ctx context.Context, obd OrderBookDataRequestParams) (*OrderBook, error) { - if err := b.CheckLimit(obd.Limit); err != nil { - return nil, err - } - params := url.Values{} symbol, err := b.FormatSymbol(obd.Symbol, asset.Spot) if err != nil { @@ -406,7 +400,7 @@ func (b *Binance) GetSpotKline(ctx context.Context, arg *KlinesRequestParams) ([ } path := candleStick + "?" + params.Encode() - var resp interface{} + var resp any err = b.SendHTTPRequest(ctx, exchange.RestSpotSupplementary, @@ -416,16 +410,16 @@ func (b *Binance) GetSpotKline(ctx context.Context, arg *KlinesRequestParams) ([ if err != nil { return nil, err } - responseData, ok := resp.([]interface{}) + responseData, ok := resp.([]any) if !ok { - return nil, common.GetTypeAssertError("[]interface{}", resp) + return nil, common.GetTypeAssertError("[]any", resp) } klineData := make([]CandleStick, len(responseData)) for x := range responseData { - individualData, ok := responseData[x].([]interface{}) + individualData, ok := responseData[x].([]any) if !ok { - return nil, common.GetTypeAssertError("[]interface{}", responseData[x]) + return nil, common.GetTypeAssertError("[]any", responseData[x]) } if len(individualData) != 12 { return nil, errors.New("unexpected kline data length") @@ -796,7 +790,7 @@ func (b *Binance) GetMarginAccount(ctx context.Context) (*MarginAccount, error) } // SendHTTPRequest sends an unauthenticated request -func (b *Binance) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path string, f request.EndpointLimit, result interface{}) error { +func (b *Binance) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path string, f request.EndpointLimit, result any) error { endpointPath, err := b.API.Endpoints.GetURL(ePath) if err != nil { return err @@ -817,7 +811,7 @@ func (b *Binance) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path // SendAPIKeyHTTPRequest is a special API request where the api key is // appended to the headers without a secret -func (b *Binance) SendAPIKeyHTTPRequest(ctx context.Context, ePath exchange.URL, path string, f request.EndpointLimit, result interface{}) error { +func (b *Binance) SendAPIKeyHTTPRequest(ctx context.Context, ePath exchange.URL, path string, f request.EndpointLimit, result any) error { endpointPath, err := b.API.Endpoints.GetURL(ePath) if err != nil { return err @@ -846,7 +840,7 @@ func (b *Binance) SendAPIKeyHTTPRequest(ctx context.Context, ePath exchange.URL, } // SendAuthHTTPRequest sends an authenticated HTTP request -func (b *Binance) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, method, path string, params url.Values, f request.EndpointLimit, result interface{}) error { +func (b *Binance) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, method, path string, params url.Values, f request.EndpointLimit, result any) error { creds, err := b.GetCredentials(ctx) if err != nil { return err @@ -912,21 +906,6 @@ func (b *Binance) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, m return json.Unmarshal(interim, result) } -// CheckLimit checks value against a variable list -func (b *Binance) CheckLimit(limit int) error { - for x := range b.validLimits { - if b.validLimits[x] == limit { - return nil - } - } - return errors.New("incorrect limit values - valid values are 5, 10, 20, 50, 100, 500, 1000") -} - -// SetValues sets the default valid values -func (b *Binance) SetValues() { - b.validLimits = []int{5, 10, 20, 50, 100, 500, 1000, 5000} -} - // GetFee returns an estimate of fee based on type of transaction func (b *Binance) GetFee(ctx context.Context, feeBuilder *exchange.FeeBuilder) (float64, error) { var fee float64 diff --git a/exchanges/binance/binance_cfutures.go b/exchanges/binance/binance_cfutures.go index d053f852..5a892c94 100644 --- a/exchanges/binance/binance_cfutures.go +++ b/exchanges/binance/binance_cfutures.go @@ -268,7 +268,7 @@ func (b *Binance) GetFuturesKlineData(ctx context.Context, symbol currency.Pair, params.Set("endTime", strconv.FormatInt(endTime.UnixMilli(), 10)) } - var data [][10]interface{} + var data [][10]any rateBudget := getKlineRateBudget(limit) err := b.SendHTTPRequest(ctx, exchange.RestCoinMargined, cfuturesKlineData+params.Encode(), rateBudget, &data) if err != nil { @@ -388,7 +388,7 @@ func (b *Binance) GetContinuousKlineData(ctx context.Context, pair, contractType } rateBudget := getKlineRateBudget(limit) - var data [][10]interface{} + var data [][10]any err := b.SendHTTPRequest(ctx, exchange.RestCoinMargined, cfuturesContinuousKline+params.Encode(), rateBudget, &data) if err != nil { return nil, err @@ -503,7 +503,7 @@ func (b *Binance) GetIndexPriceKlines(ctx context.Context, pair, interval string } rateBudget := getKlineRateBudget(limit) - var data [][10]interface{} + var data [][10]any err := b.SendHTTPRequest(ctx, exchange.RestCoinMargined, cfuturesIndexKline+params.Encode(), rateBudget, &data) if err != nil { return nil, err @@ -621,7 +621,7 @@ func (b *Binance) GetMarkPriceKline(ctx context.Context, symbol currency.Pair, i params.Set("endTime", strconv.FormatInt(endTime.UnixMilli(), 10)) } - var data [][10]interface{} + var data [][10]any rateBudget := getKlineRateBudget(limit) err = b.SendHTTPRequest(ctx, exchange.RestCoinMargined, cfuturesMarkPriceKline+params.Encode(), rateBudget, &data) if err != nil { diff --git a/exchanges/binance/binance_live_test.go b/exchanges/binance/binance_live_test.go index 46bf3c1b..e21d570f 100644 --- a/exchanges/binance/binance_live_test.go +++ b/exchanges/binance/binance_live_test.go @@ -18,7 +18,6 @@ import ( var mockTests = false func TestMain(m *testing.M) { - b = new(Binance) if err := testexch.Setup(b); err != nil { log.Fatal(err) diff --git a/exchanges/binance/binance_test.go b/exchanges/binance/binance_test.go index 1aa78f87..bb8261eb 100644 --- a/exchanges/binance/binance_test.go +++ b/exchanges/binance/binance_test.go @@ -1969,8 +1969,7 @@ func BenchmarkWsHandleData(bb *testing.B) { <-b.Websocket.DataHandler } }() - bb.ResetTimer() - for range bb.N { + for bb.Loop() { for x := range lines { assert.NoError(bb, b.wsHandleData(lines[x])) } @@ -1990,7 +1989,7 @@ func TestSubscribe(t *testing.T) { var req WsPayload require.NoError(tb, json.Unmarshal(msg, &req), "Unmarshal should not error") require.ElementsMatch(tb, req.Params, exp, "Params should have correct channels") - return w.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf(`{"result":null,"id":%d}`, req.ID))) + return w.WriteMessage(websocket.TextMessage, fmt.Appendf(nil, `{"result":null,"id":%d}`, req.ID)) } b = testexch.MockWsInstance[Binance](t, mockws.CurryWsMockUpgrader(t, mock)) } else { @@ -2012,7 +2011,7 @@ func TestSubscribeBadResp(t *testing.T) { var req WsPayload err := json.Unmarshal(msg, &req) require.NoError(tb, err, "Unmarshal should not error") - return w.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf(`{"result":{"error":"carrots"},"id":%d}`, req.ID))) + return w.WriteMessage(websocket.TextMessage, fmt.Appendf(nil, `{"result":{"error":"carrots"},"id":%d}`, req.ID)) } b := testexch.MockWsInstance[Binance](t, mockws.CurryWsMockUpgrader(t, mock)) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes err := b.Subscribe(channels) diff --git a/exchanges/binance/binance_types.go b/exchanges/binance/binance_types.go index 9b9fd3f1..9e41b006 100644 --- a/exchanges/binance/binance_types.go +++ b/exchanges/binance/binance_types.go @@ -47,7 +47,7 @@ type ExchangeInfo struct { Interval string `json:"interval"` Limit int `json:"limit"` } `json:"rateLimits"` - ExchangeFilters interface{} `json:"exchangeFilters"` + ExchangeFilters any `json:"exchangeFilters"` Symbols []*struct { Symbol string `json:"symbol"` Status string `json:"status"` @@ -125,7 +125,7 @@ type CoinInfo struct { // OrderBookDataRequestParams represents Klines request data. type OrderBookDataRequestParams struct { Symbol currency.Pair `json:"symbol"` // Required field; example LTCBTC,BTCUSDT - Limit int `json:"limit"` // Default 100; max 1000. Valid limits:[5, 10, 20, 50, 100, 500, 1000] + Limit int `json:"limit"` // Default 100; max 5000. If limit > 5000, then the response will truncate to 5000 } // OrderbookItem stores an individual orderbook item @@ -157,7 +157,7 @@ type OrderBook struct { type DepthUpdateParams []struct { PriceLevel float64 Quantity float64 - ignore []interface{} + ignore []any } // WebsocketDepthStream is the difference for the update depth stream diff --git a/exchanges/binance/binance_ufutures.go b/exchanges/binance/binance_ufutures.go index 5a966436..74055a05 100644 --- a/exchanges/binance/binance_ufutures.go +++ b/exchanges/binance/binance_ufutures.go @@ -177,8 +177,8 @@ func (b *Binance) URecentTrades(ctx context.Context, symbol currency.Pair, fromI } // UFuturesHistoricalTrades gets historical public trades for USDTMarginedFutures -func (b *Binance) UFuturesHistoricalTrades(ctx context.Context, symbol currency.Pair, fromID string, limit int64) ([]interface{}, error) { - var resp []interface{} +func (b *Binance) UFuturesHistoricalTrades(ctx context.Context, symbol currency.Pair, fromID string, limit int64) ([]any, error) { + var resp []any params := url.Values{} symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures) if err != nil { @@ -253,7 +253,7 @@ func (b *Binance) UKlineData(ctx context.Context, symbol currency.Pair, interval rateBudget = uFuturesKlineMaxRate } - var data [][10]interface{} + var data [][10]any err = b.SendHTTPRequest(ctx, exchange.RestUSDTMargined, ufuturesKlineData+params.Encode(), rateBudget, &data) if err != nil { return nil, err diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 7e414d94..28b192d9 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -66,7 +66,6 @@ func (b *Binance) SetDefaults() { b.Verbose = true b.API.CredentialsValidator.RequiresKey = true b.API.CredentialsValidator.RequiresSecret = true - b.SetValues() for a, ps := range defaultAssetPairStores { if err := b.SetAssetPairStore(a, ps); err != nil { diff --git a/exchanges/binance/cfutures_types.go b/exchanges/binance/cfutures_types.go index 7cc59f09..80744d09 100644 --- a/exchanges/binance/cfutures_types.go +++ b/exchanges/binance/cfutures_types.go @@ -623,7 +623,7 @@ type UFuturesSymbolInfo struct { // CExchangeInfo stores exchange info for cfutures type CExchangeInfo struct { - ExchangeFilters []interface{} `json:"exchangeFilters"` + ExchangeFilters []any `json:"exchangeFilters"` RateLimits []struct { Interval string `json:"interval"` IntervalNum int64 `json:"intervalNul"` diff --git a/exchanges/binanceus/binanceus.go b/exchanges/binanceus/binanceus.go index 27122676..d92a4543 100644 --- a/exchanges/binanceus/binanceus.go +++ b/exchanges/binanceus/binanceus.go @@ -25,7 +25,6 @@ import ( // Binanceus is the overarching type across this package type Binanceus struct { - validLimits []int64 exchange.Base obm *orderbookManager } @@ -114,7 +113,7 @@ const ( recvWindowSize5000 = 5000 ) -var recvWindowSize5000String = strconv.Itoa(recvWindowSize5000) +const recvWindowSize5000String = "5000" // This is a list of error Messages to be returned by binanceus endpoint methods. var ( @@ -125,7 +124,6 @@ var ( errInvalidAssetAmount = errors.New("invalid asset amount") errIncompleteArguments = errors.New("missing required argument") errStartTimeOrFromIDNotSet = errors.New("please set StartTime or FromId, but not both") - errIncorrectLimitValues = errors.New("incorrect limit values - valid values are 5, 10, 20, 50, 100, 500, 1000") errUnexpectedKlineDataLength = errors.New("unexpected kline data length") errMissingRequiredArgumentCoin = errors.New("missing required argument,coin") errMissingRequiredArgumentNetwork = errors.New("missing required argument,network") @@ -147,11 +145,6 @@ var ( errInvalidRowNumber = errors.New("invalid row number") ) -// SetValues sets the default valid values -func (bi *Binanceus) SetValues() { - bi.validLimits = []int64{5, 10, 20, 50, 100, 500, 1000, 5000} -} - // General Data Endpoints // GetServerTime this endpoint returns the exchange server time. @@ -338,9 +331,6 @@ func (bi *Binanceus) batchAggregateTrades(ctx context.Context, arg *AggregatedTr // GetOrderBookDepth to get the order book depth. Please note the limits in the table below. func (bi *Binanceus) GetOrderBookDepth(ctx context.Context, arg *OrderBookDataRequestParams) (*OrderBook, error) { - if err := bi.CheckLimit(arg.Limit); err != nil { - return nil, err - } params := url.Values{} symbol, err := bi.FormatSymbol(arg.Symbol, asset.Spot) if err != nil { @@ -391,16 +381,6 @@ func (bi *Binanceus) GetOrderBookDepth(ctx context.Context, arg *OrderBookDataRe return &orderbook, nil } -// CheckLimit checks value against a variable list -func (bi *Binanceus) CheckLimit(limit int64) error { - for x := range bi.validLimits { - if bi.validLimits[x] == limit { - return nil - } - } - return errIncorrectLimitValues -} - // GetIntervalEnum allowed interval params by Binanceus func (bi *Binanceus) GetIntervalEnum(interval kline.Interval) string { switch interval { @@ -458,7 +438,7 @@ func (bi *Binanceus) GetSpotKline(ctx context.Context, arg *KlinesRequestParams) params.Set("endTime", strconv.FormatInt((arg.EndTime).UnixMilli(), 10)) } path := common.EncodeURLValues(candleStick, params) - var resp interface{} + var resp any err = bi.SendHTTPRequest(ctx, exchange.RestSpotSupplementary, path, @@ -467,16 +447,16 @@ func (bi *Binanceus) GetSpotKline(ctx context.Context, arg *KlinesRequestParams) if err != nil { return nil, err } - responseData, ok := resp.([]interface{}) + responseData, ok := resp.([]any) if !ok { - return nil, common.GetTypeAssertError("[]interface{}", resp, "responseData") + return nil, common.GetTypeAssertError("[]any", resp, "responseData") } klineData := make([]CandleStick, len(responseData)) for x := range responseData { - individualData, ok := responseData[x].([]interface{}) + individualData, ok := responseData[x].([]any) if !ok { - return nil, common.GetTypeAssertError("[]interface{}", responseData[x], "individualData") + return nil, common.GetTypeAssertError("[]any", responseData[x], "individualData") } if len(individualData) != 12 { return nil, errUnexpectedKlineDataLength @@ -805,7 +785,7 @@ func (bi *Binanceus) GetAssetDistributionHistory(ctx context.Context, asset stri func (bi *Binanceus) QuickEnableCryptoWithdrawal(ctx context.Context) error { params := url.Values{} response := struct { - Data interface{} + Data any }{} params.Set("timestamp", strconv.FormatInt(time.Now().UnixMilli(), 10)) return bi.SendAuthHTTPRequest(ctx, exchange.RestSpotSupplementary, @@ -1485,14 +1465,13 @@ func (bi *Binanceus) WithdrawCrypto(ctx context.Context, arg *withdraw.Request) } params.Set("amount", strconv.FormatFloat(arg.Amount, 'f', 0, 64)) var response WithdrawalResponse - er := bi.SendAuthHTTPRequest(ctx, + if err := bi.SendAuthHTTPRequest(ctx, exchange.RestSpotSupplementary, http.MethodPost, applyWithdrawal, - params, spotDefaultRate, &response) - if er != nil { - return "", er + params, spotDefaultRate, &response); err != nil { + return "", err } - return response.ID, er + return response.ID, nil } // WithdrawalHistory gets the status of recent withdrawals @@ -1765,7 +1744,7 @@ func (bi *Binanceus) GetReferralRewardHistory(ctx context.Context, userBusinessT } // SendHTTPRequest sends an unauthenticated request -func (bi *Binanceus) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path string, f request.EndpointLimit, result interface{}) error { +func (bi *Binanceus) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path string, f request.EndpointLimit, result any) error { endpointPath, err := bi.API.Endpoints.GetURL(ePath) if err != nil { return err @@ -1785,7 +1764,7 @@ func (bi *Binanceus) SendHTTPRequest(ctx context.Context, ePath exchange.URL, pa // SendAPIKeyHTTPRequest is a special API request where the api key is // appended to the headers without a secret -func (bi *Binanceus) SendAPIKeyHTTPRequest(ctx context.Context, ePath exchange.URL, path string, f request.EndpointLimit, result interface{}) error { +func (bi *Binanceus) SendAPIKeyHTTPRequest(ctx context.Context, ePath exchange.URL, path string, f request.EndpointLimit, result any) error { endpointPath, err := bi.API.Endpoints.GetURL(ePath) if err != nil { return err @@ -1813,7 +1792,7 @@ func (bi *Binanceus) SendAPIKeyHTTPRequest(ctx context.Context, ePath exchange.U } // SendAuthHTTPRequest sends an authenticated HTTP request -func (bi *Binanceus) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, method, path string, params url.Values, f request.EndpointLimit, result interface{}) error { +func (bi *Binanceus) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, method, path string, params url.Values, f request.EndpointLimit, result any) error { creds, err := bi.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/binanceus/binanceus_types.go b/exchanges/binanceus/binanceus_types.go index 6040d17f..b9bb3c19 100644 --- a/exchanges/binanceus/binanceus_types.go +++ b/exchanges/binanceus/binanceus_types.go @@ -51,7 +51,7 @@ type ExchangeInfo struct { Interval string `json:"interval"` Limit int64 `json:"limit"` } `json:"rateLimits"` - ExchangeFilters interface{} `json:"exchangeFilters"` + ExchangeFilters any `json:"exchangeFilters"` Symbols []struct { Symbol string `json:"symbol"` Status string `json:"status"` @@ -162,7 +162,7 @@ func (a *AggregatedTrade) toTradeData(p currency.Pair, exchange string, aType as // OrderBookDataRequestParams represents Klines request data. type OrderBookDataRequestParams struct { Symbol currency.Pair `json:"symbol"` // Required field; example LTCBTC,BTCUSDT - Limit int64 `json:"limit"` // Default 100; max 1000. Valid limits:[5, 10, 20, 50, 100, 500, 1000] + Limit int64 `json:"limit"` // Default 100; max 5000. If limit > 5000, then the response will truncate to 5000 } // OrderbookItem stores an individual orderbook item @@ -809,9 +809,9 @@ type UserAccountStream struct { // WebsocketPayload defines the payload through the websocket connection type WebsocketPayload struct { - Method string `json:"method"` - Params []interface{} `json:"params"` - ID int64 `json:"id"` + Method string `json:"method"` + Params []any `json:"params"` + ID int64 `json:"id"` } // orderbookManager defines a way of managing and maintaining synchronisation diff --git a/exchanges/binanceus/binanceus_websocket.go b/exchanges/binanceus/binanceus_websocket.go index 7957def1..8b2515d4 100644 --- a/exchanges/binanceus/binanceus_websocket.go +++ b/exchanges/binanceus/binanceus_websocket.go @@ -162,7 +162,7 @@ func stringToOrderStatus(status string) (order.Status, error) { } func (bi *Binanceus) wsHandleData(respRaw []byte) error { - var multiStreamData map[string]interface{} + var multiStreamData map[string]any err := json.Unmarshal(respRaw, &multiStreamData) if err != nil { return err @@ -182,7 +182,7 @@ func (bi *Binanceus) wsHandleData(respRaw []byte) error { return nil } } - if newData, ok := multiStreamData["data"].(map[string]interface{}); ok { + if newData, ok := multiStreamData["data"].(map[string]any); ok { if e, ok := newData["e"].(string); ok { switch e { case "outboundAccountPosition": @@ -581,7 +581,7 @@ func (bi *Binanceus) Subscribe(channelsToSubscribe subscription.List) error { if err != nil { return err } - payload.Params = []interface{}{} + payload.Params = []any{} } } if len(payload.Params) > 0 { @@ -605,7 +605,7 @@ func (bi *Binanceus) Unsubscribe(channelsToUnsubscribe subscription.List) error if err != nil { return err } - payload.Params = []interface{}{} + payload.Params = []any{} } } if len(payload.Params) > 0 { diff --git a/exchanges/binanceus/binanceus_wrapper.go b/exchanges/binanceus/binanceus_wrapper.go index 01ea628d..8a686fe1 100644 --- a/exchanges/binanceus/binanceus_wrapper.go +++ b/exchanges/binanceus/binanceus_wrapper.go @@ -37,7 +37,6 @@ func (bi *Binanceus) SetDefaults() { bi.Verbose = true bi.API.CredentialsValidator.RequiresKey = true bi.API.CredentialsValidator.RequiresSecret = true - bi.SetValues() fmt1 := currency.PairStore{ AssetEnabled: true, diff --git a/exchanges/bitfinex/bitfinex.go b/exchanges/bitfinex/bitfinex.go index 7c6598f5..2d19ebbf 100644 --- a/exchanges/bitfinex/bitfinex.go +++ b/exchanges/bitfinex/bitfinex.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "maps" "net/http" "net/url" "slices" @@ -135,7 +136,7 @@ func (b *Bitfinex) GetPlatformStatus(ctx context.Context) (int, error) { return -1, fmt.Errorf("unexpected platform status value %d", response[0]) } -func baseMarginInfo(data []interface{}) (MarginInfoV2, error) { +func baseMarginInfo(data []any) (MarginInfoV2, error) { var resp MarginInfoV2 marginInfo, ok := data[1].([]any) if !ok { @@ -159,7 +160,7 @@ func baseMarginInfo(data []interface{}) (MarginInfoV2, error) { return resp, nil } -func symbolMarginInfo(data []interface{}) ([]MarginInfoV2, error) { +func symbolMarginInfo(data []any) ([]MarginInfoV2, error) { resp := make([]MarginInfoV2, len(data)) for x := range data { var tempResp MarginInfoV2 @@ -195,7 +196,7 @@ func symbolMarginInfo(data []interface{}) ([]MarginInfoV2, error) { return resp, nil } -func defaultMarginV2Info(data []interface{}) (MarginInfoV2, error) { +func defaultMarginV2Info(data []any) (MarginInfoV2, error) { var resp MarginInfoV2 var ok bool if resp.Symbol, ok = data[1].(string); !ok { @@ -226,7 +227,7 @@ func defaultMarginV2Info(data []interface{}) (MarginInfoV2, error) { // GetV2MarginInfo gets v2 margin info for a symbol provided // symbol: base, sym_all, any other trading symbol example tBTCUSD func (b *Bitfinex) GetV2MarginInfo(ctx context.Context, symbol string) ([]MarginInfoV2, error) { - var data []interface{} + var data []any err := b.SendAuthenticatedHTTPRequestV2(ctx, exchange.RestSpot, http.MethodPost, bitfinexV2MarginInfo+symbol, @@ -258,9 +259,9 @@ func (b *Bitfinex) GetV2MarginInfo(ctx context.Context, symbol string) ([]Margin // GetV2MarginFunding gets borrowing rates for margin trading func (b *Bitfinex) GetV2MarginFunding(ctx context.Context, symbol, amount string, period int32) (MarginV2FundingData, error) { - var resp []interface{} + var resp []any var response MarginV2FundingData - params := make(map[string]interface{}) + params := make(map[string]any) params["symbol"] = symbol params["period"] = period params["amount"] = amount @@ -291,7 +292,7 @@ func (b *Bitfinex) GetV2MarginFunding(ctx context.Context, symbol, amount string // GetV2FundingInfo gets funding info for margin pairs func (b *Bitfinex) GetV2FundingInfo(ctx context.Context, key string) (MarginFundingDataV2, error) { - var resp []interface{} + var resp []any var response MarginFundingDataV2 err := b.SendAuthenticatedHTTPRequestV2(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(bitfinexV2FundingInfo, key), @@ -339,7 +340,7 @@ func (b *Bitfinex) GetV2FundingInfo(ctx context.Context, key string) (MarginFund // GetAccountInfoV2 gets V2 account data func (b *Bitfinex) GetAccountInfoV2(ctx context.Context) (AccountV2Data, error) { var resp AccountV2Data - var data []interface{} + var data []any err := b.SendAuthenticatedHTTPRequestV2(ctx, exchange.RestSpot, http.MethodPost, bitfinexV2AccountInfo, nil, @@ -383,7 +384,7 @@ func (b *Bitfinex) GetAccountInfoV2(ctx context.Context) (AccountV2Data, error) // GetV2Balances gets v2 balances func (b *Bitfinex) GetV2Balances(ctx context.Context) ([]WalletDataV2, error) { - var data [][4]interface{} + var data [][4]any err := b.SendAuthenticatedHTTPRequestV2(ctx, exchange.RestSpot, http.MethodPost, bitfinexV2Balances, @@ -567,7 +568,7 @@ func (b *Bitfinex) GetDerivativeStatusInfo(ctx context.Context, keys, startTime, params.Set("limit", strconv.FormatInt(limit, 10)) } - var result [][]interface{} + var result [][]any path := bitfinexAPIVersion2 + bitfinexDerivativeData + params.Encode() err := b.SendHTTPRequest(ctx, exchange.RestSpot, path, &result, status) @@ -768,7 +769,7 @@ func (b *Bitfinex) GetTrades(ctx context.Context, currencyPair string, limit, ti path := bitfinexAPIVersion2 + bitfinexTrades + currencyPair + "/hist" + "?" + v.Encode() - var resp [][]interface{} + var resp [][]any err := b.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp, tradeRateLimit) if err != nil { return nil, err @@ -846,7 +847,7 @@ func (b *Bitfinex) GetOrderbook(ctx context.Context, symbol, precision string, l u.Set("len", strconv.FormatInt(limit, 10)) } path := bitfinexAPIVersion2 + bitfinexOrderbook + symbol + "/" + precision + "?" + u.Encode() - var response [][]interface{} + var response [][]any err := b.SendHTTPRequest(ctx, exchange.RestSpot, path, &response, orderbookFunction) if err != nil { return Orderbook{}, err @@ -1027,7 +1028,7 @@ func (b *Bitfinex) GetCandles(ctx context.Context, symbol, timeFrame string, sta path += "?" + v.Encode() } - var response [][]interface{} + var response [][]any err := b.SendHTTPRequest(ctx, exchange.RestSpot, path, &response, candle) if err != nil { return nil, err @@ -1064,7 +1065,7 @@ func (b *Bitfinex) GetCandles(ctx context.Context, symbol, timeFrame string, sta path += "/last" - var response []interface{} + var response []any err := b.SendHTTPRequest(ctx, exchange.RestSpot, path, &response, candle) if err != nil { return nil, err @@ -1159,12 +1160,12 @@ func (b *Bitfinex) GetLeaderboard(ctx context.Context, key, timeframe, symbol st vals.Set("end", end) } path = common.EncodeURLValues(path, vals) - var resp []interface{} + var resp []any if err := b.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp, leaderBoardReqRate); err != nil { return nil, err } - parseTwitterHandle := func(i interface{}) string { + parseTwitterHandle := func(i any) string { r, ok := i.(string) if !ok { return "" @@ -1174,7 +1175,7 @@ func (b *Bitfinex) GetLeaderboard(ctx context.Context, key, timeframe, symbol st result := make([]LeaderboardEntry, len(resp)) for x := range resp { - r, ok := resp[x].([]interface{}) + r, ok := resp[x].([]any) if !ok { return nil, errors.New("unable to type assert leaderboard") } @@ -1268,11 +1269,11 @@ func (b *Bitfinex) NewDeposit(ctx context.Context, method, walletName string, re AcceptedWalletNames) } - req := make(map[string]interface{}, 3) + req := make(map[string]any, 3) req["wallet"] = walletName req["method"] = strings.ToLower(method) req["op_renew"] = renew - var result []interface{} + var result []any err := b.SendAuthenticatedHTTPRequestV2(ctx, exchange.RestSpot, @@ -1289,7 +1290,7 @@ func (b *Bitfinex) NewDeposit(ctx context.Context, method, walletName string, re return nil, errors.New("expected result to have a len of 8") } - depositInfo, ok := result[4].([]interface{}) + depositInfo, ok := result[4].([]any) if !ok || len(depositInfo) != 6 { return nil, errors.New("unable to get deposit data") } @@ -1364,7 +1365,7 @@ func (b *Bitfinex) GetAccountBalance(ctx context.Context) ([]Balance, error) { // WalletTo - example "deposit" func (b *Bitfinex) WalletTransfer(ctx context.Context, amount float64, currency, walletFrom, walletTo string) (WalletTransfer, error) { var response []WalletTransfer - req := make(map[string]interface{}) + req := make(map[string]any) req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) req["currency"] = currency req["walletfrom"] = walletFrom @@ -1389,7 +1390,7 @@ func (b *Bitfinex) WalletTransfer(ctx context.Context, amount float64, currency, // For FIAT, use WithdrawFIAT func (b *Bitfinex) WithdrawCryptocurrency(ctx context.Context, wallet, address, paymentID, curr string, amount float64) (Withdrawal, error) { var response []Withdrawal - req := make(map[string]interface{}) + req := make(map[string]any) req["withdraw_type"] = strings.ToLower(curr) req["walletselected"] = wallet req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) @@ -1417,7 +1418,7 @@ func (b *Bitfinex) WithdrawCryptocurrency(ctx context.Context, wallet, address, // WithdrawFIAT Sends an authenticated request to withdraw FIAT currency func (b *Bitfinex) WithdrawFIAT(ctx context.Context, withdrawalType, walletType string, withdrawRequest *withdraw.Request) (Withdrawal, error) { var response []Withdrawal - req := make(map[string]interface{}) + req := make(map[string]any) req["withdraw_type"] = withdrawalType req["walletselected"] = walletType @@ -1467,7 +1468,7 @@ func (b *Bitfinex) NewOrder(ctx context.Context, currencyPair, orderType string, } response := Order{} - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = currencyPair req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) req["price"] = strconv.FormatFloat(price, 'f', -1, 64) @@ -1488,7 +1489,7 @@ func (b *Bitfinex) NewOrder(ctx context.Context, currencyPair, orderType string, // OrderUpdate will send an update signal for an existing order // and attempt to modify it func (b *Bitfinex) OrderUpdate(ctx context.Context, orderID, groupID, clientOrderID string, amount, price, leverage float64) (*Order, error) { - req := make(map[string]interface{}) + req := make(map[string]any) if orderID != "" { req["id"] = orderID } @@ -1514,7 +1515,7 @@ func (b *Bitfinex) OrderUpdate(ctx context.Context, orderID, groupID, clientOrde // NewOrderMulti allows several new orders at once func (b *Bitfinex) NewOrderMulti(ctx context.Context, orders []PlaceOrder) (OrderMultiResponse, error) { response := OrderMultiResponse{} - req := make(map[string]interface{}) + req := make(map[string]any) req["orders"] = orders return response, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, @@ -1527,7 +1528,7 @@ func (b *Bitfinex) NewOrderMulti(ctx context.Context, orders []PlaceOrder) (Orde // CancelExistingOrder cancels a single order by OrderID func (b *Bitfinex) CancelExistingOrder(ctx context.Context, orderID int64) (Order, error) { response := Order{} - req := make(map[string]interface{}) + req := make(map[string]any) req["order_id"] = orderID return response, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, @@ -1540,7 +1541,7 @@ func (b *Bitfinex) CancelExistingOrder(ctx context.Context, orderID int64) (Orde // CancelMultipleOrders cancels multiple orders func (b *Bitfinex) CancelMultipleOrders(ctx context.Context, orderIDs []int64) (string, error) { response := GenericResponse{} - req := make(map[string]interface{}) + req := make(map[string]any) req["order_ids"] = orderIDs return response.Result, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, bitfinexOrderCancelMulti, @@ -1551,8 +1552,8 @@ func (b *Bitfinex) CancelMultipleOrders(ctx context.Context, orderIDs []int64) ( // CancelMultipleOrdersV2 cancels multiple orders func (b *Bitfinex) CancelMultipleOrdersV2(ctx context.Context, orderID, clientOrderID, groupOrderID int64, clientOrderIDDate time.Time, allOrders bool) ([]CancelMultiOrderResponse, error) { - var response []interface{} - req := make(map[string]interface{}) + var response []any + req := make(map[string]any) if orderID > 0 { req["id"] = orderID } @@ -1579,12 +1580,12 @@ func (b *Bitfinex) CancelMultipleOrdersV2(ctx context.Context, orderID, clientOr } var cancelledOrders []CancelMultiOrderResponse for x := range response { - cancelledOrdersSlice, ok := response[x].([]interface{}) + cancelledOrdersSlice, ok := response[x].([]any) if !ok { continue } for y := range cancelledOrdersSlice { - cancelledOrderFields, ok := cancelledOrdersSlice[y].([]interface{}) + cancelledOrderFields, ok := cancelledOrdersSlice[y].([]any) if !ok { continue } @@ -1709,7 +1710,7 @@ func (b *Bitfinex) CancelAllExistingOrders(ctx context.Context) (string, error) // ReplaceOrder replaces an older order with a new order func (b *Bitfinex) ReplaceOrder(ctx context.Context, orderID int64, symbol string, amount, price float64, buy bool, orderType string, hidden bool) (Order, error) { response := Order{} - req := make(map[string]interface{}) + req := make(map[string]any) req["order_id"] = orderID req["symbol"] = symbol req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) @@ -1734,7 +1735,7 @@ func (b *Bitfinex) ReplaceOrder(ctx context.Context, orderID int64, symbol strin // GetOrderStatus returns order status information func (b *Bitfinex) GetOrderStatus(ctx context.Context, orderID int64) (Order, error) { orderStatus := Order{} - req := make(map[string]interface{}) + req := make(map[string]any) req["order_id"] = orderID return orderStatus, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, @@ -1747,7 +1748,7 @@ func (b *Bitfinex) GetOrderStatus(ctx context.Context, orderID int64) (Order, er // GetInactiveOrders returns order status information func (b *Bitfinex) GetInactiveOrders(ctx context.Context, symbol string, ids ...int64) ([]Order, error) { var response []Order - req := make(map[string]interface{}) + req := make(map[string]any) req["limit"] = 2500 if len(ids) > 0 { req["ids"] = ids @@ -1765,7 +1766,7 @@ func (b *Bitfinex) GetInactiveOrders(ctx context.Context, symbol string, ids ... // GetOpenOrders returns all active orders and statuses func (b *Bitfinex) GetOpenOrders(ctx context.Context, ids ...int64) ([]Order, error) { var response []Order - req := make(map[string]interface{}) + req := make(map[string]any) if len(ids) > 0 { req["ids"] = ids } @@ -1790,7 +1791,7 @@ func (b *Bitfinex) GetActivePositions(ctx context.Context) ([]Position, error) { // ClaimPosition allows positions to be claimed func (b *Bitfinex) ClaimPosition(ctx context.Context, positionID int) (Position, error) { response := Position{} - req := make(map[string]interface{}) + req := make(map[string]any) req["position_id"] = positionID return response, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, @@ -1803,7 +1804,7 @@ func (b *Bitfinex) ClaimPosition(ctx context.Context, positionID int) (Position, // GetBalanceHistory returns balance history for the account func (b *Bitfinex) GetBalanceHistory(ctx context.Context, symbol string, timeSince, timeUntil time.Time, limit int, wallet string) ([]BalanceHistory, error) { var response []BalanceHistory - req := make(map[string]interface{}) + req := make(map[string]any) req["currency"] = symbol if !timeSince.IsZero() { @@ -1828,8 +1829,8 @@ func (b *Bitfinex) GetBalanceHistory(ctx context.Context, symbol string, timeSin // GetMovementHistory returns an array of past deposits and withdrawals func (b *Bitfinex) GetMovementHistory(ctx context.Context, symbol, method string, timeSince, timeUntil time.Time, limit int) ([]MovementHistory, error) { - var response [][]interface{} - req := make(map[string]interface{}) + var response [][]any + req := make(map[string]any) req["currency"] = symbol if method != "" { @@ -1924,7 +1925,7 @@ func (b *Bitfinex) GetMovementHistory(ctx context.Context, symbol, method string // GetTradeHistory returns past executed trades func (b *Bitfinex) GetTradeHistory(ctx context.Context, currencyPair string, timestamp, until time.Time, limit, reverse int) ([]TradeHistory, error) { var response []TradeHistory - req := make(map[string]interface{}) + req := make(map[string]any) req["currency"] = currencyPair req["timestamp"] = timestamp @@ -1948,7 +1949,7 @@ func (b *Bitfinex) GetTradeHistory(ctx context.Context, currencyPair string, tim // NewOffer submits a new offer func (b *Bitfinex) NewOffer(ctx context.Context, symbol string, amount, rate float64, period int64, direction string) (Offer, error) { response := Offer{} - req := make(map[string]interface{}) + req := make(map[string]any) req["currency"] = symbol req["amount"] = amount req["rate"] = rate @@ -1965,7 +1966,7 @@ func (b *Bitfinex) NewOffer(ctx context.Context, symbol string, amount, rate flo // CancelOffer cancels offer by offerID func (b *Bitfinex) CancelOffer(ctx context.Context, offerID int64) (Offer, error) { response := Offer{} - req := make(map[string]interface{}) + req := make(map[string]any) req["offer_id"] = offerID return response, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, @@ -1979,7 +1980,7 @@ func (b *Bitfinex) CancelOffer(ctx context.Context, offerID int64) (Offer, error // is still active func (b *Bitfinex) GetOfferStatus(ctx context.Context, offerID int64) (Offer, error) { response := Offer{} - req := make(map[string]interface{}) + req := make(map[string]any) req["offer_id"] = offerID return response, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, @@ -2049,7 +2050,7 @@ func (b *Bitfinex) GetMarginTotalTakenFunds(ctx context.Context) ([]MarginTotalT // CloseMarginFunding closes an unused or used taken fund func (b *Bitfinex) CloseMarginFunding(ctx context.Context, swapID int64) (Offer, error) { response := Offer{} - req := make(map[string]interface{}) + req := make(map[string]any) req["swap_id"] = swapID return response, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, @@ -2060,7 +2061,7 @@ func (b *Bitfinex) CloseMarginFunding(ctx context.Context, swapID int64) (Offer, } // SendHTTPRequest sends an unauthenticated request -func (b *Bitfinex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}, e request.EndpointLimit) error { +func (b *Bitfinex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any, e request.EndpointLimit) error { endpoint, err := b.API.Endpoints.GetURL(ep) if err != nil { return err @@ -2081,7 +2082,7 @@ func (b *Bitfinex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st // SendAuthenticatedHTTPRequest sends an authenticated http request and json // unmarshals result to a supplied variable -func (b *Bitfinex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params map[string]interface{}, result interface{}, endpoint request.EndpointLimit) error { +func (b *Bitfinex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params map[string]any, result any, endpoint request.EndpointLimit) error { creds, err := b.GetCredentials(ctx) if err != nil { return err @@ -2094,13 +2095,11 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange fullPath := ePoint + bitfinexAPIVersion + path return b.SendPayload(ctx, endpoint, func() (*request.Item, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["request"] = bitfinexAPIVersion + path req["nonce"] = b.Requester.GetNonce(nonce.UnixNano).String() - for key, value := range params { - req[key] = value - } + maps.Copy(req, params) PayloadJSON, err := json.Marshal(req) if err != nil { @@ -2134,7 +2133,7 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange // SendAuthenticatedHTTPRequestV2 sends an authenticated http request and json // unmarshals result to a supplied variable -func (b *Bitfinex) SendAuthenticatedHTTPRequestV2(ctx context.Context, ep exchange.URL, method, path string, params map[string]interface{}, result interface{}, endpoint request.EndpointLimit) error { +func (b *Bitfinex) SendAuthenticatedHTTPRequestV2(ctx context.Context, ep exchange.URL, method, path string, params map[string]any, result any, endpoint request.EndpointLimit) error { creds, err := b.GetCredentials(ctx) if err != nil { return err @@ -2285,7 +2284,7 @@ func (b *Bitfinex) PopulateAcceptableMethods(ctx context.Context) error { return nil } - var response [][][]interface{} + var response [][][]any err := b.SendHTTPRequest(ctx, exchange.RestSpot, bitfinexAPIVersion2+bitfinexDepositMethod, @@ -2311,7 +2310,7 @@ func (b *Bitfinex) PopulateAcceptableMethods(ctx context.Context) error { } var availOptions []string - options, ok := data[x][1].([]interface{}) + options, ok := data[x][1].([]any) if !ok { return errors.New("unable to type assert options") } diff --git a/exchanges/bitfinex/bitfinex_test.go b/exchanges/bitfinex/bitfinex_test.go index 91bb3250..484d9520 100644 --- a/exchanges/bitfinex/bitfinex_test.go +++ b/exchanges/bitfinex/bitfinex_test.go @@ -1114,11 +1114,11 @@ func TestWSAuth(t *testing.T) { testexch.SetupWs(t, b) require.True(t, b.Websocket.CanUseAuthenticatedEndpoints(), "CanUseAuthenticatedEndpoints should be turned on") - var resp map[string]interface{} + var resp map[string]any catcher := func() (ok bool) { select { case v := <-b.Websocket.ToRoutine: - resp, ok = v.(map[string]interface{}) + resp, ok = v.(map[string]any) default: } return diff --git a/exchanges/bitfinex/bitfinex_types.go b/exchanges/bitfinex/bitfinex_types.go index c1c65636..08da47da 100644 --- a/exchanges/bitfinex/bitfinex_types.go +++ b/exchanges/bitfinex/bitfinex_types.go @@ -254,7 +254,7 @@ type AccountInfoFees struct { // AccountFees stores withdrawal account fee data from Bitfinex type AccountFees struct { - Withdraw map[string]interface{} `json:"withdraw"` + Withdraw map[string]any `json:"withdraw"` } // AccountSummary holds account summary data @@ -639,7 +639,7 @@ type WsFundingOffer struct { Amount float64 OriginalAmount float64 Type string - Flags interface{} + Flags any Status string Rate float64 Period int64 @@ -658,7 +658,7 @@ type WsCredit struct { Created time.Time Updated time.Time Amount float64 - Flags interface{} // Future params object (stay tuned) + Flags any // Future params object (stay tuned) Status string Rate float64 Period int64 diff --git a/exchanges/bitfinex/bitfinex_websocket.go b/exchanges/bitfinex/bitfinex_websocket.go index 020db54d..ed27bad9 100644 --- a/exchanges/bitfinex/bitfinex_websocket.go +++ b/exchanges/bitfinex/bitfinex_websocket.go @@ -205,14 +205,14 @@ func (b *Bitfinex) WsDataHandler() { } func (b *Bitfinex) wsHandleData(respRaw []byte) error { - var result interface{} + var result any if err := json.Unmarshal(respRaw, &result); err != nil { return err } switch d := result.(type) { - case map[string]interface{}: + case map[string]any: return b.handleWSEvent(respRaw) - case []interface{}: + case []any: chanIDFloat, ok := d[0].(float64) if !ok { return common.GetTypeAssertError("float64", d[0], "chanID") @@ -244,17 +244,17 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { case wsNotification: return b.handleWSNotification(d, respRaw) case wsOrderSnapshot: - if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 { - if _, ok := snapBundle[0].([]interface{}); ok { + if snapBundle, ok := d[2].([]any); ok && len(snapBundle) > 0 { + if _, ok := snapBundle[0].([]any); ok { for i := range snapBundle { - if positionData, ok := snapBundle[i].([]interface{}); ok { + if positionData, ok := snapBundle[i].([]any); ok { b.wsHandleOrder(positionData) } } } } case wsOrderCancel, wsOrderNew, wsOrderUpdate: - if oData, ok := d[2].([]interface{}); ok && len(oData) > 0 { + if oData, ok := d[2].([]any); ok && len(oData) > 0 { b.wsHandleOrder(oData) } case wsPositionSnapshot: @@ -264,11 +264,11 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { case wsTradeExecuted, wsTradeUpdated: return b.handleWSMyTradeUpdate(d, eventType) case wsFundingOfferSnapshot: - if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 { - if _, ok := snapBundle[0].([]interface{}); ok { + if snapBundle, ok := d[2].([]any); ok && len(snapBundle) > 0 { + if _, ok := snapBundle[0].([]any); ok { snapshot := make([]*WsFundingOffer, len(snapBundle)) for i := range snapBundle { - data, ok := snapBundle[i].([]interface{}) + data, ok := snapBundle[i].([]any) if !ok { return errors.New("unable to type assert wsFundingOrderSnapshot snapBundle data") } @@ -282,7 +282,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { } } case wsFundingOfferNew, wsFundingOfferUpdate, wsFundingOfferCancel: - if data, ok := d[2].([]interface{}); ok && len(data) > 0 { + if data, ok := d[2].([]any); ok && len(data) > 0 { offer, err := wsHandleFundingOffer(data, true /* include rate real */) if err != nil { return err @@ -290,11 +290,11 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { b.Websocket.DataHandler <- offer } case wsFundingCreditSnapshot: - if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 { - if _, ok := snapBundle[0].([]interface{}); ok { + if snapBundle, ok := d[2].([]any); ok && len(snapBundle) > 0 { + if _, ok := snapBundle[0].([]any); ok { snapshot := make([]*WsCredit, len(snapBundle)) for i := range snapBundle { - data, ok := snapBundle[i].([]interface{}) + data, ok := snapBundle[i].([]any) if !ok { return errors.New("unable to type assert wsFundingCreditSnapshot snapBundle data") } @@ -308,7 +308,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { } } case wsFundingCreditNew, wsFundingCreditUpdate, wsFundingCreditCancel: - if data, ok := d[2].([]interface{}); ok && len(data) > 0 { + if data, ok := d[2].([]any); ok && len(data) > 0 { fundingCredit, err := wsHandleFundingCreditLoanData(data, true /* include position pair */) if err != nil { return err @@ -316,11 +316,11 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { b.Websocket.DataHandler <- fundingCredit } case wsFundingLoanSnapshot: - if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 { - if _, ok := snapBundle[0].([]interface{}); ok { + if snapBundle, ok := d[2].([]any); ok && len(snapBundle) > 0 { + if _, ok := snapBundle[0].([]any); ok { snapshot := make([]*WsCredit, len(snapBundle)) for i := range snapBundle { - data, ok := snapBundle[i].([]interface{}) + data, ok := snapBundle[i].([]any) if !ok { return errors.New("unable to type assert wsFundingLoanSnapshot snapBundle data") } @@ -334,7 +334,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { } } case wsFundingLoanNew, wsFundingLoanUpdate, wsFundingLoanCancel: - if data, ok := d[2].([]interface{}); ok && len(data) > 0 { + if data, ok := d[2].([]any); ok && len(data) > 0 { fundingData, err := wsHandleFundingCreditLoanData(data, false /* include position pair */) if err != nil { return err @@ -342,11 +342,11 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { b.Websocket.DataHandler <- fundingData } case wsWalletSnapshot: - if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 { - if _, ok := snapBundle[0].([]interface{}); ok { + if snapBundle, ok := d[2].([]any); ok && len(snapBundle) > 0 { + if _, ok := snapBundle[0].([]any); ok { snapshot := make([]WsWallet, len(snapBundle)) for i := range snapBundle { - data, ok := snapBundle[i].([]interface{}) + data, ok := snapBundle[i].([]any) if !ok { return errors.New("unable to type assert wsWalletSnapshot snapBundle data") } @@ -374,7 +374,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { } } case wsWalletUpdate: - if data, ok := d[2].([]interface{}); ok && len(data) > 0 { + if data, ok := d[2].([]any); ok && len(data) > 0 { var wallet WsWallet if wallet.Type, ok = data[0].(string); !ok { return errors.New("unable to type assert wallet snapshot type") @@ -396,7 +396,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { b.Websocket.DataHandler <- wallet } case wsBalanceUpdate: - if data, ok := d[2].([]interface{}); ok && len(data) > 0 { + if data, ok := d[2].([]any); ok && len(data) > 0 { var balance WsBalanceInfo if balance.TotalAssetsUnderManagement, ok = data[0].(float64); !ok { return errors.New("unable to type assert balance total assets under management") @@ -407,9 +407,9 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { b.Websocket.DataHandler <- balance } case wsMarginInfoUpdate: - if data, ok := d[2].([]interface{}); ok && len(data) > 0 { + if data, ok := d[2].([]any); ok && len(data) > 0 { if eventType, ok := data[0].(string); ok && eventType == "base" { - baseData, ok := data[1].([]interface{}) + baseData, ok := data[1].([]any) if !ok { return errors.New("unable to type assert wsMarginInfoUpdate baseData") } @@ -433,9 +433,9 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { } } case wsFundingInfoUpdate: - if data, ok := d[2].([]interface{}); ok && len(data) > 0 { + if data, ok := d[2].([]any); ok && len(data) > 0 { if fundingType, ok := data[0].(string); ok && fundingType == "sym" { - symbolData, ok := data[2].([]interface{}) + symbolData, ok := data[2].([]any) if !ok { return errors.New("unable to type assert wsFundingInfoUpdate symbolData") } @@ -459,7 +459,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { } } case wsFundingTradeExecuted, wsFundingTradeUpdated: - if data, ok := d[2].([]interface{}); ok && len(data) > 0 { + if data, ok := d[2].([]any); ok && len(data) > 0 { var wsFundingTrade WsFundingTrade tradeID, ok := data[0].(float64) if !ok { @@ -540,7 +540,7 @@ func (b *Bitfinex) handleWSEvent(respRaw []byte) error { return fmt.Errorf("%w 'status': %w from message: %s", common.ErrParsingWSField, err, respRaw) } if status == "OK" { - var glob map[string]interface{} + var glob map[string]any if err := json.Unmarshal(respRaw, &glob); err != nil { return fmt.Errorf("unable to Unmarshal auth resp; Error: %w Msg: %v", err, respRaw) } @@ -606,7 +606,7 @@ func (b *Bitfinex) handleWSSubscribed(respRaw []byte) error { return b.Websocket.Match.RequireMatchWithData("subscribe:"+subID, respRaw) } -func (b *Bitfinex) handleWSChannelUpdate(s *subscription.Subscription, respRaw []byte, eventType string, d []interface{}) error { +func (b *Bitfinex) handleWSChannelUpdate(s *subscription.Subscription, respRaw []byte, eventType string, d []any) error { if s == nil { return fmt.Errorf("%w: Subscription param", common.ErrNilPointer) } @@ -636,7 +636,7 @@ func (b *Bitfinex) handleWSChannelUpdate(s *subscription.Subscription, respRaw [ return fmt.Errorf("%s unhandled channel update: %s", b.Name, s.Channel) } -func (b *Bitfinex) handleWSChecksum(c *subscription.Subscription, d []interface{}) error { +func (b *Bitfinex) handleWSChecksum(c *subscription.Subscription, d []any) error { if c == nil { return fmt.Errorf("%w: Subscription param", common.ErrNilPointer) } @@ -670,7 +670,7 @@ func (b *Bitfinex) handleWSChecksum(c *subscription.Subscription, d []interface{ return nil } -func (b *Bitfinex) handleWSBookUpdate(c *subscription.Subscription, d []interface{}) error { +func (b *Bitfinex) handleWSBookUpdate(c *subscription.Subscription, d []any) error { if c == nil { return fmt.Errorf("%w: Subscription param", common.ErrNilPointer) } @@ -678,7 +678,7 @@ func (b *Bitfinex) handleWSBookUpdate(c *subscription.Subscription, d []interfac return subscription.ErrNotSinglePair } var newOrderbook []WebsocketBook - obSnapBundle, ok := d[1].([]interface{}) + obSnapBundle, ok := d[1].([]any) if !ok { return errors.New("orderbook interface cast failed") } @@ -694,9 +694,9 @@ func (b *Bitfinex) handleWSBookUpdate(c *subscription.Subscription, d []interfac } var fundingRate bool switch id := obSnapBundle[0].(type) { - case []interface{}: + case []any: for i := range obSnapBundle { - data, ok := obSnapBundle[i].([]interface{}) + data, ok := obSnapBundle[i].([]any) if !ok { return errors.New("type assertion failed for orderbok item data") } @@ -775,23 +775,23 @@ func (b *Bitfinex) handleWSBookUpdate(c *subscription.Subscription, d []interfac return nil } -func (b *Bitfinex) handleWSCandleUpdate(c *subscription.Subscription, d []interface{}) error { +func (b *Bitfinex) handleWSCandleUpdate(c *subscription.Subscription, d []any) error { if c == nil { return fmt.Errorf("%w: Subscription param", common.ErrNilPointer) } if len(c.Pairs) != 1 { return subscription.ErrNotSinglePair } - candleBundle, ok := d[1].([]interface{}) + candleBundle, ok := d[1].([]any) if !ok || len(candleBundle) == 0 { return nil } switch candleData := candleBundle[0].(type) { - case []interface{}: + case []any: for i := range candleBundle { - var element []interface{} - element, ok = candleBundle[i].([]interface{}) + var element []any + element, ok = candleBundle[i].([]any) if !ok { return errors.New("candle type assertion for element data") } @@ -855,14 +855,14 @@ func (b *Bitfinex) handleWSCandleUpdate(c *subscription.Subscription, d []interf return nil } -func (b *Bitfinex) handleWSTickerUpdate(c *subscription.Subscription, d []interface{}) error { +func (b *Bitfinex) handleWSTickerUpdate(c *subscription.Subscription, d []any) error { if c == nil { return fmt.Errorf("%w: Subscription param", common.ErrNilPointer) } if len(c.Pairs) != 1 { return subscription.ErrNotSinglePair } - tickerData, ok := d[1].([]interface{}) + tickerData, ok := d[1].([]any) if !ok { return errors.New("type assertion for tickerData") } @@ -1007,12 +1007,12 @@ func (b *Bitfinex) handleWSPublicTradeUpdate(respRaw []byte) (*wsTrade, error) { return t, json.Unmarshal(v, t) } -func (b *Bitfinex) handleWSNotification(d []interface{}, respRaw []byte) error { - notification, ok := d[2].([]interface{}) +func (b *Bitfinex) handleWSNotification(d []any, respRaw []byte) error { + notification, ok := d[2].([]any) if !ok { return errors.New("unable to type assert notification data") } - if data, ok := notification[4].([]interface{}); ok { + if data, ok := notification[4].([]any); ok { channelName, ok := notification[1].(string) if !ok { return errors.New("unable to type assert channelName") @@ -1078,19 +1078,19 @@ func (b *Bitfinex) handleWSNotification(d []interface{}, respRaw []byte) error { return nil } -func (b *Bitfinex) handleWSPositionSnapshot(d []interface{}) error { - snapBundle, ok := d[2].([]interface{}) +func (b *Bitfinex) handleWSPositionSnapshot(d []any) error { + snapBundle, ok := d[2].([]any) if !ok { - return common.GetTypeAssertError("[]interface{}", d[2], "positionSnapshotBundle") + return common.GetTypeAssertError("[]any", d[2], "positionSnapshotBundle") } if len(snapBundle) == 0 { return nil } snapshot := make([]WebsocketPosition, len(snapBundle)) for i := range snapBundle { - positionData, ok := snapBundle[i].([]interface{}) + positionData, ok := snapBundle[i].([]any) if !ok { - return common.GetTypeAssertError("[]interface{}", snapBundle[i], "positionSnapshot") + return common.GetTypeAssertError("[]any", snapBundle[i], "positionSnapshot") } var position WebsocketPosition if position.Pair, ok = positionData[0].(string); !ok { @@ -1131,10 +1131,10 @@ func (b *Bitfinex) handleWSPositionSnapshot(d []interface{}) error { return nil } -func (b *Bitfinex) handleWSPositionUpdate(d []interface{}) error { - positionData, ok := d[2].([]interface{}) +func (b *Bitfinex) handleWSPositionUpdate(d []any) error { + positionData, ok := d[2].([]any) if !ok { - return common.GetTypeAssertError("[]interface{}", d[2], "positionUpdate") + return common.GetTypeAssertError("[]any", d[2], "positionUpdate") } if len(positionData) == 0 { return nil @@ -1176,10 +1176,10 @@ func (b *Bitfinex) handleWSPositionUpdate(d []interface{}) error { return nil } -func (b *Bitfinex) handleWSMyTradeUpdate(d []interface{}, eventType string) error { - tradeData, ok := d[2].([]interface{}) +func (b *Bitfinex) handleWSMyTradeUpdate(d []any, eventType string) error { + tradeData, ok := d[2].([]any) if !ok { - return common.GetTypeAssertError("[]interface{}", d[2], "tradeUpdate") + return common.GetTypeAssertError("[]any", d[2], "tradeUpdate") } if len(tradeData) <= 4 { return nil @@ -1232,7 +1232,7 @@ func (b *Bitfinex) handleWSMyTradeUpdate(d []interface{}, eventType string) erro return nil } -func wsHandleFundingOffer(data []interface{}, includeRateReal bool) (*WsFundingOffer, error) { +func wsHandleFundingOffer(data []any, includeRateReal bool) (*WsFundingOffer, error) { var offer WsFundingOffer var ok bool if data[0] != nil { @@ -1327,7 +1327,7 @@ func wsHandleFundingOffer(data []interface{}, includeRateReal bool) (*WsFundingO return &offer, nil } -func wsHandleFundingCreditLoanData(data []interface{}, includePositionPair bool) (*WsCredit, error) { +func wsHandleFundingCreditLoanData(data []any, includePositionPair bool) (*WsCredit, error) { var credit WsCredit var ok bool if data[0] != nil { @@ -1445,7 +1445,7 @@ func wsHandleFundingCreditLoanData(data []interface{}, includePositionPair bool) return &credit, nil } -func (b *Bitfinex) wsHandleOrder(data []interface{}) { +func (b *Bitfinex) wsHandleOrder(data []any) { var od order.Detail var err error od.Exchange = b.Name @@ -1709,7 +1709,7 @@ func (b *Bitfinex) GetSubscriptionTemplate(_ *subscription.Subscription) (*templ // ConfigureWS to send checksums and sequence numbers func (b *Bitfinex) ConfigureWS() error { - return b.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, map[string]interface{}{ + return b.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, map[string]any{ "event": "conf", "flags": bitfinexChecksumFlag + bitfinexWsSequenceFlag, }) @@ -1790,7 +1790,7 @@ func (b *Bitfinex) unsubscribeFromChan(subs subscription.List) error { return common.GetTypeAssertError("int", s.Key, "subscription.Key") } - req := map[string]interface{}{ + req := map[string]any{ "event": "unsubscribe", "chanId": chanID, } @@ -1878,7 +1878,7 @@ func (b *Bitfinex) WsNewOrder(data *WsNewOrderRequest) (string, error) { if resp == nil { return "", errors.New(b.Name + " - Order message not returned") } - var respData []interface{} + var respData []any err = json.Unmarshal(resp, &respData) if err != nil { return "", err @@ -1887,7 +1887,7 @@ func (b *Bitfinex) WsNewOrder(data *WsNewOrderRequest) (string, error) { if len(respData) < 3 { return "", errors.New("unexpected respData length") } - responseDataDetail, ok := respData[2].([]interface{}) + responseDataDetail, ok := respData[2].([]any) if !ok { return "", errors.New("unable to type assert respData") } @@ -1896,7 +1896,7 @@ func (b *Bitfinex) WsNewOrder(data *WsNewOrderRequest) (string, error) { return "", errors.New("invalid responseDataDetail length") } - responseOrderDetail, ok := responseDataDetail[4].([]interface{}) + responseOrderDetail, ok := responseDataDetail[4].([]any) if !ok { return "", errors.New("unable to type assert responseOrderDetail") } @@ -1936,7 +1936,7 @@ func (b *Bitfinex) WsModifyOrder(data *WsUpdateOrderRequest) error { return errors.New(b.Name + " - Order message not returned") } - var responseData []interface{} + var responseData []any err = json.Unmarshal(resp, &responseData) if err != nil { return err @@ -1944,7 +1944,7 @@ func (b *Bitfinex) WsModifyOrder(data *WsUpdateOrderRequest) error { if len(responseData) < 3 { return errors.New("unexpected responseData length") } - responseOrderData, ok := responseData[2].([]interface{}) + responseOrderData, ok := responseData[2].([]any) if !ok { return errors.New("unable to type assert responseOrderData") } @@ -1989,7 +1989,7 @@ func (b *Bitfinex) WsCancelOrder(orderID int64) error { if resp == nil { return fmt.Errorf("%v - Order %v failed to cancel", b.Name, orderID) } - var responseData []interface{} + var responseData []any err = json.Unmarshal(resp, &responseData) if err != nil { return err @@ -1997,7 +1997,7 @@ func (b *Bitfinex) WsCancelOrder(orderID int64) error { if len(responseData) < 3 { return errors.New("unexpected responseData length") } - responseOrderData, ok := responseData[2].([]interface{}) + responseOrderData, ok := responseData[2].([]any) if !ok { return errors.New("unable to type assert responseOrderData") } @@ -2046,7 +2046,7 @@ func (b *Bitfinex) WsCancelOffer(orderID int64) error { if resp == nil { return fmt.Errorf("%v - Order %v failed to cancel", b.Name, orderID) } - var responseData []interface{} + var responseData []any err = json.Unmarshal(resp, &responseData) if err != nil { return err @@ -2054,7 +2054,7 @@ func (b *Bitfinex) WsCancelOffer(orderID int64) error { if len(responseData) < 3 { return errors.New("unexpected responseData length") } - responseOrderData, ok := responseData[2].([]interface{}) + responseOrderData, ok := responseData[2].([]any) if !ok { return errors.New("unable to type assert responseOrderData") } @@ -2078,8 +2078,8 @@ func (b *Bitfinex) WsCancelOffer(orderID int64) error { return nil } -func makeRequestInterface(channelName string, data interface{}) []interface{} { - return []interface{}{0, channelName, nil, data} +func makeRequestInterface(channelName string, data any) []any { + return []any{0, channelName, nil, data} } func validateCRC32(book *orderbook.Base, token uint32) error { @@ -2185,7 +2185,7 @@ func subToMap(s *subscription.Subscription, a asset.Item, p currency.Pair) map[s if name, ok := subscriptionNames[s.Channel]; ok { c = name } - req := map[string]interface{}{ + req := map[string]any{ "channel": c, } diff --git a/exchanges/bitflyer/bitflyer.go b/exchanges/bitflyer/bitflyer.go index 6ad8ae5a..fe29586d 100644 --- a/exchanges/bitflyer/bitflyer.go +++ b/exchanges/bitflyer/bitflyer.go @@ -287,7 +287,7 @@ func (b *Bitflyer) GetTradingCommission() { } // SendHTTPRequest sends an unauthenticated request -func (b *Bitflyer) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error { +func (b *Bitflyer) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { endpoint, err := b.API.Endpoints.GetURL(ep) if err != nil { return err diff --git a/exchanges/bithumb/bithumb.go b/exchanges/bithumb/bithumb.go index 101795b0..58c2a1bb 100644 --- a/exchanges/bithumb/bithumb.go +++ b/exchanges/bithumb/bithumb.go @@ -530,7 +530,7 @@ func (b *Bithumb) MarketSellOrder(ctx context.Context, pair currency.Pair, units } // SendHTTPRequest sends an unauthenticated HTTP request -func (b *Bithumb) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error { +func (b *Bithumb) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { endpoint, err := b.API.Endpoints.GetURL(ep) if err != nil { return err @@ -549,7 +549,7 @@ func (b *Bithumb) SendHTTPRequest(ctx context.Context, ep exchange.URL, path str } // SendAuthenticatedHTTPRequest sends an authenticated HTTP request to bithumb -func (b *Bithumb) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, path string, params url.Values, result interface{}) error { +func (b *Bithumb) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, path string, params url.Values, result any) error { creds, err := b.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/bithumb/bithumb_types.go b/exchanges/bithumb/bithumb_types.go index 3622f883..92f23da4 100644 --- a/exchanges/bithumb/bithumb_types.go +++ b/exchanges/bithumb/bithumb_types.go @@ -83,9 +83,9 @@ type Account struct { // Balance holds balance details type Balance struct { - Status string `json:"status"` - Data map[string]interface{} `json:"data"` - Message string `json:"message"` + Status string `json:"status"` + Data map[string]any `json:"data"` + Message string `json:"message"` } // WalletAddressRes contains wallet address information @@ -290,8 +290,8 @@ type FullBalance struct { // OHLCVResponse holds returned kline data type OHLCVResponse struct { - Status string `json:"status"` - Data [][6]interface{} `json:"data"` + Status string `json:"status"` + Data [][6]any `json:"data"` } // Status defines the current exchange allowance to deposit or withdraw a diff --git a/exchanges/bithumb/bithumb_websocket_test.go b/exchanges/bithumb/bithumb_websocket_test.go index c343e2d0..39fbb93a 100644 --- a/exchanges/bithumb/bithumb_websocket_test.go +++ b/exchanges/bithumb/bithumb_websocket_test.go @@ -54,7 +54,7 @@ func TestWsHandleData(t *testing.T) { }, }, Websocket: &stream.Websocket{ - DataHandler: make(chan interface{}, 1), + DataHandler: make(chan any, 1), }, }, } diff --git a/exchanges/bitmex/bitmex.go b/exchanges/bitmex/bitmex.go index 281fe3ec..cb76bfb4 100644 --- a/exchanges/bitmex/bitmex.go +++ b/exchanges/bitmex/bitmex.go @@ -837,8 +837,8 @@ func (b *Bitmex) GetWalletSummary(ctx context.Context, currency string) ([]Trans } // SendHTTPRequest sends an unauthenticated HTTP request -func (b *Bitmex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, params Parameter, result interface{}) error { - var respCheck interface{} +func (b *Bitmex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, params Parameter, result any) error { + var respCheck any endpoint, err := b.API.Endpoints.GetURL(ep) if err != nil { return err @@ -871,7 +871,7 @@ func (b *Bitmex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path stri } // SendAuthenticatedHTTPRequest sends an authenticated HTTP request to bitmex -func (b *Bitmex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, verb, path string, params Parameter, result interface{}) error { +func (b *Bitmex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, verb, path string, params Parameter, result any) error { creds, err := b.GetCredentials(ctx) if err != nil { return err @@ -881,7 +881,7 @@ func (b *Bitmex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U return err } - var respCheck interface{} + var respCheck any newRequest := func() (*request.Item, error) { expires := time.Now().Add(time.Second * 10) timestamp := expires.UnixNano() @@ -937,7 +937,7 @@ func (b *Bitmex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U } // CaptureError little hack that captures an error -func (b *Bitmex) CaptureError(resp, reType interface{}) error { +func (b *Bitmex) CaptureError(resp, reType any) error { var Error RequestError marshalled, err := json.Marshal(resp) diff --git a/exchanges/bitmex/bitmex_parameters.go b/exchanges/bitmex/bitmex_parameters.go index a238192c..1b0766e3 100644 --- a/exchanges/bitmex/bitmex_parameters.go +++ b/exchanges/bitmex/bitmex_parameters.go @@ -19,7 +19,7 @@ type Parameter interface { // StructValsToURLVals converts a struct into url.values for easy encoding // can set json tags for outgoing naming conventions. -func StructValsToURLVals(v interface{}) (url.Values, error) { +func StructValsToURLVals(v any) (url.Values, error) { values := url.Values{} if reflect.ValueOf(v).Kind() != reflect.Ptr { diff --git a/exchanges/bitmex/bitmex_types.go b/exchanges/bitmex/bitmex_types.go index c404ed7d..0171bb7e 100644 --- a/exchanges/bitmex/bitmex_types.go +++ b/exchanges/bitmex/bitmex_types.go @@ -25,15 +25,15 @@ type Announcement struct { // APIKey Persistent API Keys for Developers type APIKey struct { - Cidr string `json:"cidr"` - Created string `json:"created"` - Enabled bool `json:"enabled"` - ID string `json:"id"` - Name string `json:"name"` - Nonce int64 `json:"nonce"` - Permissions []interface{} `json:"permissions"` - Secret string `json:"secret"` - UserID int32 `json:"userId"` + Cidr string `json:"cidr"` + Created string `json:"created"` + Enabled bool `json:"enabled"` + ID string `json:"id"` + Name string `json:"name"` + Nonce int64 `json:"nonce"` + Permissions []any `json:"permissions"` + Secret string `json:"secret"` + UserID int32 `json:"userId"` } // Chat Trollbox Data @@ -514,32 +514,32 @@ type User struct { // UserPreferences user preferences type UserPreferences struct { - AlertOnLiquidations bool `json:"alertOnLiquidations"` - AnimationsEnabled bool `json:"animationsEnabled"` - AnnouncementsLastSeen string `json:"announcementsLastSeen"` - ChatChannelID float64 `json:"chatChannelID"` - ColorTheme string `json:"colorTheme"` - Currency string `json:"currency"` - Debug bool `json:"debug"` - DisableEmails []string `json:"disableEmails"` - HideConfirmDialogs []string `json:"hideConfirmDialogs"` - HideConnectionModal bool `json:"hideConnectionModal"` - HideFromLeaderboard bool `json:"hideFromLeaderboard"` - HideNameFromLeaderboard bool `json:"hideNameFromLeaderboard"` - HideNotifications []string `json:"hideNotifications"` - Locale string `json:"locale"` - MsgsSeen []string `json:"msgsSeen"` - OrderBookBinning interface{} `json:"orderBookBinning"` - OrderBookType string `json:"orderBookType"` - OrderClearImmediate bool `json:"orderClearImmediate"` - OrderControlsPlusMinus bool `json:"orderControlsPlusMinus"` - ShowLocaleNumbers bool `json:"showLocaleNumbers"` - Sounds []string `json:"sounds"` - StrictIPCheck bool `json:"strictIPCheck"` - StrictTimeout bool `json:"strictTimeout"` - TickerGroup string `json:"tickerGroup"` - TickerPinned bool `json:"tickerPinned"` - TradeLayout string `json:"tradeLayout"` + AlertOnLiquidations bool `json:"alertOnLiquidations"` + AnimationsEnabled bool `json:"animationsEnabled"` + AnnouncementsLastSeen string `json:"announcementsLastSeen"` + ChatChannelID float64 `json:"chatChannelID"` + ColorTheme string `json:"colorTheme"` + Currency string `json:"currency"` + Debug bool `json:"debug"` + DisableEmails []string `json:"disableEmails"` + HideConfirmDialogs []string `json:"hideConfirmDialogs"` + HideConnectionModal bool `json:"hideConnectionModal"` + HideFromLeaderboard bool `json:"hideFromLeaderboard"` + HideNameFromLeaderboard bool `json:"hideNameFromLeaderboard"` + HideNotifications []string `json:"hideNotifications"` + Locale string `json:"locale"` + MsgsSeen []string `json:"msgsSeen"` + OrderBookBinning any `json:"orderBookBinning"` + OrderBookType string `json:"orderBookType"` + OrderClearImmediate bool `json:"orderClearImmediate"` + OrderControlsPlusMinus bool `json:"orderControlsPlusMinus"` + ShowLocaleNumbers bool `json:"showLocaleNumbers"` + Sounds []string `json:"sounds"` + StrictIPCheck bool `json:"strictIPCheck"` + StrictTimeout bool `json:"strictTimeout"` + TickerGroup string `json:"tickerGroup"` + TickerPinned bool `json:"tickerPinned"` + TradeLayout string `json:"tradeLayout"` } // AffiliateStatus affiliate Status details diff --git a/exchanges/bitmex/bitmex_websocket_types.go b/exchanges/bitmex/bitmex_websocket_types.go index dc22099a..d4f6b7c5 100644 --- a/exchanges/bitmex/bitmex_websocket_types.go +++ b/exchanges/bitmex/bitmex_websocket_types.go @@ -14,7 +14,7 @@ type WebsocketRequest struct { type WebsocketErrorResponse struct { Status int64 `json:"status"` Error string `json:"error"` - Meta interface{} `json:"meta"` + Meta any `json:"meta"` Request WebsocketRequest `json:"request"` } @@ -79,10 +79,10 @@ type AnnouncementData struct { // WsAffiliateResponse private api response type WsAffiliateResponse struct { WsDataResponse - ForeignKeys interface{} `json:"foreignKeys"` + ForeignKeys any `json:"foreignKeys"` Attributes WsAffiliateResponseAttributes `json:"attributes"` Filter WsAffiliateResponseFilter `json:"filter"` - Data []interface{} `json:"data"` + Data []any `json:"data"` } // WsAffiliateResponseAttributes private api data @@ -179,10 +179,10 @@ type WsOrderResponseForeignKeys struct { // WsTransactResponse private api response type WsTransactResponse struct { WsDataResponse - ForeignKeys interface{} `json:"foreignKeys"` + ForeignKeys any `json:"foreignKeys"` Attributes WsTransactResponseAttributes `json:"attributes"` Filter WsTransactResponseFilter `json:"filter"` - Data []interface{} `json:"data"` + Data []any `json:"data"` } // WsTransactResponseAttributes private api data @@ -199,7 +199,7 @@ type WsTransactResponseFilter struct { // WsWalletResponse private api response type WsWalletResponse struct { WsDataResponse - ForeignKeys interface{} `json:"foreignKeys"` + ForeignKeys any `json:"foreignKeys"` Attributes WsWalletResponseAttributes `json:"attributes"` Filter WsWalletResponseFilter `json:"filter"` Data []WsWalletResponseData `json:"data"` @@ -213,31 +213,31 @@ type WsWalletResponseAttributes struct { // WsWalletResponseData private api data type WsWalletResponseData struct { - Account int64 `json:"account"` - Currency string `json:"currency"` - PrevDeposited float64 `json:"prevDeposited"` - PrevWithdrawn float64 `json:"prevWithdrawn"` - PrevTransferIn float64 `json:"prevTransferIn"` - PrevTransferOut float64 `json:"prevTransferOut"` - PrevAmount float64 `json:"prevAmount"` - PrevTimestamp string `json:"prevTimestamp"` - DeltaDeposited float64 `json:"deltaDeposited"` - DeltaWithdrawn float64 `json:"deltaWithdrawn"` - DeltaTransferIn float64 `json:"deltaTransferIn"` - DeltaTransferOut float64 `json:"deltaTransferOut"` - DeltaAmount float64 `json:"deltaAmount"` - Deposited float64 `json:"deposited"` - Withdrawn float64 `json:"withdrawn"` - TransferIn float64 `json:"transferIn"` - TransferOut float64 `json:"transferOut"` - Amount float64 `json:"amount"` - PendingCredit float64 `json:"pendingCredit"` - PendingDebit float64 `json:"pendingDebit"` - ConfirmedDebit int64 `json:"confirmedDebit"` - Timestamp string `json:"timestamp"` - Addr string `json:"addr"` - Script string `json:"script"` - WithdrawalLock []interface{} `json:"withdrawalLock"` + Account int64 `json:"account"` + Currency string `json:"currency"` + PrevDeposited float64 `json:"prevDeposited"` + PrevWithdrawn float64 `json:"prevWithdrawn"` + PrevTransferIn float64 `json:"prevTransferIn"` + PrevTransferOut float64 `json:"prevTransferOut"` + PrevAmount float64 `json:"prevAmount"` + PrevTimestamp string `json:"prevTimestamp"` + DeltaDeposited float64 `json:"deltaDeposited"` + DeltaWithdrawn float64 `json:"deltaWithdrawn"` + DeltaTransferIn float64 `json:"deltaTransferIn"` + DeltaTransferOut float64 `json:"deltaTransferOut"` + DeltaAmount float64 `json:"deltaAmount"` + Deposited float64 `json:"deposited"` + Withdrawn float64 `json:"withdrawn"` + TransferIn float64 `json:"transferIn"` + TransferOut float64 `json:"transferOut"` + Amount float64 `json:"amount"` + PendingCredit float64 `json:"pendingCredit"` + PendingDebit float64 `json:"pendingDebit"` + ConfirmedDebit int64 `json:"confirmedDebit"` + Timestamp string `json:"timestamp"` + Addr string `json:"addr"` + Script string `json:"script"` + WithdrawalLock []any `json:"withdrawalLock"` } // WsWalletResponseFilter private api data @@ -336,7 +336,7 @@ type WsDataResponse struct { // WsMarginResponse private api response type WsMarginResponse struct { WsDataResponse - ForeignKeys interface{} `json:"foreignKeys"` + ForeignKeys any `json:"foreignKeys"` Attributes WsMarginResponseAttributes `json:"attributes"` Filter WsMarginResponseFilter `json:"filter"` Data []WsMarginResponseData `json:"data"` @@ -350,47 +350,47 @@ type WsMarginResponseAttributes struct { // WsMarginResponseData private api data type WsMarginResponseData struct { - Account int64 `json:"account"` - Currency string `json:"currency"` - RiskLimit float64 `json:"riskLimit"` - PrevState string `json:"prevState"` - State string `json:"state"` - Action string `json:"action"` - Amount float64 `json:"amount"` - PendingCredit float64 `json:"pendingCredit"` - PendingDebit float64 `json:"pendingDebit"` - ConfirmedDebit float64 `json:"confirmedDebit"` - PrevRealisedPnl float64 `json:"prevRealisedPnl"` - PrevUnrealisedPnl float64 `json:"prevUnrealisedPnl"` - GrossComm float64 `json:"grossComm"` - GrossOpenCost float64 `json:"grossOpenCost"` - GrossOpenPremium float64 `json:"grossOpenPremium"` - GrossExecCost float64 `json:"grossExecCost"` - GrossMarkValue float64 `json:"grossMarkValue"` - RiskValue float64 `json:"riskValue"` - TaxableMargin float64 `json:"taxableMargin"` - InitMargin float64 `json:"initMargin"` - MaintMargin float64 `json:"maintMargin"` - SessionMargin float64 `json:"sessionMargin"` - TargetExcessMargin float64 `json:"targetExcessMargin"` - VarMargin float64 `json:"varMargin"` - RealisedPnl float64 `json:"realisedPnl"` - UnrealisedPnl float64 `json:"unrealisedPnl"` - IndicativeTax float64 `json:"indicativeTax"` - UnrealisedProfit float64 `json:"unrealisedProfit"` - SyntheticMargin interface{} `json:"syntheticMargin"` - WalletBalance float64 `json:"walletBalance"` - MarginBalance float64 `json:"marginBalance"` - MarginBalancePcnt float64 `json:"marginBalancePcnt"` - MarginLeverage float64 `json:"marginLeverage"` - MarginUsedPcnt float64 `json:"marginUsedPcnt"` - ExcessMargin float64 `json:"excessMargin"` - ExcessMarginPcnt float64 `json:"excessMarginPcnt"` - AvailableMargin float64 `json:"availableMargin"` - WithdrawableMargin float64 `json:"withdrawableMargin"` - Timestamp time.Time `json:"timestamp"` - GrossLastValue float64 `json:"grossLastValue"` - Commission interface{} `json:"commission"` + Account int64 `json:"account"` + Currency string `json:"currency"` + RiskLimit float64 `json:"riskLimit"` + PrevState string `json:"prevState"` + State string `json:"state"` + Action string `json:"action"` + Amount float64 `json:"amount"` + PendingCredit float64 `json:"pendingCredit"` + PendingDebit float64 `json:"pendingDebit"` + ConfirmedDebit float64 `json:"confirmedDebit"` + PrevRealisedPnl float64 `json:"prevRealisedPnl"` + PrevUnrealisedPnl float64 `json:"prevUnrealisedPnl"` + GrossComm float64 `json:"grossComm"` + GrossOpenCost float64 `json:"grossOpenCost"` + GrossOpenPremium float64 `json:"grossOpenPremium"` + GrossExecCost float64 `json:"grossExecCost"` + GrossMarkValue float64 `json:"grossMarkValue"` + RiskValue float64 `json:"riskValue"` + TaxableMargin float64 `json:"taxableMargin"` + InitMargin float64 `json:"initMargin"` + MaintMargin float64 `json:"maintMargin"` + SessionMargin float64 `json:"sessionMargin"` + TargetExcessMargin float64 `json:"targetExcessMargin"` + VarMargin float64 `json:"varMargin"` + RealisedPnl float64 `json:"realisedPnl"` + UnrealisedPnl float64 `json:"unrealisedPnl"` + IndicativeTax float64 `json:"indicativeTax"` + UnrealisedProfit float64 `json:"unrealisedProfit"` + SyntheticMargin any `json:"syntheticMargin"` + WalletBalance float64 `json:"walletBalance"` + MarginBalance float64 `json:"marginBalance"` + MarginBalancePcnt float64 `json:"marginBalancePcnt"` + MarginLeverage float64 `json:"marginLeverage"` + MarginUsedPcnt float64 `json:"marginUsedPcnt"` + ExcessMargin float64 `json:"excessMargin"` + ExcessMarginPcnt float64 `json:"excessMarginPcnt"` + AvailableMargin float64 `json:"availableMargin"` + WithdrawableMargin float64 `json:"withdrawableMargin"` + Timestamp time.Time `json:"timestamp"` + GrossLastValue float64 `json:"grossLastValue"` + Commission any `json:"commission"` } // WsMarginResponseFilter private api data @@ -480,7 +480,7 @@ type WsPositionResponseForeignKeys struct { // WsPrivateNotificationsResponse private api response type WsPrivateNotificationsResponse struct { - Table string `json:"table"` - Action string `json:"action"` - Data []interface{} `json:"data"` + Table string `json:"table"` + Action string `json:"action"` + Data []any `json:"data"` } diff --git a/exchanges/bitstamp/bitstamp.go b/exchanges/bitstamp/bitstamp.go index a07832e3..954ed9ab 100644 --- a/exchanges/bitstamp/bitstamp.go +++ b/exchanges/bitstamp/bitstamp.go @@ -277,16 +277,16 @@ func (b *Bitstamp) GetBalance(ctx context.Context) (Balances, error) { // GetUserTransactions returns an array of transactions func (b *Bitstamp) GetUserTransactions(ctx context.Context, currencyPair string) ([]UserTransactions, error) { type Response struct { - Date string `json:"datetime"` - TransactionID int64 `json:"id"` - Type int `json:"type,string"` - USD interface{} `json:"usd"` - EUR interface{} `json:"eur"` - XRP interface{} `json:"xrp"` - BTC interface{} `json:"btc"` - BTCUSD interface{} `json:"btc_usd"` - Fee float64 `json:"fee,string"` - OrderID int64 `json:"order_id"` + Date string `json:"datetime"` + TransactionID int64 `json:"id"` + Type int `json:"type,string"` + USD any `json:"usd"` + EUR any `json:"eur"` + XRP any `json:"xrp"` + BTC any `json:"btc"` + BTCUSD any `json:"btc_usd"` + Fee float64 `json:"fee,string"` + OrderID int64 `json:"order_id"` } var response []Response @@ -306,7 +306,7 @@ func (b *Bitstamp) GetUserTransactions(ctx context.Context, currencyPair string) } } - processNumber := func(i interface{}) float64 { + processNumber := func(i any) float64 { switch t := i.(type) { case float64: return t @@ -554,13 +554,13 @@ func (b *Bitstamp) TransferAccountBalance(ctx context.Context, amount float64, c path = bitstampAPITransferFromMain } - var resp interface{} + var resp any return b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, req, &resp) } // SendHTTPRequest sends an unauthenticated HTTP request -func (b *Bitstamp) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error { +func (b *Bitstamp) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { endpoint, err := b.API.Endpoints.GetURL(ep) if err != nil { return err @@ -579,7 +579,7 @@ func (b *Bitstamp) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st } // SendAuthenticatedHTTPRequest sends an authenticated request -func (b *Bitstamp) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, path string, v2 bool, values url.Values, result interface{}) error { +func (b *Bitstamp) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, path string, v2 bool, values url.Values, result any) error { creds, err := b.GetCredentials(ctx) if err != nil { return err @@ -640,9 +640,9 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange } errCap := struct { - Error string `json:"error"` // v1 errors - Status string `json:"status"` // v2 errors - Reason interface{} `json:"reason"` // v2 errors + Error string `json:"error"` // v1 errors + Status string `json:"status"` // v2 errors + Reason any `json:"reason"` // v2 errors }{} if err := json.Unmarshal(interim, &errCap); err == nil { if errCap.Error != "" || errCap.Status == errStr { @@ -650,7 +650,7 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange return fmt.Errorf("%w %v", request.ErrAuthRequestFailed, errCap.Error) } switch data := errCap.Reason.(type) { // v2 errors - case map[string]interface{}: + case map[string]any: var details strings.Builder for k, v := range data { details.WriteString(fmt.Sprintf("%s: %v", k, v)) diff --git a/exchanges/bitstamp/bitstamp_types.go b/exchanges/bitstamp/bitstamp_types.go index 6590a096..5aad13ba 100644 --- a/exchanges/bitstamp/bitstamp_types.go +++ b/exchanges/bitstamp/bitstamp_types.go @@ -193,10 +193,10 @@ type UnconfirmedBTCTransactions struct { // CaptureError is used to capture unmarshalled errors type CaptureError struct { - Status interface{} `json:"status"` - Reason interface{} `json:"reason"` - Code interface{} `json:"code"` - Error interface{} `json:"error"` + Status any `json:"status"` + Reason any `json:"reason"` + Code any `json:"code"` + Error any `json:"error"` } const ( diff --git a/exchanges/btcmarkets/btcmarkets.go b/exchanges/btcmarkets/btcmarkets.go index ed584581..0856e12c 100644 --- a/exchanges/btcmarkets/btcmarkets.go +++ b/exchanges/btcmarkets/btcmarkets.go @@ -388,7 +388,7 @@ func (b *BTCMarkets) getTimeInForce(s *order.Submit) string { // NewOrder requests a new order and returns an ID func (b *BTCMarkets) NewOrder(ctx context.Context, price, amount, triggerPrice, targetAmount float64, marketID, orderType, side, timeInForce, selfTrade, clientOrderID string, postOnly bool) (OrderData, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["marketId"] = marketID if price != 0 { req["price"] = strconv.FormatFloat(price, 'f', -1, 64) @@ -454,7 +454,7 @@ func (b *BTCMarkets) GetOrders(ctx context.Context, marketID string, before, aft // CancelAllOpenOrdersByPairs cancels all open orders unless pairs are specified func (b *BTCMarkets) CancelAllOpenOrdersByPairs(ctx context.Context, marketIDs []string) ([]CancelOrderResp, error) { var resp []CancelOrderResp - req := make(map[string]interface{}) + req := make(map[string]any) if len(marketIDs) > 0 { var strTemp strings.Builder for x := range marketIDs { @@ -503,7 +503,7 @@ func (b *BTCMarkets) ReplaceOrder(ctx context.Context, id, clientOrderID string, return nil, errIDRequired } - req := make(map[string]interface{}, 3) + req := make(map[string]any, 3) req["price"] = strconv.FormatFloat(price, 'f', -1, 64) req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) if clientOrderID != "" { @@ -704,7 +704,7 @@ func (b *BTCMarkets) GetTransactions(ctx context.Context, assetName string, befo // CreateNewReport creates a new report func (b *BTCMarkets) CreateNewReport(ctx context.Context, reportType, format string) (CreateReportResp, error) { var resp CreateReportResp - req := make(map[string]interface{}) + req := make(map[string]any) req["type"] = reportType req["format"] = format return resp, b.SendAuthenticatedRequest(ctx, http.MethodPost, @@ -729,7 +729,7 @@ func (b *BTCMarkets) RequestWithdraw(ctx context.Context, assetName string, amou toAddress, accountName, accountNumber, bsbNumber, bankName string, ) (TransferData, error) { var resp TransferData - req := make(map[string]interface{}) + req := make(map[string]any) req["assetName"] = assetName req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) if assetName != "AUD" { @@ -762,7 +762,7 @@ func (b *BTCMarkets) BatchPlaceCancelOrders(ctx context.Context, cancelOrders [] return nil, errors.New("BTCMarkets can only handle 4 orders at a time") } - orderRequests := make([]interface{}, numActions) + orderRequests := make([]any, numActions) for x := range cancelOrders { orderRequests[x] = CancelOrderMethod{CancelOrder: cancelOrders[x]} } @@ -806,7 +806,7 @@ func (b *BTCMarkets) CancelBatch(ctx context.Context, ids []string) (BatchCancel } // SendHTTPRequest sends an unauthenticated HTTP request -func (b *BTCMarkets) SendHTTPRequest(ctx context.Context, path string, result interface{}) error { +func (b *BTCMarkets) SendHTTPRequest(ctx context.Context, path string, result any) error { item := &request.Item{ Method: http.MethodGet, Path: path, @@ -821,7 +821,7 @@ func (b *BTCMarkets) SendHTTPRequest(ctx context.Context, path string, result in } // SendAuthenticatedRequest sends an authenticated HTTP request -func (b *BTCMarkets) SendAuthenticatedRequest(ctx context.Context, method, path string, data, result interface{}, f request.EndpointLimit) (err error) { +func (b *BTCMarkets) SendAuthenticatedRequest(ctx context.Context, method, path string, data, result any, f request.EndpointLimit) (err error) { creds, err := b.GetCredentials(ctx) if err != nil { return err @@ -832,7 +832,7 @@ func (b *BTCMarkets) SendAuthenticatedRequest(ctx context.Context, method, path var body io.Reader var payload, hmac []byte switch data.(type) { - case map[string]interface{}, []interface{}: + case map[string]any, []any: payload, err = json.Marshal(data) if err != nil { return nil, err diff --git a/exchanges/btcmarkets/btcmarkets_types.go b/exchanges/btcmarkets/btcmarkets_types.go index f104f6ac..162e0ca3 100644 --- a/exchanges/btcmarkets/btcmarkets_types.go +++ b/exchanges/btcmarkets/btcmarkets_types.go @@ -320,12 +320,12 @@ type PlaceBatch struct { // PlaceOrderMethod stores data for place request type PlaceOrderMethod struct { - PlaceOrder PlaceBatch `json:"placeOrder,omitempty"` + PlaceOrder PlaceBatch `json:"placeOrder"` } // CancelOrderMethod stores data for Cancel request type CancelOrderMethod struct { - CancelOrder CancelBatch `json:"cancelOrder,omitempty"` + CancelOrder CancelBatch `json:"cancelOrder"` } // TradingFeeData stores trading fee data diff --git a/exchanges/btcmarkets/btcmarkets_websocket.go b/exchanges/btcmarkets/btcmarkets_websocket.go index 9a2cafa8..1e7c02fe 100644 --- a/exchanges/btcmarkets/btcmarkets_websocket.go +++ b/exchanges/btcmarkets/btcmarkets_websocket.go @@ -91,7 +91,7 @@ func (b *BTCMarkets) wsReadData() { // UnmarshalJSON implements the unmarshaler interface. func (w *WebsocketOrderbook) UnmarshalJSON(data []byte) error { - resp := make([][3]interface{}, len(data)) + resp := make([][3]any, len(data)) err := json.Unmarshal(data, &resp) if err != nil { return err @@ -452,7 +452,7 @@ func (b *BTCMarkets) ReSubscribeSpecificOrderbook(pair currency.Pair) error { // checksum provides assurance on current in memory liquidity func checksum(ob *orderbook.Base, checksum uint32) error { - check := crc32.ChecksumIEEE([]byte(concat(ob.Bids) + concat(ob.Asks))) + check := crc32.ChecksumIEEE([]byte(concatOrderbookLiquidity(ob.Bids) + concatOrderbookLiquidity(ob.Asks))) if check != checksum { return fmt.Errorf("%s %s %s ID: %v expected: %v but received: %v %w", ob.Exchange, @@ -466,14 +466,10 @@ func checksum(ob *orderbook.Base, checksum uint32) error { return nil } -// concat concatenates price and amounts together for checksum processing -func concat(liquidity orderbook.Tranches) string { - length := 10 - if len(liquidity) < 10 { - length = len(liquidity) - } +// concatOrderbookLiquidity concatenates price and amounts together for checksum processing +func concatOrderbookLiquidity(liquidity orderbook.Tranches) string { var c string - for x := range length { + for x := range min(10, len(liquidity)) { c += trim(liquidity[x].Price) + trim(liquidity[x].Amount) } return c diff --git a/exchanges/btse/btse.go b/exchanges/btse/btse.go index d9e50594..44358392 100644 --- a/exchanges/btse/btse.go +++ b/exchanges/btse/btse.go @@ -225,7 +225,7 @@ func (b *BTSE) GetWalletAddress(ctx context.Context, currency string) (WalletAdd // CreateWalletAddress create new deposit address for requested currency func (b *BTSE) CreateWalletAddress(ctx context.Context, currency string) (WalletAddress, error) { var resp WalletAddress - req := make(map[string]interface{}, 1) + req := make(map[string]any, 1) req["currency"] = currency err := b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, btseWalletAddress, true, nil, req, &resp, queryFunc) if err != nil { @@ -252,7 +252,7 @@ func (b *BTSE) CreateWalletAddress(ctx context.Context, currency string) (Wallet // WalletWithdrawal submit request to withdraw crypto currency func (b *BTSE) WalletWithdrawal(ctx context.Context, currency, address, tag, amount string) (WithdrawalResponse, error) { var resp WithdrawalResponse - req := make(map[string]interface{}, 4) + req := make(map[string]any, 4) req["currency"] = currency req["address"] = address req["tag"] = tag @@ -262,7 +262,7 @@ func (b *BTSE) WalletWithdrawal(ctx context.Context, currency, address, tag, amo // CreateOrder creates an order func (b *BTSE) CreateOrder(ctx context.Context, clOrderID string, deviation float64, postOnly bool, price float64, side string, size, stealth, stopPrice float64, symbol, timeInForce string, trailValue, triggerPrice float64, txType, orderType string) ([]Order, error) { - req := make(map[string]interface{}) + req := make(map[string]any) if clOrderID != "" { req["clOrderID"] = clOrderID } @@ -341,7 +341,7 @@ func (b *BTSE) CancelExistingOrder(ctx context.Context, orderID, symbol, clOrder // CancelAllAfter cancels all orders after timeout func (b *BTSE) CancelAllAfter(ctx context.Context, timeout int) error { - req := make(map[string]interface{}) + req := make(map[string]any) req["timeout"] = timeout return b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, btseCancelAllAfter, true, url.Values{}, req, nil, orderFunc) } @@ -349,7 +349,7 @@ func (b *BTSE) CancelAllAfter(ctx context.Context, timeout int) error { // IndexOrderPeg create peg order that will track a certain percentage above/below the index price func (b *BTSE) IndexOrderPeg(ctx context.Context, clOrderID string, deviation float64, postOnly bool, price float64, side string, size, stealth, stopPrice float64, symbol, timeInForce string, trailValue, triggerPrice float64, txType, orderType string) ([]Order, error) { var o []Order - req := make(map[string]interface{}) + req := make(map[string]any) if clOrderID != "" { req["clOrderID"] = clOrderID } @@ -432,7 +432,7 @@ func (b *BTSE) TradeHistory(ctx context.Context, symbol string, start, end time. } // SendHTTPRequest sends an HTTP request to the desired endpoint -func (b *BTSE) SendHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, result interface{}, spotEndpoint bool, f request.EndpointLimit) error { +func (b *BTSE) SendHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, result any, spotEndpoint bool, f request.EndpointLimit) error { ePoint, err := b.API.Endpoints.GetURL(ep) if err != nil { return err @@ -455,7 +455,7 @@ func (b *BTSE) SendHTTPRequest(ctx context.Context, ep exchange.URL, method, end } // SendAuthenticatedHTTPRequest sends an authenticated HTTP request to the desired endpoint -func (b *BTSE) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, isSpot bool, values url.Values, req map[string]interface{}, result interface{}, f request.EndpointLimit) error { +func (b *BTSE) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, isSpot bool, values url.Values, req map[string]any, result any, f request.EndpointLimit) error { creds, err := b.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/btse/btse_websocket.go b/exchanges/btse/btse_websocket.go index 5c9c01e4..04c244d0 100644 --- a/exchanges/btse/btse_websocket.go +++ b/exchanges/btse/btse_websocket.go @@ -130,7 +130,7 @@ func (b *BTSE) wsReadData() { } func (b *BTSE) wsHandleData(respRaw []byte) error { - type Result map[string]interface{} + type Result map[string]any var result Result err := json.Unmarshal(respRaw, &result) if err != nil { diff --git a/exchanges/bybit/bybit.go b/exchanges/bybit/bybit.go index 5411df22..d28621de 100644 --- a/exchanges/bybit/bybit.go +++ b/exchanges/bybit/bybit.go @@ -2040,7 +2040,7 @@ func (by *Bybit) DeleteSubUID(ctx context.Context, subMemberID string) error { arg := &struct { SubMemberID string `json:"subMemberId"` }{SubMemberID: subMemberID} - var resp interface{} + var resp any return by.SendAuthHTTPRequestV5(ctx, exchange.RestSpot, http.MethodPost, "/v5/user/del-submember", nil, arg, &resp, defaultEPL) } @@ -2545,7 +2545,7 @@ func processOB(ob [][2]string) ([]orderbook.Tranche, error) { } // SendHTTPRequest sends an unauthenticated request -func (by *Bybit) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path string, f request.EndpointLimit, result interface{}) error { +func (by *Bybit) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path string, f request.EndpointLimit, result any) error { endpointPath, err := by.API.Endpoints.GetURL(ePath) if err != nil { return err @@ -2577,7 +2577,7 @@ func (by *Bybit) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path s } // SendAuthHTTPRequestV5 sends an authenticated HTTP request -func (by *Bybit) SendAuthHTTPRequestV5(ctx context.Context, ePath exchange.URL, method, path string, params url.Values, arg, result interface{}, f request.EndpointLimit) error { +func (by *Bybit) SendAuthHTTPRequestV5(ctx context.Context, ePath exchange.URL, method, path string, params url.Values, arg, result any, f request.EndpointLimit) error { val := reflect.ValueOf(result) if val.Kind() != reflect.Ptr { return errNonePointerArgument diff --git a/exchanges/bybit/bybit_convert.go b/exchanges/bybit/bybit_convert.go index cf1ea3d6..45fc1841 100644 --- a/exchanges/bybit/bybit_convert.go +++ b/exchanges/bybit/bybit_convert.go @@ -12,7 +12,7 @@ func (a *orderbookResponse) UnmarshalJSON(data []byte) error { } err := json.Unmarshal(data, child) if err != nil { - var resp []interface{} + var resp []any err = json.Unmarshal(data, &resp) if err != nil { return err diff --git a/exchanges/bybit/bybit_types.go b/exchanges/bybit/bybit_types.go index f06c410e..aba37fd5 100644 --- a/exchanges/bybit/bybit_types.go +++ b/exchanges/bybit/bybit_types.go @@ -27,9 +27,9 @@ type orderbookResponse struct { // Authenticate stores authentication variables required type Authenticate struct { - RequestID string `json:"req_id"` - Args []interface{} `json:"args"` - Operation string `json:"op"` + RequestID string `json:"req_id"` + Args []any `json:"args"` + Operation string `json:"op"` } // SubscriptionArgument represents a subscription arguments. @@ -105,9 +105,9 @@ type InstrumentInfo struct { // RestResponse represents a REST response instance. type RestResponse struct { - RetCode int64 `json:"retCode"` - RetMsg string `json:"retMsg"` - Result interface{} `json:"result"` + RetCode int64 `json:"retCode"` + RetMsg string `json:"retMsg"` + Result any `json:"result"` RetExtInfo struct { List []ErrorMessage `json:"list"` } `json:"retExtInfo"` @@ -344,7 +344,7 @@ type OrderResponse struct { // AmendOrderParams represents a parameter for amending order. type AmendOrderParams struct { Category string `json:"category,omitempty"` - Symbol currency.Pair `json:"symbol,omitempty"` + Symbol currency.Pair `json:"symbol,omitzero"` OrderID string `json:"orderId,omitempty"` OrderLinkID string `json:"orderLinkId,omitempty"` // User customised order ID. A max of 36 characters. Combinations of numbers, letters (upper and lower cases), dashes, and underscores are supported. future orderLinkId rules: OrderImpliedVolatility string `json:"orderIv,omitempty"` @@ -373,7 +373,7 @@ type AmendOrderParams struct { // CancelOrderParams represents a cancel order parameters. type CancelOrderParams struct { Category string `json:"category,omitempty"` - Symbol currency.Pair `json:"symbol,omitempty"` + Symbol currency.Pair `json:"symbol,omitzero"` OrderID string `json:"orderId,omitempty"` OrderLinkID string `json:"orderLinkId,omitempty"` // User customised order ID. A max of 36 characters. Combinations of numbers, letters (upper and lower cases), dashes, and underscores are supported. future orderLinkId rules: @@ -464,7 +464,7 @@ type PlaceBatchOrderParam struct { // BatchOrderItemParam represents a batch order place parameter. type BatchOrderItemParam struct { Category string `json:"category,omitempty"` - Symbol currency.Pair `json:"symbol,omitempty"` + Symbol currency.Pair `json:"symbol,omitzero"` OrderType string `json:"orderType,omitempty"` Side string `json:"side,omitempty"` OrderQuantity float64 `json:"qty,string,omitempty"` @@ -1242,7 +1242,7 @@ type WithdrawableAmount struct { // WithdrawalParam represents asset withdrawal request parameter. type WithdrawalParam struct { - Coin currency.Code `json:"coin,omitempty"` + Coin currency.Code `json:"coin,omitzero"` Chain string `json:"chain,omitempty"` Address string `json:"address,omitempty"` Tag string `json:"tag,omitempty"` diff --git a/exchanges/bybit/bybit_websocket.go b/exchanges/bybit/bybit_websocket.go index fbe781d4..24411de5 100644 --- a/exchanges/bybit/bybit_websocket.go +++ b/exchanges/bybit/bybit_websocket.go @@ -139,7 +139,7 @@ func (by *Bybit) WsAuth(ctx context.Context) error { req := Authenticate{ RequestID: strconv.FormatInt(by.Websocket.AuthConn.GenerateMessageID(false), 10), Operation: "auth", - Args: []interface{}{creds.Key, intNonce, sign}, + Args: []any{creds.Key, intNonce, sign}, } resp, err := by.Websocket.AuthConn.SendMessageReturnResponse(context.TODO(), request.Unset, req.RequestID, req) if err != nil { diff --git a/exchanges/coinbasepro/coinbasepro.go b/exchanges/coinbasepro/coinbasepro.go index 446ba29e..73e6f3f5 100644 --- a/exchanges/coinbasepro/coinbasepro.go +++ b/exchanges/coinbasepro/coinbasepro.go @@ -68,7 +68,7 @@ func (c *CoinbasePro) GetProducts(ctx context.Context) ([]Product, error) { } // GetOrderbook returns orderbook by currency pair and level -func (c *CoinbasePro) GetOrderbook(ctx context.Context, symbol string, level int) (interface{}, error) { +func (c *CoinbasePro) GetOrderbook(ctx context.Context, symbol string, level int) (any, error) { orderbook := OrderbookResponse{} path := fmt.Sprintf("%s/%s/%s", coinbaseproProducts, symbol, coinbaseproOrderbook) @@ -337,7 +337,7 @@ func (c *CoinbasePro) GetHolds(ctx context.Context, accountID string) ([]Account // postOnly - [optional] Post only flag Invalid when time_in_force is IOC or FOK func (c *CoinbasePro) PlaceLimitOrder(ctx context.Context, clientRef string, price, amount float64, side string, timeInforce RequestParamsTimeForceType, cancelAfter, productID, stp string, postOnly bool) (string, error) { resp := GeneralizedOrderResponse{} - req := make(map[string]interface{}) + req := make(map[string]any) req["type"] = order.Limit.Lower() req["price"] = strconv.FormatFloat(price, 'f', -1, 64) req["size"] = strconv.FormatFloat(amount, 'f', -1, 64) @@ -386,7 +386,7 @@ func (c *CoinbasePro) PlaceLimitOrder(ctx context.Context, clientRef string, pri // * One of size or funds is required. func (c *CoinbasePro) PlaceMarketOrder(ctx context.Context, clientRef string, size, funds float64, side, productID, stp string) (string, error) { resp := GeneralizedOrderResponse{} - req := make(map[string]interface{}) + req := make(map[string]any) req["side"] = side req["product_id"] = productID req["type"] = order.Market.Lower() @@ -429,7 +429,7 @@ func (c *CoinbasePro) PlaceMarketOrder(ctx context.Context, clientRef string, si // funds - [optional]* Desired amount of quote currency to use func (c *CoinbasePro) PlaceMarginOrder(ctx context.Context, clientRef string, size, funds float64, side, productID, stp string) (string, error) { resp := GeneralizedOrderResponse{} - req := make(map[string]interface{}) + req := make(map[string]any) req["side"] = side req["product_id"] = productID req["type"] = "margin" @@ -468,7 +468,7 @@ func (c *CoinbasePro) CancelExistingOrder(ctx context.Context, orderID string) e // canceled func (c *CoinbasePro) CancelAllExistingOrders(ctx context.Context, currencyPair string) ([]string, error) { var resp []string - req := make(map[string]interface{}) + req := make(map[string]any) if currencyPair != "" { req["product_id"] = currencyPair @@ -538,7 +538,7 @@ func (c *CoinbasePro) GetFills(ctx context.Context, orderID, currencyPair string // currency - currency to transfer, currently on "BTC" or "USD" func (c *CoinbasePro) MarginTransfer(ctx context.Context, amount float64, transferType, profileID, currency string) (MarginTransfer, error) { resp := MarginTransfer{} - req := make(map[string]interface{}) + req := make(map[string]any) req["type"] = transferType req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) req["currency"] = currency @@ -560,7 +560,7 @@ func (c *CoinbasePro) GetPosition(ctx context.Context) (AccountOverview, error) // repayOnly - allows the position to be repaid func (c *CoinbasePro) ClosePosition(ctx context.Context, repayOnly bool) (AccountOverview, error) { resp := AccountOverview{} - req := make(map[string]interface{}) + req := make(map[string]any) req["repay_only"] = repayOnly return resp, @@ -583,7 +583,7 @@ func (c *CoinbasePro) GetPayMethods(ctx context.Context) ([]PaymentMethod, error // paymentID - ID of the payment method func (c *CoinbasePro) DepositViaPaymentMethod(ctx context.Context, amount float64, currency, paymentID string) (DepositWithdrawalInfo, error) { resp := DepositWithdrawalInfo{} - req := make(map[string]interface{}) + req := make(map[string]any) req["amount"] = amount req["currency"] = currency req["payment_method_id"] = paymentID @@ -602,7 +602,7 @@ func (c *CoinbasePro) DepositViaPaymentMethod(ctx context.Context, amount float6 // accountID - ID of the coinbase account func (c *CoinbasePro) DepositViaCoinbase(ctx context.Context, amount float64, currency, accountID string) (DepositWithdrawalInfo, error) { resp := DepositWithdrawalInfo{} - req := make(map[string]interface{}) + req := make(map[string]any) req["amount"] = amount req["currency"] = currency req["coinbase_account_id"] = accountID @@ -618,7 +618,7 @@ func (c *CoinbasePro) DepositViaCoinbase(ctx context.Context, amount float64, cu // paymentID - ID of the payment method func (c *CoinbasePro) WithdrawViaPaymentMethod(ctx context.Context, amount float64, currency, paymentID string) (DepositWithdrawalInfo, error) { resp := DepositWithdrawalInfo{} - req := make(map[string]interface{}) + req := make(map[string]any) req["amount"] = amount req["currency"] = currency req["payment_method_id"] = paymentID @@ -635,7 +635,7 @@ func (c *CoinbasePro) WithdrawViaPaymentMethod(ctx context.Context, amount float // accountID - ID of the coinbase account // func (c *CoinbasePro) WithdrawViaCoinbase(amount float64, currency, accountID string) (DepositWithdrawalInfo, error) { // resp := DepositWithdrawalInfo{} -// req := make(map[string]interface{}) +// req := make(map[string]any) // req["amount"] = amount // req["currency"] = currency // req["coinbase_account_id"] = accountID @@ -651,7 +651,7 @@ func (c *CoinbasePro) WithdrawViaPaymentMethod(ctx context.Context, amount float // cryptoAddress - A crypto address of the recipient func (c *CoinbasePro) WithdrawCrypto(ctx context.Context, amount float64, currency, cryptoAddress string) (DepositWithdrawalInfo, error) { resp := DepositWithdrawalInfo{} - req := make(map[string]interface{}) + req := make(map[string]any) req["amount"] = amount req["currency"] = currency req["crypto_address"] = cryptoAddress @@ -682,7 +682,7 @@ func (c *CoinbasePro) GetCoinbaseAccounts(ctx context.Context) ([]CoinbaseAccoun // email - [optional] Email address to send the report to func (c *CoinbasePro) GetReport(ctx context.Context, reportType, startDate, endDate, currencyPair, accountID, format, email string) (Report, error) { resp := Report{} - req := make(map[string]interface{}) + req := make(map[string]any) req["type"] = reportType req["start_date"] = startDate req["end_date"] = endDate @@ -731,7 +731,7 @@ func (c *CoinbasePro) GetTransfers(ctx context.Context, profileID, transferType return nil, err } } - req := make(map[string]interface{}) + req := make(map[string]any) if profileID != "" { req["profile_id"] = profileID } @@ -752,7 +752,7 @@ func (c *CoinbasePro) GetTransfers(ctx context.Context, profileID, transferType } // SendHTTPRequest sends an unauthenticated HTTP request -func (c *CoinbasePro) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error { +func (c *CoinbasePro) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { endpoint, err := c.API.Endpoints.GetURL(ep) if err != nil { return err @@ -773,7 +773,7 @@ func (c *CoinbasePro) SendHTTPRequest(ctx context.Context, ep exchange.URL, path } // SendAuthenticatedHTTPRequest sends an authenticated HTTP request -func (c *CoinbasePro) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params map[string]interface{}, result interface{}) (err error) { +func (c *CoinbasePro) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params map[string]any, result any) (err error) { creds, err := c.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/coinbasepro/coinbasepro_types.go b/exchanges/coinbasepro/coinbasepro_types.go index de2a3728..60da085a 100644 --- a/exchanges/coinbasepro/coinbasepro_types.go +++ b/exchanges/coinbasepro/coinbasepro_types.go @@ -95,12 +95,12 @@ type AccountResponse struct { // AccountLedgerResponse holds account history information type AccountLedgerResponse struct { - ID string `json:"id"` - CreatedAt time.Time `json:"created_at"` - Amount float64 `json:"amount,string"` - Balance float64 `json:"balance,string"` - Type string `json:"type"` - Details interface{} `json:"details"` + ID string `json:"id"` + CreatedAt time.Time `json:"created_at"` + Amount float64 `json:"amount,string"` + Balance float64 `json:"balance,string"` + Type string `json:"type"` + Details any `json:"details"` } // AccountHolds contains the hold information about an account @@ -341,9 +341,9 @@ type OrderbookL3 struct { // OrderbookResponse is a generalized response for order books type OrderbookResponse struct { - Sequence int64 `json:"sequence"` - Bids [][3]interface{} `json:"bids"` - Asks [][3]interface{} `json:"asks"` + Sequence int64 `json:"sequence"` + Bids [][3]any `json:"bids"` + Asks [][3]any `json:"asks"` } // FillResponse contains fill information from the exchange @@ -460,31 +460,31 @@ type wsMsgType struct { type wsStatus struct { Currencies []struct { - ConvertibleTo []string `json:"convertible_to"` - Details struct{} `json:"details"` - ID string `json:"id"` - MaxPrecision float64 `json:"max_precision,string"` - MinSize float64 `json:"min_size,string"` - Name string `json:"name"` - Status string `json:"status"` - StatusMessage interface{} `json:"status_message"` + ConvertibleTo []string `json:"convertible_to"` + Details struct{} `json:"details"` + ID string `json:"id"` + MaxPrecision float64 `json:"max_precision,string"` + MinSize float64 `json:"min_size,string"` + Name string `json:"name"` + Status string `json:"status"` + StatusMessage any `json:"status_message"` } `json:"currencies"` Products []struct { - BaseCurrency string `json:"base_currency"` - BaseIncrement float64 `json:"base_increment,string"` - BaseMaxSize float64 `json:"base_max_size,string"` - BaseMinSize float64 `json:"base_min_size,string"` - CancelOnly bool `json:"cancel_only"` - DisplayName string `json:"display_name"` - ID string `json:"id"` - LimitOnly bool `json:"limit_only"` - MaxMarketFunds float64 `json:"max_market_funds,string"` - MinMarketFunds float64 `json:"min_market_funds,string"` - PostOnly bool `json:"post_only"` - QuoteCurrency string `json:"quote_currency"` - QuoteIncrement float64 `json:"quote_increment,string"` - Status string `json:"status"` - StatusMessage interface{} `json:"status_message"` + BaseCurrency string `json:"base_currency"` + BaseIncrement float64 `json:"base_increment,string"` + BaseMaxSize float64 `json:"base_max_size,string"` + BaseMinSize float64 `json:"base_min_size,string"` + CancelOnly bool `json:"cancel_only"` + DisplayName string `json:"display_name"` + ID string `json:"id"` + LimitOnly bool `json:"limit_only"` + MaxMarketFunds float64 `json:"max_market_funds,string"` + MinMarketFunds float64 `json:"min_market_funds,string"` + PostOnly bool `json:"post_only"` + QuoteCurrency string `json:"quote_currency"` + QuoteIncrement float64 `json:"quote_increment,string"` + Status string `json:"status"` + StatusMessage any `json:"status_message"` } `json:"products"` Type string `json:"type"` } diff --git a/exchanges/coinut/coinut.go b/exchanges/coinut/coinut.go index fce637fa..fde02bf0 100644 --- a/exchanges/coinut/coinut.go +++ b/exchanges/coinut/coinut.go @@ -69,7 +69,7 @@ func (c *COINUT) SeedInstruments(ctx context.Context) error { // GetInstruments returns instruments func (c *COINUT) GetInstruments(ctx context.Context) (Instruments, error) { var result Instruments - params := make(map[string]interface{}) + params := make(map[string]any) params["sec_type"] = strings.ToUpper(asset.Spot.String()) return result, c.SendHTTPRequest(ctx, exchange.RestSpot, coinutInstruments, params, false, &result) } @@ -77,7 +77,7 @@ func (c *COINUT) GetInstruments(ctx context.Context) (Instruments, error) { // GetInstrumentTicker returns a ticker for a specific instrument func (c *COINUT) GetInstrumentTicker(ctx context.Context, instrumentID int64) (Ticker, error) { var result Ticker - params := make(map[string]interface{}) + params := make(map[string]any) params["inst_id"] = instrumentID return result, c.SendHTTPRequest(ctx, exchange.RestSpot, coinutTicker, params, false, &result) } @@ -85,7 +85,7 @@ func (c *COINUT) GetInstrumentTicker(ctx context.Context, instrumentID int64) (T // GetInstrumentOrderbook returns the orderbooks for a specific instrument func (c *COINUT) GetInstrumentOrderbook(ctx context.Context, instrumentID, limit int64) (*Orderbook, error) { var result Orderbook - params := make(map[string]interface{}) + params := make(map[string]any) params["inst_id"] = instrumentID if limit > 0 { params["top_n"] = limit @@ -97,7 +97,7 @@ func (c *COINUT) GetInstrumentOrderbook(ctx context.Context, instrumentID, limit // GetTrades returns trade information func (c *COINUT) GetTrades(ctx context.Context, instrumentID int64) (Trades, error) { var result Trades - params := make(map[string]interface{}) + params := make(map[string]any) params["inst_id"] = instrumentID return result, c.SendHTTPRequest(ctx, exchange.RestSpot, coinutTrades, params, false, &result) @@ -110,9 +110,9 @@ func (c *COINUT) GetUserBalance(ctx context.Context) (*UserBalance, error) { } // NewOrder places a new order on the exchange -func (c *COINUT) NewOrder(ctx context.Context, instrumentID int64, quantity, price float64, buy bool, orderID uint32) (interface{}, error) { - var result interface{} - params := make(map[string]interface{}) +func (c *COINUT) NewOrder(ctx context.Context, instrumentID int64, quantity, price float64, buy bool, orderID uint32) (any, error) { + var result any + params := make(map[string]any) params["inst_id"] = instrumentID if price > 0 { params["price"] = strconv.FormatFloat(price, 'f', -1, 64) @@ -130,7 +130,7 @@ func (c *COINUT) NewOrder(ctx context.Context, instrumentID int64, quantity, pri // NewOrders places multiple orders on the exchange func (c *COINUT) NewOrders(ctx context.Context, orders []Order) ([]OrdersBase, error) { var result OrdersResponse - params := make(map[string]interface{}) + params := make(map[string]any) params["orders"] = orders return result.Data, c.SendHTTPRequest(ctx, exchange.RestSpot, coinutOrders, params, true, &result.Data) @@ -139,7 +139,7 @@ func (c *COINUT) NewOrders(ctx context.Context, orders []Order) ([]OrdersBase, e // GetOpenOrders returns a list of open order and relevant information func (c *COINUT) GetOpenOrders(ctx context.Context, instrumentID int64) (GetOpenOrdersResponse, error) { var result GetOpenOrdersResponse - params := make(map[string]interface{}) + params := make(map[string]any) params["inst_id"] = instrumentID return result, c.SendHTTPRequest(ctx, exchange.RestSpot, coinutOrdersOpen, params, true, &result) } @@ -147,7 +147,7 @@ func (c *COINUT) GetOpenOrders(ctx context.Context, instrumentID int64) (GetOpen // CancelExistingOrder cancels a specific order and returns if it was actioned func (c *COINUT) CancelExistingOrder(ctx context.Context, instrumentID, orderID int64) (bool, error) { var result GenericResponse - params := make(map[string]interface{}) + params := make(map[string]any) type Request struct { InstrumentID int64 `json:"inst_id"` OrderID int64 `json:"order_id"` @@ -171,7 +171,7 @@ func (c *COINUT) CancelExistingOrder(ctx context.Context, instrumentID, orderID // CancelOrders cancels multiple orders func (c *COINUT) CancelOrders(ctx context.Context, orders []CancelOrders) (CancelOrdersResponse, error) { var result CancelOrdersResponse - params := make(map[string]interface{}) + params := make(map[string]any) var entries []CancelOrders entries = append(entries, orders...) params["entries"] = entries @@ -182,7 +182,7 @@ func (c *COINUT) CancelOrders(ctx context.Context, orders []CancelOrders) (Cance // GetTradeHistory returns trade history for a specific instrument. func (c *COINUT) GetTradeHistory(ctx context.Context, instrumentID, start, limit int64) (TradeHistory, error) { var result TradeHistory - params := make(map[string]interface{}) + params := make(map[string]any) params["inst_id"] = instrumentID if start >= 0 && start <= 100 { params["start"] = start @@ -197,16 +197,16 @@ func (c *COINUT) GetTradeHistory(ctx context.Context, instrumentID, start, limit // GetIndexTicker returns the index ticker for an asset func (c *COINUT) GetIndexTicker(ctx context.Context, asset string) (IndexTicker, error) { var result IndexTicker - params := make(map[string]interface{}) + params := make(map[string]any) params["asset"] = asset return result, c.SendHTTPRequest(ctx, exchange.RestSpot, coinutIndexTicker, params, false, &result) } // GetDerivativeInstruments returns a list of derivative instruments -func (c *COINUT) GetDerivativeInstruments(ctx context.Context, secType string) (interface{}, error) { - var result interface{} // to-do - params := make(map[string]interface{}) +func (c *COINUT) GetDerivativeInstruments(ctx context.Context, secType string) (any, error) { + var result any // TODO: Make this a concrete type + params := make(map[string]any) params["sec_type"] = secType return result, c.SendHTTPRequest(ctx, exchange.RestSpot, coinutInstruments, params, false, &result) @@ -215,7 +215,7 @@ func (c *COINUT) GetDerivativeInstruments(ctx context.Context, secType string) ( // GetOptionChain returns option chain func (c *COINUT) GetOptionChain(ctx context.Context, asset, secType string) (OptionChainResponse, error) { var result OptionChainResponse - params := make(map[string]interface{}) + params := make(map[string]any) params["asset"] = asset params["sec_type"] = secType @@ -225,7 +225,7 @@ func (c *COINUT) GetOptionChain(ctx context.Context, asset, secType string) (Opt // GetPositionHistory returns position history func (c *COINUT) GetPositionHistory(ctx context.Context, secType string, start, limit int) (PositionHistory, error) { var result PositionHistory - params := make(map[string]interface{}) + params := make(map[string]any) params["sec_type"] = secType if start >= 0 { params["start"] = start @@ -243,24 +243,22 @@ func (c *COINUT) GetOpenPositionsForInstrument(ctx context.Context, instrumentID Positions []OpenPosition `json:"positions"` } var result Response - params := make(map[string]interface{}) + params := make(map[string]any) params["inst_id"] = instrumentID return result.Positions, c.SendHTTPRequest(ctx, exchange.RestSpot, coinutPositionOpen, params, true, &result) } -// to-do: user position update via websocket - // SendHTTPRequest sends either an authenticated or unauthenticated HTTP request -func (c *COINUT) SendHTTPRequest(ctx context.Context, ep exchange.URL, apiRequest string, params map[string]interface{}, authenticated bool, result interface{}) (err error) { +func (c *COINUT) SendHTTPRequest(ctx context.Context, ep exchange.URL, apiRequest string, params map[string]any, authenticated bool, result any) (err error) { endpoint, err := c.API.Endpoints.GetURL(ep) if err != nil { return err } if params == nil { - params = map[string]interface{}{} + params = make(map[string]any) } requestType := request.AuthType(request.UnauthenticatedRequest) @@ -380,50 +378,27 @@ func (c *COINUT) calculateTradingFee(base, quote currency.Code, purchasePrice, a } func getInternationalBankWithdrawalFee(c currency.Code, amount float64) float64 { - var fee float64 - - switch c { + switch c.Upper() { case currency.USD: - if amount*0.001 < 10 { - fee = 10 - } else { - fee = amount * 0.001 - } + return max(amount*0.001, 10.0) case currency.CAD: - if amount*0.005 < 10 { - fee = 2 - } else { - fee = amount * 0.005 - } + return max(amount*0.005, 2.0) case currency.SGD: - if amount*0.001 < 10 { - fee = 10 - } else { - fee = amount * 0.001 - } + return 2.0 + default: + return 0 // Handle unknown currencies } - - return fee } func getInternationalBankDepositFee(c currency.Code, amount float64) float64 { - var fee float64 - - if c.Equal(currency.USD) { - if amount*0.001 < 10 { - fee = 10 - } else { - fee = amount * 0.001 - } - } else if c.Equal(currency.CAD) { - if amount*0.005 < 10 { - fee = 2 - } else { - fee = amount * 0.005 - } + switch c.Upper() { + case currency.USD: + return max(amount*0.001, 10.0) + case currency.CAD: + return max(amount*0.005, 2.0) + default: + return 0 } - - return fee } // IsLoaded returns whether or not the instrument map has been seeded diff --git a/exchanges/coinut/coinut_test.go b/exchanges/coinut/coinut_test.go index 90ab801f..a1e58c0e 100644 --- a/exchanges/coinut/coinut_test.go +++ b/exchanges/coinut/coinut_test.go @@ -608,34 +608,17 @@ func TestCurrencyMapInstrumentIDs(t *testing.T) { t.Parallel() var i instrumentMap - if r := i.GetInstrumentIDs(); len(r) > 0 { - t.Error("non initialised instrument map shouldn't return any ids") - } + assert.Empty(t, i.GetInstrumentIDs()) // Seed the instrument map i.Seed("BTCUSD", 1234) i.Seed("LTCUSD", 1337) - f := func(ids []int64, target int64) bool { - for x := range ids { - if ids[x] == target { - return true - } - } - return false - } - // Test 2 valid instruments and one invalid ids := i.GetInstrumentIDs() - if r := f(ids, 1234); !r { - t.Error("unexpected result") - } - if r := f(ids, 1337); !r { - t.Error("unexpected result") - } - if r := f(ids, 4321); r { - t.Error("unexpected result") - } + assert.Contains(t, ids, int64(1234)) + assert.Contains(t, ids, int64(1337)) + assert.NotContains(t, ids, int64(4321)) } func TestGetNonce(t *testing.T) { diff --git a/exchanges/coinut/coinut_types.go b/exchanges/coinut/coinut_types.go index 9709a139..5e313923 100644 --- a/exchanges/coinut/coinut_types.go +++ b/exchanges/coinut/coinut_types.go @@ -312,7 +312,7 @@ type WsOrderbookSnapshot struct { TotalBuy float64 `json:"total_buy,string"` TotalSell float64 `json:"total_sell,string"` Reply string `json:"reply"` - Status []interface{} `json:"status"` + Status []any `json:"status"` } // WsOrderbookData defines singular orderbook data @@ -341,7 +341,7 @@ type WsTradeSnapshot struct { InstrumentID int64 `json:"inst_id"` Nonce int64 `json:"nonce"` Reply string `json:"reply"` - Status []interface{} `json:"status"` + Status []any `json:"status"` Trades []WsTradeData `json:"trades"` } @@ -371,7 +371,7 @@ type WsInstrumentList struct { Spot map[string][]InstrumentBase `json:"SPOT"` Nonce int64 `json:"nonce,omitempty"` Reply string `json:"inst_list,omitempty"` - Status []interface{} `json:"status,omitempty"` + Status []any `json:"status,omitempty"` } // WsSupportedCurrency defines supported currency on the exchange diff --git a/exchanges/coinut/coinut_websocket.go b/exchanges/coinut/coinut_websocket.go index fdc67605..22de4c79 100644 --- a/exchanges/coinut/coinut_websocket.go +++ b/exchanges/coinut/coinut_websocket.go @@ -652,7 +652,7 @@ func (c *COINUT) Unsubscribe(channelToUnsubscribe subscription.List) error { errs = common.AppendError(errs, err) continue } - var response map[string]interface{} + var response map[string]any err = json.Unmarshal(resp, &response) if err == nil { val, ok := response["status"].([]any) diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go index 8ed8ecc4..b20dbbd5 100644 --- a/exchanges/coinut/coinut_wrapper.go +++ b/exchanges/coinut/coinut_wrapper.go @@ -505,7 +505,7 @@ func (c *COINUT) SubmitOrder(ctx context.Context, o *order.Submit) (*order.Submi return nil, errLookupInstrumentID } - var APIResponse interface{} + var APIResponse any var clientIDInt uint64 clientIDInt, err = strconv.ParseUint(o.ClientID, 10, 32) if err != nil { @@ -520,7 +520,7 @@ func (c *COINUT) SubmitOrder(ctx context.Context, o *order.Submit) (*order.Submi if err != nil { return nil, err } - responseMap, ok := APIResponse.(map[string]interface{}) + responseMap, ok := APIResponse.(map[string]any) if !ok { return nil, errors.New("unable to type assert responseMap") } diff --git a/exchanges/deribit/deribit.go b/exchanges/deribit/deribit.go index 0504d0eb..fb5734bd 100644 --- a/exchanges/deribit/deribit.go +++ b/exchanges/deribit/deribit.go @@ -291,7 +291,7 @@ func (d *Deribit) GetHistoricalVolatility(ctx context.Context, ccy currency.Code } params := url.Values{} params.Set("currency", ccy.String()) - var data [][2]interface{} + var data [][2]any err := d.SendHTTPRequest(ctx, exchange.RestFutures, nonMatchingEPL, common.EncodeURLValues(getHistoricalVolatility, params), &data) if err != nil { @@ -719,15 +719,15 @@ func (d *Deribit) GetPublicTicker(ctx context.Context, instrument string) (*Tick } // SendHTTPRequest sends an unauthenticated HTTP request -func (d *Deribit) SendHTTPRequest(ctx context.Context, ep exchange.URL, epl request.EndpointLimit, path string, result interface{}) error { +func (d *Deribit) SendHTTPRequest(ctx context.Context, ep exchange.URL, epl request.EndpointLimit, path string, result any) error { endpoint, err := d.API.Endpoints.GetURL(ep) if err != nil { return err } data := &struct { - JSONRPC string `json:"jsonrpc"` - ID int64 `json:"id"` - Data interface{} `json:"result"` + JSONRPC string `json:"jsonrpc"` + ID int64 `json:"id"` + Data any `json:"result"` }{ Data: result, } @@ -1328,7 +1328,7 @@ func (d *Deribit) RemoveAPIKey(ctx context.Context, id int64) error { } params := url.Values{} params.Set("id", strconv.FormatInt(id, 10)) - var resp interface{} + var resp any err := d.SendHTTPAuthRequest(ctx, exchange.RestFutures, nonMatchingEPL, http.MethodGet, removeAPIKey, params, &resp) if err != nil { return err @@ -1396,7 +1396,7 @@ func (d *Deribit) SetEmailForSubAccount(ctx context.Context, sid int64, email st params := url.Values{} params.Set("sid", strconv.FormatInt(sid, 10)) params.Set("email", email) - var resp interface{} + var resp any err := d.SendHTTPAuthRequest(ctx, exchange.RestFutures, nonMatchingEPL, http.MethodGet, setEmailForSubAccount, params, &resp) if err != nil { @@ -2264,7 +2264,7 @@ func (d *Deribit) GetSettlementHistoryByCurency(ctx context.Context, ccy currenc } // SendHTTPAuthRequest sends an authenticated request to deribit api -func (d *Deribit) SendHTTPAuthRequest(ctx context.Context, ep exchange.URL, epl request.EndpointLimit, method, path string, params url.Values, result interface{}) error { +func (d *Deribit) SendHTTPAuthRequest(ctx context.Context, ep exchange.URL, epl request.EndpointLimit, method, path string, params url.Values, result any) error { endpoint, err := d.API.Endpoints.GetURL(ep) if err != nil { return err diff --git a/exchanges/deribit/deribit_types.go b/exchanges/deribit/deribit_types.go index 3d553278..bc89e8a1 100644 --- a/exchanges/deribit/deribit_types.go +++ b/exchanges/deribit/deribit_types.go @@ -44,7 +44,6 @@ var ( errWebsocketConnectionNotAuthenticated = errors.New("websocket connection is not authenticated") errResolutionNotSet = errors.New("resolution not set") errInvalidDestinationID = errors.New("invalid destination id") - errUnsupportedChannel = errors.New("channels not supported") errUnacceptableAPIKey = errors.New("unacceptable api key name") errInvalidUsername = errors.New("new username has to be specified") errSubAccountNameChangeFailed = errors.New("subaccount name change failed") @@ -845,19 +844,19 @@ type TransactionsData struct { // wsInput defines a request obj for the JSON-RPC login and gets a websocket // response type wsInput struct { - JSONRPCVersion string `json:"jsonrpc,omitempty"` - ID int64 `json:"id,omitempty"` - Method string `json:"method"` - Params map[string]interface{} `json:"params,omitempty"` + JSONRPCVersion string `json:"jsonrpc,omitempty"` + ID int64 `json:"id,omitempty"` + Method string `json:"method"` + Params map[string]any `json:"params,omitempty"` } // WsRequest defines a request obj for the JSON-RPC endpoints and gets a websocket // response type WsRequest struct { - JSONRPCVersion string `json:"jsonrpc,omitempty"` - ID int64 `json:"id,omitempty"` - Method string `json:"method"` - Params interface{} `json:"params,omitempty"` + JSONRPCVersion string `json:"jsonrpc,omitempty"` + ID int64 `json:"id,omitempty"` + Method string `json:"method"` + Params any `json:"params,omitempty"` } // WsSubscriptionInput defines a request obj for the JSON-RPC and gets a websocket @@ -870,22 +869,22 @@ type WsSubscriptionInput struct { } type wsResponse struct { - JSONRPCVersion string `json:"jsonrpc,omitempty"` - ID int64 `json:"id,omitempty"` - Result interface{} `json:"result,omitempty"` + JSONRPCVersion string `json:"jsonrpc,omitempty"` + ID int64 `json:"id,omitempty"` + Result any `json:"result,omitempty"` Error struct { - Message string `json:"message,omitempty"` - Code int64 `json:"code,omitempty"` - Data interface{} `json:"data"` - } `json:"error,omitempty"` + Message string `json:"message,omitempty"` + Code int64 `json:"code,omitempty"` + Data any `json:"data"` + } `json:"error"` } type wsLoginResponse struct { - JSONRPCVersion string `json:"jsonrpc"` - ID int64 `json:"id"` - Method string `json:"method"` - Result map[string]interface{} `json:"result"` - Error *UnmarshalError `json:"error"` + JSONRPCVersion string `json:"jsonrpc"` + ID int64 `json:"id"` + Method string `json:"method"` + Result map[string]any `json:"result"` + Error *UnmarshalError `json:"error"` } type wsSubscriptionResponse struct { @@ -934,25 +933,25 @@ type BlockTradeParam struct { // BlockTradeData represents a user's block trade data. type BlockTradeData struct { - TradeSeq int64 `json:"trade_seq"` - TradeID string `json:"trade_id"` - Timestamp types.Time `json:"timestamp"` - TickDirection int64 `json:"tick_direction"` - State string `json:"state"` - SelfTrade bool `json:"self_trade"` - Price float64 `json:"price"` - OrderType string `json:"order_type"` - OrderID string `json:"order_id"` - MatchingID interface{} `json:"matching_id"` - Liquidity string `json:"liquidity"` - OptionmpliedVolatility float64 `json:"iv,omitempty"` - InstrumentName string `json:"instrument_name"` - IndexPrice float64 `json:"index_price"` - FeeCurrency string `json:"fee_currency"` - Fee float64 `json:"fee"` - Direction string `json:"direction"` - BlockTradeID string `json:"block_trade_id"` - Amount float64 `json:"amount"` + TradeSeq int64 `json:"trade_seq"` + TradeID string `json:"trade_id"` + Timestamp types.Time `json:"timestamp"` + TickDirection int64 `json:"tick_direction"` + State string `json:"state"` + SelfTrade bool `json:"self_trade"` + Price float64 `json:"price"` + OrderType string `json:"order_type"` + OrderID string `json:"order_id"` + MatchingID any `json:"matching_id"` + Liquidity string `json:"liquidity"` + OptionmpliedVolatility float64 `json:"iv,omitempty"` + InstrumentName string `json:"instrument_name"` + IndexPrice float64 `json:"index_price"` + FeeCurrency string `json:"fee_currency"` + Fee float64 `json:"fee"` + Direction string `json:"direction"` + BlockTradeID string `json:"block_trade_id"` + Amount float64 `json:"amount"` } // Announcement represents public announcements. @@ -987,9 +986,9 @@ type PortfolioMargin struct { Pls []float64 `json:"pls"` PcoOpt float64 `json:"pco_opt"` PcoFtu float64 `json:"pco_ftu"` - OptSummary []interface{} `json:"opt_summary"` + OptSummary []any `json:"opt_summary"` OptPls []float64 `json:"opt_pls"` - OptEntries []interface{} `json:"opt_entries"` + OptEntries []any `json:"opt_entries"` MarginPos float64 `json:"margin_pos"` Margin float64 `json:"margin"` FtuSummary []struct { @@ -1114,8 +1113,8 @@ type BlockTradeMoveResponse struct { type WsResponse struct { ID int64 `json:"id,omitempty"` Params struct { - Data interface{} `json:"data"` - Channel string `json:"channel"` + Data any `json:"data"` + Channel string `json:"channel"` // Used in heartbead and test_request messages. Type string `json:"type"` @@ -1124,7 +1123,7 @@ type WsResponse struct { JSONRPCVersion string `json:"jsonrpc"` // for status "ok" and "version" push data messages - Result interface{} `json:"result"` + Result any `json:"result"` } // VersionInformation represents websocket version information @@ -1134,12 +1133,12 @@ type VersionInformation struct { // wsOrderbook represents orderbook push data for a book websocket subscription. type wsOrderbook struct { - Type string `json:"type"` - Timestamp types.Time `json:"timestamp"` - InstrumentName string `json:"instrument_name"` - ChangeID int64 `json:"change_id"` - Bids [][]interface{} `json:"bids"` - Asks [][]interface{} `json:"asks"` + Type string `json:"type"` + Timestamp types.Time `json:"timestamp"` + InstrumentName string `json:"instrument_name"` + ChangeID int64 `json:"change_id"` + Bids [][]any `json:"bids"` + Asks [][]any `json:"asks"` } // wsCandlestickData represents publicly available market data used to generate a TradingView candle chart. @@ -1310,11 +1309,11 @@ type wsQuoteTickerInformation struct { // wsRequestForQuote represents a notifications about RFQs for instruments in given currency. type wsRequestForQuote struct { - State bool `json:"state"` - Side interface{} `json:"side"` - LastRFQTimestamp types.Time `json:"last_rfq_tstamp"` - InstrumentName string `json:"instrument_name"` - Amount interface{} `json:"amount"` + State bool `json:"state"` + Side any `json:"side"` + LastRFQTimestamp types.Time `json:"last_rfq_tstamp"` + InstrumentName string `json:"instrument_name"` + Amount any `json:"amount"` } // wsTrade represents trades for an instrument. @@ -1344,27 +1343,27 @@ type wsAccessLog struct { // wsChanges represents user's updates related to order, trades, etc. in an instrument. type wsChanges struct { Trades []struct { - TradeSeq float64 `json:"trade_seq"` - TradeID string `json:"trade_id"` - Timestamp types.Time `json:"timestamp"` - TickDirection float64 `json:"tick_direction"` - State string `json:"state"` - SelfTrade bool `json:"self_trade"` - ReduceOnly bool `json:"reduce_only"` - ProfitLoss float64 `json:"profit_loss"` - Price float64 `json:"price"` - PostOnly bool `json:"post_only"` - OrderType string `json:"order_type"` - OrderID string `json:"order_id"` - MatchingID interface{} `json:"matching_id"` - MarkPrice float64 `json:"mark_price"` - Liquidity string `json:"liquidity"` - InstrumentName string `json:"instrument_name"` - IndexPrice float64 `json:"index_price"` - FeeCurrency string `json:"fee_currency"` - Fee float64 `json:"fee"` - Direction string `json:"direction"` - Amount float64 `json:"amount"` + TradeSeq float64 `json:"trade_seq"` + TradeID string `json:"trade_id"` + Timestamp types.Time `json:"timestamp"` + TickDirection float64 `json:"tick_direction"` + State string `json:"state"` + SelfTrade bool `json:"self_trade"` + ReduceOnly bool `json:"reduce_only"` + ProfitLoss float64 `json:"profit_loss"` + Price float64 `json:"price"` + PostOnly bool `json:"post_only"` + OrderType string `json:"order_type"` + OrderID string `json:"order_id"` + MatchingID any `json:"matching_id"` + MarkPrice float64 `json:"mark_price"` + Liquidity string `json:"liquidity"` + InstrumentName string `json:"instrument_name"` + IndexPrice float64 `json:"index_price"` + FeeCurrency string `json:"fee_currency"` + Fee float64 `json:"fee"` + Direction string `json:"direction"` + Amount float64 `json:"amount"` } `json:"trades"` Positions []WebsocketPosition `json:"positions"` Orders []struct { diff --git a/exchanges/deribit/deribit_websocket.go b/exchanges/deribit/deribit_websocket.go index d1215c1b..63e960d1 100644 --- a/exchanges/deribit/deribit_websocket.go +++ b/exchanges/deribit/deribit_websocket.go @@ -105,8 +105,6 @@ var defaultSubscriptions = subscription.List{ } var ( - indexENUMS = []string{"ada_usd", "algo_usd", "avax_usd", "bch_usd", "bnb_usd", "btc_usd", "doge_usd", "dot_usd", "eth_usd", "link_usd", "ltc_usd", "luna_usd", "matic_usd", "near_usd", "shib_usd", "sol_usd", "trx_usd", "uni_usd", "usdc_usd", "xrp_usd", "ada_usdc", "bch_usdc", "algo_usdc", "avax_usdc", "btc_usdc", "doge_usdc", "dot_usdc", "bch_usdc", "bnb_usdc", "eth_usdc", "link_usdc", "ltc_usdc", "luna_usdc", "matic_usdc", "near_usdc", "shib_usdc", "sol_usdc", "trx_usdc", "uni_usdc", "xrp_usdc", "btcdvol_usdc", "ethdvol_usdc"} - pingMessage = WsSubscriptionInput{ ID: 2, JSONRPCVersion: rpcVersion, @@ -117,7 +115,7 @@ var ( ID: 1, JSONRPCVersion: rpcVersion, Method: "public/set_heartbeat", - Params: map[string]interface{}{ + Params: map[string]any{ "interval": 15, }, } @@ -168,7 +166,7 @@ func (d *Deribit) wsLogin(ctx context.Context) error { JSONRPCVersion: rpcVersion, Method: "public/auth", ID: d.Websocket.Conn.GenerateMessageID(false), - Params: map[string]interface{}{ + Params: map[string]any{ "grant_type": "client_signature", "client_id": creds.Key, "timestamp": strTS, @@ -592,7 +590,7 @@ func (d *Deribit) processTicker(respRaw []byte, channels []string) error { return nil } -func (d *Deribit) processData(respRaw []byte, result interface{}) error { +func (d *Deribit) processData(respRaw []byte, result any) error { var response WsResponse response.Params.Data = result err := json.Unmarshal(respRaw, &response) diff --git a/exchanges/deribit/deribit_ws_endpoints.go b/exchanges/deribit/deribit_ws_endpoints.go index b28999d5..09c56c79 100644 --- a/exchanges/deribit/deribit_ws_endpoints.go +++ b/exchanges/deribit/deribit_ws_endpoints.go @@ -160,7 +160,7 @@ func (d *Deribit) WSRetrieveHistoricalVolatility(ccy currency.Code) ([]Historica }{ Currency: ccy, } - var data [][2]interface{} + var data [][2]any err := d.SendWSRequest(nonMatchingEPL, getHistoricalVolatility, input, &data, false) if err != nil { return nil, err @@ -1889,7 +1889,7 @@ func (d *Deribit) WSSetMMPConfig(ccy currency.Code, interval kline.Interval, fro if ccy.IsEmpty() { return currency.ErrCurrencyCodeEmpty } - params := make(map[string]interface{}) + params := make(map[string]any) params["currency"] = ccy intervalString, err := d.GetResolutionFromInterval(interval) if err != nil { @@ -2015,7 +2015,7 @@ func (d *Deribit) WSCreateCombo(args []ComboParam) (*ComboDetail, error) { } } var resp *ComboDetail - return resp, d.SendWSRequest(nonMatchingEPL, createCombos, map[string]interface{}{"trades": args}, &resp, true) + return resp, d.SendWSRequest(nonMatchingEPL, createCombos, map[string]any{"trades": args}, &resp, true) } // WsLogout gracefully close websocket connection, when COD (Cancel On Disconnect) is enabled orders are not cancelled @@ -2355,7 +2355,7 @@ func (d *Deribit) WsSimulateBlockTrade(role string, trades []BlockTradeParam) (b // SendWSRequest sends a request through the websocket connection. // both authenticated and public endpoints are allowed. -func (d *Deribit) SendWSRequest(epl request.EndpointLimit, method string, params, response interface{}, authenticated bool) error { +func (d *Deribit) SendWSRequest(epl request.EndpointLimit, method string, params, response any, authenticated bool) error { if authenticated && !d.Websocket.CanUseAuthenticatedEndpoints() { return errWebsocketConnectionNotAuthenticated } @@ -2418,10 +2418,8 @@ func (d *Deribit) sendWsPayload(ep request.EndpointLimit, input *WsRequest, resp case 10040: after := 100 * time.Millisecond // because all the request rate will be reset after 1 sec interval backoff := request.DefaultBackoff()(attempt) - delay := backoff - if after > backoff { - delay = after - } + delay := max(after, backoff) + if dl, ok := ctx.Deadline(); ok && dl.Before(time.Now().Add(delay)) { return errors.New("deadline would be exceeded by retry") } diff --git a/exchanges/exchange.go b/exchanges/exchange.go index 5fbb1f3a..7d46edaa 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "maps" "net" "net/url" "sort" @@ -1292,12 +1293,8 @@ func (e *Endpoints) GetURL(key URL) (string, error) { // GetURLMap gets all urls for either running or default map based on the bool value supplied func (e *Endpoints) GetURLMap() map[string]string { e.mu.RLock() - urlMap := make(map[string]string) - for k, v := range e.defaults { - urlMap[k] = v - } - e.mu.RUnlock() - return urlMap + defer e.mu.RUnlock() + return maps.Clone(e.defaults) } // GetCachedOpenInterest returns open interest data if the exchange diff --git a/exchanges/exmo/exmo.go b/exchanges/exmo/exmo.go index acf50798..07ee4f13 100644 --- a/exchanges/exmo/exmo.go +++ b/exchanges/exmo/exmo.go @@ -192,14 +192,14 @@ func (e *EXMO) GetRequiredAmount(ctx context.Context, pair string, amount float6 // GetCryptoDepositAddress returns a list of addresses for cryptocurrency deposits func (e *EXMO) GetCryptoDepositAddress(ctx context.Context) (map[string]string, error) { - var result interface{} + var result any err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoDepositAddress, url.Values{}, &result) if err != nil { return nil, err } switch r := result.(type) { - case map[string]interface{}: + case map[string]any: mapString := make(map[string]string) for key, value := range r { if key == "error" { @@ -285,7 +285,7 @@ func (e *EXMO) GetWalletHistory(ctx context.Context, date int64) (WalletHistory, } // SendHTTPRequest sends an unauthenticated HTTP request -func (e *EXMO) SendHTTPRequest(ctx context.Context, endpoint exchange.URL, path string, result interface{}) error { +func (e *EXMO) SendHTTPRequest(ctx context.Context, endpoint exchange.URL, path string, result any) error { urlPath, err := e.API.Endpoints.GetURL(endpoint) if err != nil { return err @@ -305,7 +305,7 @@ func (e *EXMO) SendHTTPRequest(ctx context.Context, endpoint exchange.URL, path } // SendAuthenticatedHTTPRequest sends an authenticated HTTP request -func (e *EXMO) SendAuthenticatedHTTPRequest(ctx context.Context, epath exchange.URL, method, endpoint string, vals url.Values, result interface{}) error { +func (e *EXMO) SendAuthenticatedHTTPRequest(ctx context.Context, epath exchange.URL, method, endpoint string, vals url.Values, result any) error { creds, err := e.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/fill/fill.go b/exchanges/fill/fill.go index aea552c1..04755fe4 100644 --- a/exchanges/fill/fill.go +++ b/exchanges/fill/fill.go @@ -6,7 +6,7 @@ import "errors" var ErrFeedDisabled = errors.New("fill feed disabled") // Setup sets up the fill processor -func (f *Fills) Setup(fillsFeedEnabled bool, c chan interface{}) { +func (f *Fills) Setup(fillsFeedEnabled bool, c chan any) { f.dataHandler = c f.fillsFeedEnabled = fillsFeedEnabled } diff --git a/exchanges/fill/fill_test.go b/exchanges/fill/fill_test.go index e34733b3..fe15e1c1 100644 --- a/exchanges/fill/fill_test.go +++ b/exchanges/fill/fill_test.go @@ -9,7 +9,7 @@ import ( // TestSetup tests the setup function of the Fills struct func TestSetup(t *testing.T) { fill := &Fills{} - channel := make(chan interface{}) + channel := make(chan any) fill.Setup(true, channel) if fill.dataHandler == nil { @@ -23,7 +23,7 @@ func TestSetup(t *testing.T) { // TestUpdateDisabledFeed tests the Update function when fillsFeedEnabled is false func TestUpdateDisabledFeed(t *testing.T) { - channel := make(chan interface{}, 1) + channel := make(chan any, 1) fill := Fills{dataHandler: channel, fillsFeedEnabled: false} // Send a test data to the Update function @@ -42,7 +42,7 @@ func TestUpdateDisabledFeed(t *testing.T) { // TestUpdate tests the Update function of the Fills struct. func TestUpdate(t *testing.T) { - channel := make(chan interface{}, 1) + channel := make(chan any, 1) fill := &Fills{dataHandler: channel, fillsFeedEnabled: true} receivedData := Data{Timestamp: time.Now(), Price: 15.2, Amount: 3.2} if err := fill.Update(receivedData); err != nil { @@ -66,7 +66,7 @@ func TestUpdate(t *testing.T) { // TestUpdateNoData tests the Update function with no Data objects func TestUpdateNoData(t *testing.T) { - channel := make(chan interface{}, 1) + channel := make(chan any, 1) fill := &Fills{dataHandler: channel, fillsFeedEnabled: true} if err := fill.Update(); err != nil { t.Errorf("Update returned error %v", err) @@ -82,7 +82,7 @@ func TestUpdateNoData(t *testing.T) { // TestUpdateMultipleData tests the Update function with multiple Data objects func TestUpdateMultipleData(t *testing.T) { - channel := make(chan interface{}, 2) + channel := make(chan any, 2) fill := &Fills{dataHandler: channel, fillsFeedEnabled: true} receivedData := Data{Timestamp: time.Now(), Price: 15.2, Amount: 3.2} receivedData2 := Data{Timestamp: time.Now(), Price: 18.2, Amount: 9.0} diff --git a/exchanges/fill/fill_types.go b/exchanges/fill/fill_types.go index 9b6f4a86..efc2505d 100644 --- a/exchanges/fill/fill_types.go +++ b/exchanges/fill/fill_types.go @@ -10,7 +10,7 @@ import ( // Fills is used to hold data and methods related to fill dissemination type Fills struct { - dataHandler chan interface{} + dataHandler chan any fillsFeedEnabled bool } diff --git a/exchanges/gateio/gateio.go b/exchanges/gateio/gateio.go index 774fc759..ed2ede40 100644 --- a/exchanges/gateio/gateio.go +++ b/exchanges/gateio/gateio.go @@ -928,7 +928,7 @@ func (g *Gateio) CancelPriceTriggeredOrder(ctx context.Context, orderID string) } // GenerateSignature returns hash for authenticated requests -func (g *Gateio) GenerateSignature(secret, method, path, query string, body interface{}, dtime time.Time) (string, error) { +func (g *Gateio) GenerateSignature(secret, method, path, query string, body any, dtime time.Time) (string, error) { h := sha512.New() if body != nil { val, err := json.Marshal(body) @@ -952,7 +952,7 @@ func (g *Gateio) GenerateSignature(secret, method, path, query string, body inte // SendAuthenticatedHTTPRequest sends authenticated requests to the Gateio API // To use this you must setup an APIKey and APISecret from the exchange -func (g *Gateio) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, epl request.EndpointLimit, method, endpoint string, param url.Values, data, result interface{}) error { +func (g *Gateio) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, epl request.EndpointLimit, method, endpoint string, param url.Values, data, result any) error { creds, err := g.GetCredentials(ctx) if err != nil { return err @@ -1026,7 +1026,7 @@ func (g *Gateio) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U } // SendHTTPRequest sends an unauthenticated HTTP request -func (g *Gateio) SendHTTPRequest(ctx context.Context, ep exchange.URL, epl request.EndpointLimit, path string, result interface{}) error { +func (g *Gateio) SendHTTPRequest(ctx context.Context, ep exchange.URL, epl request.EndpointLimit, path string, result any) error { endpoint, err := g.API.Endpoints.GetURL(ep) if err != nil { return err diff --git a/exchanges/gateio/gateio_test.go b/exchanges/gateio/gateio_test.go index 81a73b32..985b6a1f 100644 --- a/exchanges/gateio/gateio_test.go +++ b/exchanges/gateio/gateio_test.go @@ -2742,7 +2742,7 @@ func TestOptionsOrderbookPushData(t *testing.T) { assert.NoError(t, g.WsHandleOptionsData(context.Background(), []byte(optionsOrderbookTickerPushDataJSON))) avail, err := g.GetAvailablePairs(asset.Options) require.NoError(t, err, "GetAvailablePairs must not error") - assert.NoError(t, g.WsHandleOptionsData(context.Background(), []byte(fmt.Sprintf(optionsOrderbookUpdatePushDataJSON, avail[0].Upper().String())))) + assert.NoError(t, g.WsHandleOptionsData(context.Background(), fmt.Appendf(nil, optionsOrderbookUpdatePushDataJSON, avail[0].Upper().String()))) assert.NoError(t, g.WsHandleOptionsData(context.Background(), []byte(optionsOrderbookSnapshotPushDataJSON))) assert.NoError(t, g.WsHandleOptionsData(context.Background(), []byte(optionsOrderbookSnapshotUpdateEventPushDataJSON))) } diff --git a/exchanges/gateio/gateio_types.go b/exchanges/gateio/gateio_types.go index ec75c7e1..b9aba181 100644 --- a/exchanges/gateio/gateio_types.go +++ b/exchanges/gateio/gateio_types.go @@ -1240,7 +1240,7 @@ type MarginLoanRequestParam struct { Amount types.Number `json:"amount,omitempty"` Days int64 `json:"days,omitempty"` AutoRenew bool `json:"auto_renew,omitempty"` - CurrencyPair currency.Pair `json:"currency_pair,omitempty"` + CurrencyPair currency.Pair `json:"currency_pair,omitzero"` FeeRate types.Number `json:"fee_rate,omitempty"` OrigID string `json:"orig_id,omitempty"` Text string `json:"text,omitempty"` @@ -1367,7 +1367,7 @@ type SpotAccount struct { // CreateOrderRequestData represents a single order creation param. type CreateOrderRequestData struct { Text string `json:"text,omitempty"` - CurrencyPair currency.Pair `json:"currency_pair,omitempty"` + CurrencyPair currency.Pair `json:"currency_pair,omitzero"` Type string `json:"type,omitempty"` Account string `json:"account,omitempty"` Side string `json:"side,omitempty"` @@ -1385,8 +1385,8 @@ type SpotOrder struct { Succeeded bool `json:"succeeded"` ErrorLabel string `json:"label,omitempty"` Message string `json:"message,omitempty"` - CreateTime types.Time `json:"create_time_ms,omitempty"` - UpdateTime types.Time `json:"update_time_ms,omitempty"` + CreateTime types.Time `json:"create_time_ms,omitzero"` + UpdateTime types.Time `json:"update_time_ms,omitzero"` CurrencyPair string `json:"currency_pair,omitempty"` Status string `json:"status,omitempty"` Type string `json:"type,omitempty"` @@ -2077,7 +2077,7 @@ type WsSpotOrder struct { Succeeded bool `json:"succeeded,omitempty"` Label string `json:"label,omitempty"` Message string `json:"message,omitempty"` - CurrencyPair currency.Pair `json:"currency_pair,omitempty"` + CurrencyPair currency.Pair `json:"currency_pair,omitzero"` Type string `json:"type,omitempty"` Account string `json:"account,omitempty"` Side string `json:"side,omitempty"` @@ -2095,8 +2095,8 @@ type WsSpotOrder struct { RebatedFee string `json:"rebated_fee,omitempty"` RebatedFeeCurrency string `json:"rebated_fee_currency,omitempty"` Event string `json:"event"` - CreateTime types.Time `json:"create_time_ms,omitempty"` - UpdateTime types.Time `json:"update_time_ms,omitempty"` + CreateTime types.Time `json:"create_time_ms,omitzero"` + UpdateTime types.Time `json:"update_time_ms,omitzero"` } // WsUserPersonalTrade represents a user's personal trade pushed through the websocket connection. diff --git a/exchanges/gemini/gemini.go b/exchanges/gemini/gemini.go index 4c646d23..bcabca1b 100644 --- a/exchanges/gemini/gemini.go +++ b/exchanges/gemini/gemini.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "maps" "net/http" "net/url" "strconv" @@ -174,7 +175,7 @@ func (g *Gemini) GetAuctionHistory(ctx context.Context, currencyPair string, par // NewOrder Only limit orders are supported through the API at present. // returns order ID if successful func (g *Gemini) NewOrder(ctx context.Context, symbol string, amount, price float64, side, orderType string) (int64, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) req["price"] = strconv.FormatFloat(price, 'f', -1, 64) @@ -191,7 +192,7 @@ func (g *Gemini) NewOrder(ctx context.Context, symbol string, amount, price floa // Transfers returns transfer history ie withdrawals and deposits func (g *Gemini) Transfers(ctx context.Context, curr currency.Code, start time.Time, limit int64, account string, showCompletedDeposit bool) ([]TransferResponse, error) { - req := make(map[string]interface{}) + req := make(map[string]any) if !curr.IsEmpty() { req["symbol"] = curr.String() } @@ -215,7 +216,7 @@ func (g *Gemini) Transfers(ctx context.Context, curr currency.Code, start time.T // CancelExistingOrder will cancel an order. If the order is already canceled, the // message will succeed but have no effect. func (g *Gemini) CancelExistingOrder(ctx context.Context, orderID int64) (Order, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["order_id"] = orderID response := Order{} @@ -253,7 +254,7 @@ func (g *Gemini) CancelExistingOrders(ctx context.Context, cancelBySession bool) // GetOrderStatus returns the status for an order func (g *Gemini) GetOrderStatus(ctx context.Context, orderID int64) (Order, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["order_id"] = orderID response := Order{} @@ -271,7 +272,7 @@ func (g *Gemini) GetOrderStatus(ctx context.Context, orderID int64) (Order, erro // GetOrders returns active orders in the market func (g *Gemini) GetOrders(ctx context.Context) ([]Order, error) { - var response interface{} + var response any type orders struct { orders []Order @@ -296,7 +297,7 @@ func (g *Gemini) GetOrders(ctx context.Context) ([]Order, error) { // timestamp - [optional] Only return trades on or after this timestamp. func (g *Gemini) GetTradeHistory(ctx context.Context, currencyPair string, timestamp int64) ([]TradeHistory, error) { var response []TradeHistory - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = currencyPair if timestamp > 0 { @@ -334,7 +335,7 @@ func (g *Gemini) GetBalances(ctx context.Context) ([]Balance, error) { // GetCryptoDepositAddress returns a deposit address func (g *Gemini) GetCryptoDepositAddress(ctx context.Context, depositAddlabel, currency string) (DepositAddress, error) { response := DepositAddress{} - req := make(map[string]interface{}) + req := make(map[string]any) if depositAddlabel != "" { req["label"] = depositAddlabel @@ -353,7 +354,7 @@ func (g *Gemini) GetCryptoDepositAddress(ctx context.Context, depositAddlabel, c // WithdrawCrypto withdraws crypto currency to a whitelisted address func (g *Gemini) WithdrawCrypto(ctx context.Context, address, currency string, amount float64) (WithdrawalAddress, error) { response := WithdrawalAddress{} - req := make(map[string]interface{}) + req := make(map[string]any) req["address"] = address req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) @@ -387,7 +388,7 @@ func (g *Gemini) PostHeartbeat(ctx context.Context) (string, error) { } // SendHTTPRequest sends an unauthenticated request -func (g *Gemini) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error { +func (g *Gemini) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { endpoint, err := g.API.Endpoints.GetURL(ep) if err != nil { return err @@ -409,7 +410,7 @@ func (g *Gemini) SendHTTPRequest(ctx context.Context, ep exchange.URL, path stri // SendAuthenticatedHTTPRequest sends an authenticated HTTP request to the // exchange and returns an error -func (g *Gemini) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params map[string]interface{}, result interface{}) (err error) { +func (g *Gemini) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params map[string]any, result any) (err error) { creds, err := g.GetCredentials(ctx) if err != nil { return err @@ -421,13 +422,11 @@ func (g *Gemini) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U } return g.SendPayload(ctx, request.Auth, func() (*request.Item, error) { - req := make(map[string]interface{}) + req := make(map[string]any) req["request"] = fmt.Sprintf("/v%s/%s", geminiAPIVersion, path) req["nonce"] = g.Requester.GetNonce(nonce.UnixNano).String() - for key, value := range params { - req[key] = value - } + maps.Copy(req, params) PayloadJSON, err := json.Marshal(req) if err != nil { diff --git a/exchanges/gemini/gemini_websocket.go b/exchanges/gemini/gemini_websocket.go index b04d319d..b78645e2 100644 --- a/exchanges/gemini/gemini_websocket.go +++ b/exchanges/gemini/gemini_websocket.go @@ -287,7 +287,7 @@ func (g *Gemini) wsHandleData(respRaw []byte) error { } return nil } - var result map[string]interface{} + var result map[string]any err := json.Unmarshal(respRaw, &result) if err != nil { return fmt.Errorf("%v Error: %v, Raw: %v", g.Name, err, string(respRaw)) diff --git a/exchanges/hitbtc/hitbtc.go b/exchanges/hitbtc/hitbtc.go index 78a131f0..09c6baec 100644 --- a/exchanges/hitbtc/hitbtc.go +++ b/exchanges/hitbtc/hitbtc.go @@ -419,7 +419,7 @@ func (h *HitBTC) GetFeeInfo(ctx context.Context, currencyPair string) (Fee, erro } // SendHTTPRequest sends an unauthenticated HTTP request -func (h *HitBTC) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error { +func (h *HitBTC) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { endpoint, err := h.API.Endpoints.GetURL(ep) if err != nil { return err @@ -440,7 +440,7 @@ func (h *HitBTC) SendHTTPRequest(ctx context.Context, ep exchange.URL, path stri } // SendAuthenticatedHTTPRequest sends an authenticated http request -func (h *HitBTC) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, f request.EndpointLimit, result interface{}) error { +func (h *HitBTC) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, f request.EndpointLimit, result any) error { creds, err := h.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/hitbtc/hitbtc_types.go b/exchanges/hitbtc/hitbtc_types.go index 9b614ef9..3b717322 100644 --- a/exchanges/hitbtc/hitbtc_types.go +++ b/exchanges/hitbtc/hitbtc_types.go @@ -280,8 +280,8 @@ type LendingHistory struct { type capture struct { Method string `json:"method,omitempty"` - Result interface{} `json:"result"` - Error ResponseError `json:"error,omitempty"` + Result any `json:"result"` + Error ResponseError `json:"error"` ID int64 `json:"id,omitempty"` } @@ -372,7 +372,7 @@ type WsLoginData struct { // wsActiveOrdersResponse Active order response for auth subscription to reports type wsActiveOrdersResponse struct { Params []wsOrderData `json:"params"` - Error ResponseError `json:"error,omitempty"` + Error ResponseError `json:"error"` } type wsReportResponse struct { @@ -416,7 +416,7 @@ type wsOrderData struct { // WsReportResponse report response for auth subscription to reports type WsReportResponse struct { Params WsReportResponseData `json:"params"` - Error ResponseError `json:"error,omitempty"` + Error ResponseError `json:"error"` } // WsReportResponseData Report data for WsReportResponse @@ -461,7 +461,7 @@ type WsSubmitOrderRequestData struct { type WsSubmitOrderSuccessResponse struct { Result WsSubmitOrderSuccessResponseData `json:"result"` ID int64 `json:"id"` - Error ResponseError `json:"error,omitempty"` + Error ResponseError `json:"error"` } // WsSubmitOrderSuccessResponseData WS response data @@ -484,7 +484,7 @@ type WsSubmitOrderSuccessResponseData struct { // WsSubmitOrderErrorResponse WS error response type WsSubmitOrderErrorResponse struct { - Error WsSubmitOrderErrorResponseData `json:"error,omitempty"` + Error WsSubmitOrderErrorResponseData `json:"error"` ID int64 `json:"id"` } @@ -499,7 +499,7 @@ type WsSubmitOrderErrorResponseData struct { type WsCancelOrderResponse struct { Result WsCancelOrderResponseData `json:"result"` ID int64 `json:"id"` - Error ResponseError `json:"error,omitempty"` + Error ResponseError `json:"error"` } // WsCancelOrderResponseData WS response data @@ -524,7 +524,7 @@ type WsCancelOrderResponseData struct { type WsReplaceOrderResponse struct { Result WsReplaceOrderResponseData `json:"result"` ID int64 `json:"id"` - Error ResponseError `json:"error,omitempty"` + Error ResponseError `json:"error"` } // WsReplaceOrderResponseData WS response data @@ -550,7 +550,7 @@ type WsReplaceOrderResponseData struct { type WsGetActiveOrdersResponse struct { Result []WsGetActiveOrdersResponseData `json:"result"` ID int64 `json:"id"` - Error ResponseError `json:"error,omitempty"` + Error ResponseError `json:"error"` } // WsGetActiveOrdersResponseData WS response data @@ -576,7 +576,7 @@ type WsGetActiveOrdersResponseData struct { type WsGetTradingBalanceResponse struct { Result []WsGetTradingBalanceResponseData `json:"result"` ID int64 `json:"id"` - Error ResponseError `json:"error,omitempty"` + Error ResponseError `json:"error"` } // WsGetTradingBalanceResponseData WS response data @@ -629,7 +629,7 @@ type WsGetCurrenciesRequestParameters struct { type WsGetCurrenciesResponse struct { Result WsGetCurrenciesResponseData `json:"result"` ID int64 `json:"id"` - Error ResponseError `json:"error,omitempty"` + Error ResponseError `json:"error"` } // WsGetCurrenciesResponseData currency response data @@ -663,7 +663,7 @@ type WsGetSymbolsRequestParameters struct { type WsGetSymbolsResponse struct { Result WsGetSymbolsResponseData `json:"result"` ID int64 `json:"id"` - Error ResponseError `json:"error,omitempty"` + Error ResponseError `json:"error"` } // WsGetSymbolsResponseData symbol response data @@ -698,7 +698,7 @@ type WsGetTradesResponse struct { Jsonrpc string `json:"jsonrpc"` Result WsGetTradesResponseData `json:"result"` ID int64 `json:"id"` - Error ResponseError `json:"error,omitempty"` + Error ResponseError `json:"error"` } // WsGetTradesResponseData trade response data diff --git a/exchanges/hitbtc/hitbtc_websocket.go b/exchanges/hitbtc/hitbtc_websocket.go index b2dea790..a4af461b 100644 --- a/exchanges/hitbtc/hitbtc_websocket.go +++ b/exchanges/hitbtc/hitbtc_websocket.go @@ -117,7 +117,7 @@ func (h *HitBTC) wsGetTableName(respRaw []byte) (string, error) { return init.Method, nil } switch resultType := init.Result.(type) { - case map[string]interface{}: + case map[string]any: if reportType, ok := resultType["reportType"].(string); ok { return reportType, nil } @@ -128,13 +128,13 @@ func (h *HitBTC) wsGetTableName(respRaw []byte) (string, error) { return "", nil } } - case []interface{}: + case []any: if len(resultType) == 0 { h.Websocket.DataHandler <- fmt.Sprintf("No data returned. ID: %v", init.ID) return "", nil } - data, ok := resultType[0].(map[string]interface{}) + data, ok := resultType[0].(map[string]any) if !ok { return "", errors.New("unable to type assert data") } diff --git a/exchanges/huobi/huobi.go b/exchanges/huobi/huobi.go index 3870245e..426cf9ab 100644 --- a/exchanges/huobi/huobi.go +++ b/exchanges/huobi/huobi.go @@ -873,7 +873,7 @@ func (h *HUOBI) SearchForExistedWithdrawsAndDeposits(ctx context.Context, c curr } // SendHTTPRequest sends an unauthenticated HTTP request -func (h *HUOBI) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error { +func (h *HUOBI) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { endpoint, err := h.API.Endpoints.GetURL(ep) if err != nil { return err @@ -911,7 +911,7 @@ func (h *HUOBI) SendHTTPRequest(ctx context.Context, ep exchange.URL, path strin } // SendAuthenticatedHTTPRequest sends authenticated requests to the HUOBI API -func (h *HUOBI) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, data, result interface{}, isVersion2API bool) error { +func (h *HUOBI) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, data, result any, isVersion2API bool) error { var err error creds, err := h.GetCredentials(ctx) if err != nil { diff --git a/exchanges/huobi/huobi_cfutures.go b/exchanges/huobi/huobi_cfutures.go index 699b7348..edd4a427 100644 --- a/exchanges/huobi/huobi_cfutures.go +++ b/exchanges/huobi/huobi_cfutures.go @@ -400,7 +400,7 @@ func (h *HUOBI) GetBasisData(ctx context.Context, code currency.Pair, period, ba // GetSwapAccountInfo gets swap account info func (h *HUOBI) GetSwapAccountInfo(ctx context.Context, code currency.Pair) (SwapAccountInformation, error) { var resp SwapAccountInformation - req := make(map[string]interface{}) + req := make(map[string]any) if !code.IsEmpty() { codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { @@ -414,7 +414,7 @@ func (h *HUOBI) GetSwapAccountInfo(ctx context.Context, code currency.Pair) (Swa // GetSwapPositionsInfo gets swap positions' info func (h *HUOBI) GetSwapPositionsInfo(ctx context.Context, code currency.Pair) (SwapPositionInfo, error) { var resp SwapPositionInfo - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -426,7 +426,7 @@ func (h *HUOBI) GetSwapPositionsInfo(ctx context.Context, code currency.Pair) (S // GetSwapAssetsAndPositions gets swap positions and asset info func (h *HUOBI) GetSwapAssetsAndPositions(ctx context.Context, code currency.Pair) (SwapAssetsAndPositionsData, error) { var resp SwapAssetsAndPositionsData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -438,7 +438,7 @@ func (h *HUOBI) GetSwapAssetsAndPositions(ctx context.Context, code currency.Pai // GetSwapAllSubAccAssets gets asset info for all subaccounts func (h *HUOBI) GetSwapAllSubAccAssets(ctx context.Context, code currency.Pair) (SubAccountsAssetData, error) { var resp SubAccountsAssetData - req := make(map[string]interface{}) + req := make(map[string]any) if !code.IsEmpty() { codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { @@ -452,7 +452,7 @@ func (h *HUOBI) GetSwapAllSubAccAssets(ctx context.Context, code currency.Pair) // SwapSingleSubAccAssets gets a subaccount's assets info func (h *HUOBI) SwapSingleSubAccAssets(ctx context.Context, code currency.Pair, subUID int64) (SingleSubAccountAssetsInfo, error) { var resp SingleSubAccountAssetsInfo - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -465,7 +465,7 @@ func (h *HUOBI) SwapSingleSubAccAssets(ctx context.Context, code currency.Pair, // GetSubAccPositionInfo gets a subaccount's positions info func (h *HUOBI) GetSubAccPositionInfo(ctx context.Context, code currency.Pair, subUID int64) (SingleSubAccountPositionsInfo, error) { var resp SingleSubAccountPositionsInfo - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -478,7 +478,7 @@ func (h *HUOBI) GetSubAccPositionInfo(ctx context.Context, code currency.Pair, s // GetAccountFinancialRecords gets the account's financial records func (h *HUOBI) GetAccountFinancialRecords(ctx context.Context, code currency.Pair, orderType string, createDate, pageIndex, pageSize int64) (FinancialRecordData, error) { var resp FinancialRecordData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -502,7 +502,7 @@ func (h *HUOBI) GetAccountFinancialRecords(ctx context.Context, code currency.Pa // GetSwapSettlementRecords gets the swap account's settlement records func (h *HUOBI) GetSwapSettlementRecords(ctx context.Context, code currency.Pair, startTime, endTime time.Time, pageIndex, pageSize int64) (FinancialRecordData, error) { var resp FinancialRecordData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -527,7 +527,7 @@ func (h *HUOBI) GetSwapSettlementRecords(ctx context.Context, code currency.Pair // GetAvailableLeverage gets user's available leverage data func (h *HUOBI) GetAvailableLeverage(ctx context.Context, code currency.Pair) (AvailableLeverageData, error) { var resp AvailableLeverageData - req := make(map[string]interface{}) + req := make(map[string]any) if !code.IsEmpty() { codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { @@ -541,7 +541,7 @@ func (h *HUOBI) GetAvailableLeverage(ctx context.Context, code currency.Pair) (A // GetSwapOrderLimitInfo gets order limit info for swaps func (h *HUOBI) GetSwapOrderLimitInfo(ctx context.Context, code currency.Pair, orderType string) (SwapOrderLimitInfo, error) { var resp SwapOrderLimitInfo - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -557,7 +557,7 @@ func (h *HUOBI) GetSwapOrderLimitInfo(ctx context.Context, code currency.Pair, o // GetSwapTradingFeeInfo gets trading fee info for swaps func (h *HUOBI) GetSwapTradingFeeInfo(ctx context.Context, code currency.Pair) (SwapTradingFeeData, error) { var resp SwapTradingFeeData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -569,7 +569,7 @@ func (h *HUOBI) GetSwapTradingFeeInfo(ctx context.Context, code currency.Pair) ( // GetSwapTransferLimitInfo gets transfer limit info for swaps func (h *HUOBI) GetSwapTransferLimitInfo(ctx context.Context, code currency.Pair) (TransferLimitData, error) { var resp TransferLimitData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -581,7 +581,7 @@ func (h *HUOBI) GetSwapTransferLimitInfo(ctx context.Context, code currency.Pair // GetSwapPositionLimitInfo gets transfer limit info for swaps func (h *HUOBI) GetSwapPositionLimitInfo(ctx context.Context, code currency.Pair) (PositionLimitData, error) { var resp PositionLimitData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -593,7 +593,7 @@ func (h *HUOBI) GetSwapPositionLimitInfo(ctx context.Context, code currency.Pair // AccountTransferData gets asset transfer data between master and subaccounts func (h *HUOBI) AccountTransferData(ctx context.Context, code currency.Pair, subUID, transferType string, amount float64) (InternalAccountTransferData, error) { var resp InternalAccountTransferData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -611,7 +611,7 @@ func (h *HUOBI) AccountTransferData(ctx context.Context, code currency.Pair, sub // AccountTransferRecords gets asset transfer records between master and subaccounts func (h *HUOBI) AccountTransferRecords(ctx context.Context, code currency.Pair, transferType string, createDate, pageIndex, pageSize int64) (InternalAccountTransferData, error) { var resp InternalAccountTransferData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -637,7 +637,7 @@ func (h *HUOBI) AccountTransferRecords(ctx context.Context, code currency.Pair, // PlaceSwapOrders places orders for swaps func (h *HUOBI) PlaceSwapOrders(ctx context.Context, code currency.Pair, clientOrderID, direction, offset, orderPriceType string, price, volume, leverage float64) (SwapOrderData, error) { var resp SwapOrderData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(code, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -661,7 +661,7 @@ func (h *HUOBI) PlaceSwapOrders(ctx context.Context, code currency.Pair, clientO // PlaceSwapBatchOrders places a batch of orders for swaps func (h *HUOBI) PlaceSwapBatchOrders(ctx context.Context, data BatchOrderRequestType) (BatchOrderData, error) { var resp BatchOrderData - req := make(map[string]interface{}) + req := make(map[string]any) if len(data.Data) > 10 || len(data.Data) == 0 { return resp, errors.New("invalid data provided: maximum of 10 batch orders supported") } @@ -686,7 +686,7 @@ func (h *HUOBI) PlaceSwapBatchOrders(ctx context.Context, data BatchOrderRequest // CancelSwapOrder sends a request to cancel an order func (h *HUOBI) CancelSwapOrder(ctx context.Context, orderID, clientOrderID string, contractCode currency.Pair) (CancelOrdersData, error) { var resp CancelOrdersData - req := make(map[string]interface{}) + req := make(map[string]any) if orderID != "" { req["order_id"] = orderID } @@ -700,7 +700,7 @@ func (h *HUOBI) CancelSwapOrder(ctx context.Context, orderID, clientOrderID stri // CancelAllSwapOrders sends a request to cancel an order func (h *HUOBI) CancelAllSwapOrders(ctx context.Context, contractCode currency.Pair) (CancelOrdersData, error) { var resp CancelOrdersData - req := make(map[string]interface{}) + req := make(map[string]any) req["contract_code"] = contractCode return resp, h.FuturesAuthenticatedHTTPRequest(ctx, exchange.RestFutures, http.MethodPost, huobiSwapCancelAllOrders, nil, req, &resp) } @@ -708,7 +708,7 @@ func (h *HUOBI) CancelAllSwapOrders(ctx context.Context, contractCode currency.P // PlaceLightningCloseOrder places a lightning close order func (h *HUOBI) PlaceLightningCloseOrder(ctx context.Context, contractCode currency.Pair, direction, orderPriceType string, volume float64, clientOrderID int64) (LightningCloseOrderData, error) { var resp LightningCloseOrderData - req := make(map[string]interface{}) + req := make(map[string]any) req["contract_code"] = contractCode req["volume"] = volume req["direction"] = direction @@ -727,7 +727,7 @@ func (h *HUOBI) PlaceLightningCloseOrder(ctx context.Context, contractCode curre // GetSwapOrderDetails gets order info func (h *HUOBI) GetSwapOrderDetails(ctx context.Context, contractCode currency.Pair, orderID, createdAt, orderType string, pageIndex, pageSize int64) (SwapOrderData, error) { var resp SwapOrderData - req := make(map[string]interface{}) + req := make(map[string]any) req["contract_code"] = contractCode req["order_id"] = orderID req["created_at"] = createdAt @@ -748,7 +748,7 @@ func (h *HUOBI) GetSwapOrderDetails(ctx context.Context, contractCode currency.P // GetSwapOrderInfo gets info on a swap order func (h *HUOBI) GetSwapOrderInfo(ctx context.Context, contractCode currency.Pair, orderID, clientOrderID string) (SwapOrderInfo, error) { var resp SwapOrderInfo - req := make(map[string]interface{}) + req := make(map[string]any) if !contractCode.IsEmpty() { codeValue, err := h.FormatSymbol(contractCode, asset.CoinMarginedFutures) if err != nil { @@ -768,7 +768,7 @@ func (h *HUOBI) GetSwapOrderInfo(ctx context.Context, contractCode currency.Pair // GetSwapOpenOrders gets open orders for swap func (h *HUOBI) GetSwapOpenOrders(ctx context.Context, contractCode currency.Pair, pageIndex, pageSize int64) (SwapOpenOrdersData, error) { var resp SwapOpenOrdersData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(contractCode, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -786,7 +786,7 @@ func (h *HUOBI) GetSwapOpenOrders(ctx context.Context, contractCode currency.Pai // GetSwapOrderHistory gets swap order history func (h *HUOBI) GetSwapOrderHistory(ctx context.Context, contractCode currency.Pair, tradeType, reqType string, status []order.Status, createDate, pageIndex, pageSize int64) (SwapOrderHistory, error) { var resp SwapOrderHistory - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(contractCode, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -835,7 +835,7 @@ func (h *HUOBI) GetSwapOrderHistory(ctx context.Context, contractCode currency.P // GetSwapTradeHistory gets swap trade history func (h *HUOBI) GetSwapTradeHistory(ctx context.Context, contractCode currency.Pair, tradeType string, createDate, pageIndex, pageSize int64) (AccountTradeHistoryData, error) { var resp AccountTradeHistoryData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(contractCode, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -862,7 +862,7 @@ func (h *HUOBI) GetSwapTradeHistory(ctx context.Context, contractCode currency.P // PlaceSwapTriggerOrder places a trigger order for a swap func (h *HUOBI) PlaceSwapTriggerOrder(ctx context.Context, contractCode currency.Pair, triggerType, direction, offset, orderPriceType string, triggerPrice, orderPrice, volume, leverageRate float64) (AccountTradeHistoryData, error) { var resp AccountTradeHistoryData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(contractCode, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -889,7 +889,7 @@ func (h *HUOBI) PlaceSwapTriggerOrder(ctx context.Context, contractCode currency // CancelSwapTriggerOrder cancels swap trigger order func (h *HUOBI) CancelSwapTriggerOrder(ctx context.Context, contractCode currency.Pair, orderID string) (CancelTriggerOrdersData, error) { var resp CancelTriggerOrdersData - req := make(map[string]interface{}) + req := make(map[string]any) req["contract_code"] = contractCode req["order_id"] = orderID return resp, h.FuturesAuthenticatedHTTPRequest(ctx, exchange.RestFutures, http.MethodPost, huobiSwapCancelTriggerOrder, nil, req, &resp) @@ -898,7 +898,7 @@ func (h *HUOBI) CancelSwapTriggerOrder(ctx context.Context, contractCode currenc // CancelAllSwapTriggerOrders cancels all swap trigger orders func (h *HUOBI) CancelAllSwapTriggerOrders(ctx context.Context, contractCode currency.Pair) (CancelTriggerOrdersData, error) { var resp CancelTriggerOrdersData - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(contractCode, asset.CoinMarginedFutures) if err != nil { return resp, err @@ -910,7 +910,7 @@ func (h *HUOBI) CancelAllSwapTriggerOrders(ctx context.Context, contractCode cur // GetSwapTriggerOrderHistory gets history for swap trigger orders func (h *HUOBI) GetSwapTriggerOrderHistory(ctx context.Context, contractCode currency.Pair, status, tradeType string, createDate, pageIndex, pageSize int64) (TriggerOrderHistory, error) { var resp TriggerOrderHistory - req := make(map[string]interface{}) + req := make(map[string]any) codeValue, err := h.FormatSymbol(contractCode, asset.CoinMarginedFutures) if err != nil { return resp, err diff --git a/exchanges/huobi/huobi_futures.go b/exchanges/huobi/huobi_futures.go index 5deddd97..64bf666a 100644 --- a/exchanges/huobi/huobi_futures.go +++ b/exchanges/huobi/huobi_futures.go @@ -488,7 +488,7 @@ func (h *HUOBI) FGetBasisData(ctx context.Context, symbol currency.Pair, period, // FGetAccountInfo gets user info for futures account func (h *HUOBI) FGetAccountInfo(ctx context.Context, symbol currency.Code) (FUserAccountData, error) { var resp FUserAccountData - req := make(map[string]interface{}) + req := make(map[string]any) if !symbol.IsEmpty() { codeValue, err := h.formatFuturesCode(symbol) if err != nil { @@ -502,7 +502,7 @@ func (h *HUOBI) FGetAccountInfo(ctx context.Context, symbol currency.Code) (FUse // FGetPositionsInfo gets positions info for futures account func (h *HUOBI) FGetPositionsInfo(ctx context.Context, symbol currency.Code) (FUsersPositionsInfo, error) { var resp FUsersPositionsInfo - req := make(map[string]interface{}) + req := make(map[string]any) if !symbol.IsEmpty() { codeValue, err := h.formatFuturesCode(symbol) if err != nil { @@ -516,7 +516,7 @@ func (h *HUOBI) FGetPositionsInfo(ctx context.Context, symbol currency.Code) (FU // FGetAllSubAccountAssets gets assets info for all futures subaccounts func (h *HUOBI) FGetAllSubAccountAssets(ctx context.Context, symbol currency.Code) (FSubAccountAssetsInfo, error) { var resp FSubAccountAssetsInfo - req := make(map[string]interface{}) + req := make(map[string]any) if !symbol.IsEmpty() { codeValue, err := h.formatFuturesCode(symbol) if err != nil { @@ -530,7 +530,7 @@ func (h *HUOBI) FGetAllSubAccountAssets(ctx context.Context, symbol currency.Cod // FGetSingleSubAccountInfo gets assets info for a futures subaccount func (h *HUOBI) FGetSingleSubAccountInfo(ctx context.Context, symbol, subUID string) (FSingleSubAccountAssetsInfo, error) { var resp FSingleSubAccountAssetsInfo - req := make(map[string]interface{}) + req := make(map[string]any) if symbol != "" { req["symbol"] = symbol } @@ -541,7 +541,7 @@ func (h *HUOBI) FGetSingleSubAccountInfo(ctx context.Context, symbol, subUID str // FGetSingleSubPositions gets positions info for a single sub account func (h *HUOBI) FGetSingleSubPositions(ctx context.Context, symbol, subUID string) (FSingleSubAccountPositionsInfo, error) { var resp FSingleSubAccountPositionsInfo - req := make(map[string]interface{}) + req := make(map[string]any) if symbol != "" { req["symbol"] = symbol } @@ -552,7 +552,7 @@ func (h *HUOBI) FGetSingleSubPositions(ctx context.Context, symbol, subUID strin // FGetFinancialRecords gets financial records for futures func (h *HUOBI) FGetFinancialRecords(ctx context.Context, symbol, recordType string, createDate, pageIndex, pageSize int64) (FFinancialRecords, error) { var resp FFinancialRecords - req := make(map[string]interface{}) + req := make(map[string]any) if symbol != "" { req["symbol"] = symbol } @@ -578,7 +578,7 @@ func (h *HUOBI) FGetFinancialRecords(ctx context.Context, symbol, recordType str // FGetSettlementRecords gets settlement records for futures func (h *HUOBI) FGetSettlementRecords(ctx context.Context, symbol currency.Code, pageIndex, pageSize int64, startTime, endTime time.Time) (FSettlementRecords, error) { var resp FSettlementRecords - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol if pageIndex != 0 { req["page_index"] = pageIndex @@ -599,7 +599,7 @@ func (h *HUOBI) FGetSettlementRecords(ctx context.Context, symbol currency.Code, // FGetOrderLimits gets order limits for futures contracts func (h *HUOBI) FGetOrderLimits(ctx context.Context, symbol, orderPriceType string) (FContractInfoOnOrderLimit, error) { var resp FContractInfoOnOrderLimit - req := make(map[string]interface{}) + req := make(map[string]any) if symbol != "" { req["symbol"] = symbol } @@ -615,7 +615,7 @@ func (h *HUOBI) FGetOrderLimits(ctx context.Context, symbol, orderPriceType stri // FContractTradingFee gets futures contract trading fees func (h *HUOBI) FContractTradingFee(ctx context.Context, symbol currency.Code) (FContractTradingFeeData, error) { var resp FContractTradingFeeData - req := make(map[string]interface{}) + req := make(map[string]any) if !symbol.IsEmpty() { codeValue, err := h.formatFuturesCode(symbol) if err != nil { @@ -629,7 +629,7 @@ func (h *HUOBI) FContractTradingFee(ctx context.Context, symbol currency.Code) ( // FGetTransferLimits gets transfer limits for futures func (h *HUOBI) FGetTransferLimits(ctx context.Context, symbol currency.Code) (FTransferLimitData, error) { var resp FTransferLimitData - req := make(map[string]interface{}) + req := make(map[string]any) if !symbol.IsEmpty() { codeValue, err := h.formatFuturesCode(symbol) if err != nil { @@ -643,7 +643,7 @@ func (h *HUOBI) FGetTransferLimits(ctx context.Context, symbol currency.Code) (F // FGetPositionLimits gets position limits for futures func (h *HUOBI) FGetPositionLimits(ctx context.Context, symbol currency.Code) (FPositionLimitData, error) { var resp FPositionLimitData - req := make(map[string]interface{}) + req := make(map[string]any) if !symbol.IsEmpty() { codeValue, err := h.formatFuturesCode(symbol) if err != nil { @@ -657,7 +657,7 @@ func (h *HUOBI) FGetPositionLimits(ctx context.Context, symbol currency.Code) (F // FGetAssetsAndPositions gets assets and positions for futures func (h *HUOBI) FGetAssetsAndPositions(ctx context.Context, symbol currency.Code) (FAssetsAndPositionsData, error) { var resp FAssetsAndPositionsData - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol return resp, h.FuturesAuthenticatedHTTPRequest(ctx, exchange.RestFutures, http.MethodPost, fQueryAssetsAndPositions, nil, req, &resp) } @@ -665,7 +665,7 @@ func (h *HUOBI) FGetAssetsAndPositions(ctx context.Context, symbol currency.Code // FTransfer transfers assets between master and subaccounts func (h *HUOBI) FTransfer(ctx context.Context, subUID, symbol, transferType string, amount float64) (FAccountTransferData, error) { var resp FAccountTransferData - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol req["subUid"] = subUID req["amount"] = amount @@ -679,7 +679,7 @@ func (h *HUOBI) FTransfer(ctx context.Context, subUID, symbol, transferType stri // FGetTransferRecords gets transfer records data for futures func (h *HUOBI) FGetTransferRecords(ctx context.Context, symbol, transferType string, createDate, pageIndex, pageSize int64) (FTransferRecords, error) { var resp FTransferRecords - req := make(map[string]interface{}) + req := make(map[string]any) if symbol != "" { req["symbol"] = symbol } @@ -703,7 +703,7 @@ func (h *HUOBI) FGetTransferRecords(ctx context.Context, symbol, transferType st // FGetAvailableLeverage gets available leverage data for futures func (h *HUOBI) FGetAvailableLeverage(ctx context.Context, symbol currency.Code) (FAvailableLeverageData, error) { var resp FAvailableLeverageData - req := make(map[string]interface{}) + req := make(map[string]any) if !symbol.IsEmpty() { codeValue, err := h.formatFuturesCode(symbol) if err != nil { @@ -717,7 +717,7 @@ func (h *HUOBI) FGetAvailableLeverage(ctx context.Context, symbol currency.Code) // FOrder places an order for futures func (h *HUOBI) FOrder(ctx context.Context, contractCode currency.Pair, symbol, contractType, clientOrderID, direction, offset, orderPriceType string, price, volume, leverageRate float64) (FOrderData, error) { var resp FOrderData - req := make(map[string]interface{}) + req := make(map[string]any) if symbol != "" { req["symbol"] = symbol } @@ -762,7 +762,7 @@ func (h *HUOBI) FOrder(ctx context.Context, contractCode currency.Pair, symbol, // FPlaceBatchOrder places a batch of orders for futures func (h *HUOBI) FPlaceBatchOrder(ctx context.Context, data []fBatchOrderData) (FBatchOrderResponse, error) { var resp FBatchOrderResponse - req := make(map[string]interface{}) + req := make(map[string]any) if len(data) > 10 || len(data) == 0 { return resp, errors.New("invalid data provided: maximum of 10 batch orders supported") } @@ -797,7 +797,7 @@ func (h *HUOBI) FPlaceBatchOrder(ctx context.Context, data []fBatchOrderData) (F // FCancelOrder cancels a futures order func (h *HUOBI) FCancelOrder(ctx context.Context, baseCurrency currency.Code, orderID, clientOrderID string) (FCancelOrderData, error) { var resp FCancelOrderData - req := make(map[string]interface{}) + req := make(map[string]any) if baseCurrency.IsEmpty() { return resp, fmt.Errorf("cannot cancel futures order %w", currency.ErrCurrencyCodeEmpty) } @@ -814,7 +814,7 @@ func (h *HUOBI) FCancelOrder(ctx context.Context, baseCurrency currency.Code, or // FCancelAllOrders cancels all futures order for a given symbol func (h *HUOBI) FCancelAllOrders(ctx context.Context, contractCode currency.Pair, symbol, contractType string) (FCancelOrderData, error) { var resp FCancelOrderData - req := make(map[string]interface{}) + req := make(map[string]any) if symbol != "" { req["symbol"] = symbol } @@ -837,7 +837,7 @@ func (h *HUOBI) FCancelAllOrders(ctx context.Context, contractCode currency.Pair // FFlashCloseOrder flash closes a futures order func (h *HUOBI) FFlashCloseOrder(ctx context.Context, contractCode currency.Pair, symbol, contractType, direction, orderPriceType, clientOrderID string, volume float64) (FOrderData, error) { var resp FOrderData - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol if t := strings.ToLower(contractType); t != "" { if _, ok := contractExpiryNames[t]; !ok { @@ -869,7 +869,7 @@ func (h *HUOBI) FFlashCloseOrder(ctx context.Context, contractCode currency.Pair // FGetOrderInfo gets order info for futures func (h *HUOBI) FGetOrderInfo(ctx context.Context, symbol, clientOrderID, orderID string) (FOrderInfo, error) { var resp FOrderInfo - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol if orderID != "" { req["order_id"] = orderID @@ -883,7 +883,7 @@ func (h *HUOBI) FGetOrderInfo(ctx context.Context, symbol, clientOrderID, orderI // FOrderDetails gets order details for futures orders func (h *HUOBI) FOrderDetails(ctx context.Context, symbol, orderID, orderType string, createdAt time.Time, pageIndex, pageSize int64) (FOrderDetailsData, error) { var resp FOrderDetailsData - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol req["order_id"] = orderID req["created_at"] = strconv.FormatInt(createdAt.Unix(), 10) @@ -904,7 +904,7 @@ func (h *HUOBI) FOrderDetails(ctx context.Context, symbol, orderID, orderType st // FGetOpenOrders gets order details for futures orders func (h *HUOBI) FGetOpenOrders(ctx context.Context, symbol currency.Code, pageIndex, pageSize int64) (FOpenOrdersData, error) { var resp FOpenOrdersData - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol if pageIndex != 0 { req["page_index"] = pageIndex @@ -918,7 +918,7 @@ func (h *HUOBI) FGetOpenOrders(ctx context.Context, symbol currency.Code, pageIn // FGetOrderHistory gets order history for futures func (h *HUOBI) FGetOrderHistory(ctx context.Context, contractCode currency.Pair, symbol, tradeType, reqType, orderType string, status []order.Status, createDate, pageIndex, pageSize int64) (FOrderHistoryData, error) { var resp FOrderHistoryData - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol tType, ok := validFuturesTradeType[tradeType] if !ok { @@ -977,7 +977,7 @@ func (h *HUOBI) FGetOrderHistory(ctx context.Context, contractCode currency.Pair // FTradeHistory gets trade history data for futures func (h *HUOBI) FTradeHistory(ctx context.Context, contractCode currency.Pair, symbol, tradeType string, createDate, pageIndex, pageSize int64) (FOrderHistoryData, error) { var resp FOrderHistoryData - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol tType, ok := validTradeType[tradeType] if !ok { @@ -1007,7 +1007,7 @@ func (h *HUOBI) FTradeHistory(ctx context.Context, contractCode currency.Pair, s // FPlaceTriggerOrder places a trigger order for futures func (h *HUOBI) FPlaceTriggerOrder(ctx context.Context, contractCode currency.Pair, symbol, contractType, triggerType, orderPriceType, direction, offset string, triggerPrice, orderPrice, volume, leverageRate float64) (FTriggerOrderData, error) { var resp FTriggerOrderData - req := make(map[string]interface{}) + req := make(map[string]any) if symbol != "" { req["symbol"] = symbol } @@ -1048,7 +1048,7 @@ func (h *HUOBI) FPlaceTriggerOrder(ctx context.Context, contractCode currency.Pa // FCancelTriggerOrder cancels trigger order for futures func (h *HUOBI) FCancelTriggerOrder(ctx context.Context, symbol, orderID string) (FCancelOrderData, error) { var resp FCancelOrderData - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol req["order_id"] = orderID return resp, h.FuturesAuthenticatedHTTPRequest(ctx, exchange.RestFutures, http.MethodPost, fCancelTriggerOrder, nil, req, &resp) @@ -1057,7 +1057,7 @@ func (h *HUOBI) FCancelTriggerOrder(ctx context.Context, symbol, orderID string) // FCancelAllTriggerOrders cancels all trigger order for futures func (h *HUOBI) FCancelAllTriggerOrders(ctx context.Context, contractCode currency.Pair, symbol, contractType string) (FCancelOrderData, error) { var resp FCancelOrderData - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol if !contractCode.IsEmpty() { codeValue, err := h.FormatSymbol(contractCode, asset.Futures) @@ -1078,7 +1078,7 @@ func (h *HUOBI) FCancelAllTriggerOrders(ctx context.Context, contractCode curren // FQueryTriggerOpenOrders queries open trigger orders for futures func (h *HUOBI) FQueryTriggerOpenOrders(ctx context.Context, contractCode currency.Pair, symbol string, pageIndex, pageSize int64) (FTriggerOpenOrders, error) { var resp FTriggerOpenOrders - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol if !contractCode.IsEmpty() { codeValue, err := h.FormatSymbol(contractCode, asset.Futures) @@ -1099,7 +1099,7 @@ func (h *HUOBI) FQueryTriggerOpenOrders(ctx context.Context, contractCode curren // FQueryTriggerOrderHistory queries trigger order history for futures func (h *HUOBI) FQueryTriggerOrderHistory(ctx context.Context, contractCode currency.Pair, symbol, tradeType, status string, createDate, pageIndex, pageSize int64) (FTriggerOrderHistoryData, error) { var resp FTriggerOrderHistoryData - req := make(map[string]interface{}) + req := make(map[string]any) req["symbol"] = symbol if !contractCode.IsEmpty() { codeValue, err := h.FormatSymbol(contractCode, asset.Futures) @@ -1134,7 +1134,7 @@ func (h *HUOBI) FQueryTriggerOrderHistory(ctx context.Context, contractCode curr } // FuturesAuthenticatedHTTPRequest sends authenticated requests to the HUOBI API -func (h *HUOBI) FuturesAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, data, result interface{}) error { +func (h *HUOBI) FuturesAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, data, result any) error { creds, err := h.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/huobi/huobi_test.go b/exchanges/huobi/huobi_test.go index dc386615..84d162e3 100644 --- a/exchanges/huobi/huobi_test.go +++ b/exchanges/huobi/huobi_test.go @@ -48,7 +48,6 @@ const ( var ( h = &HUOBI{} - wsSetupRan bool btcFutureDatedPair currency.Pair btccwPair = currency.NewPair(currency.BTC, currency.NewCode("CW")) btcusdPair = currency.NewPairWithDelimiter("BTC", "USD", "-") diff --git a/exchanges/huobi/huobi_types.go b/exchanges/huobi/huobi_types.go index 149ea262..7ea1298b 100644 --- a/exchanges/huobi/huobi_types.go +++ b/exchanges/huobi/huobi_types.go @@ -7,12 +7,12 @@ import ( ) type errorCapture struct { - Status string `json:"status"` - CodeType1 interface{} `json:"err-code"` // can be either a string or int depending on the endpoint - ErrMsgType1 string `json:"err-msg"` - CodeType2 interface{} `json:"err_code"` - ErrMsgType2 string `json:"err_msg"` - Timestamp types.Time `json:"ts"` + Status string `json:"status"` + CodeType1 any `json:"err-code"` // can be either a string or int depending on the endpoint + ErrMsgType1 string `json:"err-msg"` + CodeType2 any `json:"err_code"` + ErrMsgType2 string `json:"err_msg"` + Timestamp types.Time `json:"ts"` } // MarketSummary24Hr stores past 24hr market summary data of a given symbol @@ -824,10 +824,10 @@ type WsDepth struct { Channel string `json:"ch"` Timestamp types.Time `json:"ts"` Tick struct { - Bids [][]interface{} `json:"bids"` - Asks [][]interface{} `json:"asks"` - Timestamp types.Time `json:"ts"` - Version int64 `json:"version"` + Bids [][]any `json:"bids"` + Asks [][]any `json:"asks"` + Timestamp types.Time `json:"ts"` + Version int64 `json:"version"` } `json:"tick"` } diff --git a/exchanges/huobi/huobi_websocket.go b/exchanges/huobi/huobi_websocket.go index a7bc52bb..db4347f2 100644 --- a/exchanges/huobi/huobi_websocket.go +++ b/exchanges/huobi/huobi_websocket.go @@ -53,11 +53,6 @@ const ( wsUnsubOp = "unsub" ) -var ( - errInvalidChannel = errors.New("invalid channel format") - errParsingMsg = errors.New("error parsing message") -) - var defaultSubscriptions = subscription.List{ {Enabled: true, Asset: asset.Spot, Channel: subscription.TickerChannel}, {Enabled: true, Asset: asset.Spot, Channel: subscription.CandlesChannel, Interval: kline.OneMin}, @@ -675,7 +670,7 @@ func getErrResp(msg []byte) error { return nil } if err != nil { - return fmt.Errorf("%w: %w", errParsingMsg, err) + return fmt.Errorf("%w 'code': %w from message: %s", common.ErrParsingWSField, err, msg) } errCode = strconv.Itoa(int(errCodeInt)) errMsg, _ = jsonparser.GetString(msg, "message") diff --git a/exchanges/kraken/kraken.go b/exchanges/kraken/kraken.go index ee09f69a..916e0c29 100644 --- a/exchanges/kraken/kraken.go +++ b/exchanges/kraken/kraken.go @@ -196,14 +196,14 @@ func (k *Kraken) GetOHLC(ctx context.Context, symbol currency.Pair, interval str return nil, err } - ohlcData, ok := result[translatedAsset].([]interface{}) + ohlcData, ok := result[translatedAsset].([]any) if !ok { return nil, errors.New("invalid data returned") } OHLC := make([]OpenHighLowClose, len(ohlcData)) for x := range ohlcData { - subData, ok := ohlcData[x].([]interface{}) + subData, ok := ohlcData[x].([]any) if !ok { return nil, errors.New("unable to type assert subData") } @@ -304,15 +304,15 @@ func (k *Kraken) GetTrades(ctx context.Context, symbol currency.Pair) ([]RecentT return nil, err } - trades, ok := data[translatedAsset].([]interface{}) + trades, ok := data[translatedAsset].([]any) if !ok { return nil, fmt.Errorf("no data returned for symbol %v", symbol) } - var individualTrade []interface{} + var individualTrade []any recentTrades := make([]RecentTrades, len(trades)) for x := range trades { - individualTrade, ok = trades[x].([]interface{}) + individualTrade, ok = trades[x].([]any) if !ok { return nil, errors.New("unable to parse individual trade data") } @@ -385,14 +385,14 @@ func (k *Kraken) GetSpread(ctx context.Context, symbol currency.Pair) ([]Spread, return nil, fmt.Errorf("unable to find %s in spread data", symbolValue) } - spreadData, ok := data.([]interface{}) + spreadData, ok := data.([]any) if !ok { return nil, errors.New("unable to type assert spreadData") } peanutButter := make([]Spread, len(spreadData)) for x := range spreadData { - subData, ok := spreadData[x].([]interface{}) + subData, ok := spreadData[x].([]any) if !ok { return nil, errors.New("unable to type assert subData") } @@ -816,7 +816,7 @@ func (k *Kraken) CancelExistingOrder(ctx context.Context, txid string) (*CancelO } // SendHTTPRequest sends an unauthenticated HTTP requests -func (k *Kraken) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error { +func (k *Kraken) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { endpoint, err := k.API.Endpoints.GetURL(ep) if err != nil { return err @@ -864,7 +864,7 @@ func (k *Kraken) SendHTTPRequest(ctx context.Context, ep exchange.URL, path stri } // SendAuthenticatedHTTPRequest sends an authenticated HTTP request -func (k *Kraken) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method string, params url.Values, result interface{}) error { +func (k *Kraken) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method string, params url.Values, result any) error { creds, err := k.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/kraken/kraken_futures.go b/exchanges/kraken/kraken_futures.go index a59b8159..699cee13 100644 --- a/exchanges/kraken/kraken_futures.go +++ b/exchanges/kraken/kraken_futures.go @@ -126,7 +126,7 @@ func (k *Kraken) FuturesBatchOrder(ctx context.Context, data []PlaceBatchOrderDa data[x].Symbol = formattedPair.String() } - req := make(map[string]interface{}) + req := make(map[string]any) req["batchOrder"] = data jsonData, err := json.Marshal(req) @@ -230,7 +230,7 @@ func (k *Kraken) FuturesGetFills(ctx context.Context, lastFillTime time.Time) (F // FuturesTransfer transfers funds between accounts func (k *Kraken) FuturesTransfer(ctx context.Context, fromAccount, toAccount, unit string, amount float64) (FuturesTransferData, error) { var resp FuturesTransferData - req := make(map[string]interface{}) + req := make(map[string]any) req["fromAccount"] = fromAccount req["toAccount"] = toAccount req["unit"] = unit @@ -333,7 +333,7 @@ func (k *Kraken) signFuturesRequest(secret, endpoint, nonce, data string) (strin } // SendFuturesAuthRequest will send an auth req -func (k *Kraken) SendFuturesAuthRequest(ctx context.Context, method, path string, data url.Values, result interface{}) error { +func (k *Kraken) SendFuturesAuthRequest(ctx context.Context, method, path string, data url.Values, result any) error { creds, err := k.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/kraken/kraken_test.go b/exchanges/kraken/kraken_test.go index 8a6cde39..0bd2bb24 100644 --- a/exchanges/kraken/kraken_test.go +++ b/exchanges/kraken/kraken_test.go @@ -1232,7 +1232,7 @@ func TestWSProcessTrades(t *testing.T) { testexch.FixtureToDataHandler(t, "testdata/wsAllTrades.json", k.wsHandleData) close(k.Websocket.DataHandler) - invalid := []any{"trades", []any{[]interface{}{"95873.80000", "0.00051182", "1708731380.3791859"}}} + invalid := []any{"trades", []any{[]any{"95873.80000", "0.00051182", "1708731380.3791859"}}} pair := currency.NewPair(currency.XBT, currency.USD) err = k.wsProcessTrades(invalid, pair) require.ErrorContains(t, err, "unexpected trade data length") diff --git a/exchanges/kraken/kraken_types.go b/exchanges/kraken/kraken_types.go index 952e3200..772f193b 100644 --- a/exchanges/kraken/kraken_types.go +++ b/exchanges/kraken/kraken_types.go @@ -185,7 +185,7 @@ type RecentTrades struct { Time float64 BuyOrSell string MarketOrLimit string - Miscellaneous interface{} + Miscellaneous any TradeID int64 } @@ -409,10 +409,10 @@ type WithdrawInformation struct { // DepositMethods Used to check deposit fees type DepositMethods struct { - Method string `json:"method"` - Limit interface{} `json:"limit"` // If no limit amount, this comes back as boolean - Fee float64 `json:"fee,string"` - AddressSetupFee float64 `json:"address-setup-fee,string"` + Method string `json:"method"` + Limit any `json:"limit"` // If no limit amount, this comes back as boolean + Fee float64 `json:"fee,string"` + AddressSetupFee float64 `json:"address-setup-fee,string"` } // OrderDescription represents an orders description @@ -436,8 +436,8 @@ type AddOrderOptions struct { // CancelOrderResponse type type CancelOrderResponse struct { - Count int64 `json:"count"` - Pending interface{} `json:"pending"` + Count int64 `json:"count"` + Pending any `json:"pending"` } // DepositFees the large list of predefined deposit fees @@ -479,10 +479,10 @@ var WithdrawalFees = map[currency.Code]float64{ // DepositAddress defines a deposit address type DepositAddress struct { - Address string `json:"address"` - ExpireTime interface{} `json:"expiretm"` // this is an int when new is specified - Tag string `json:"tag"` - New bool `json:"new"` + Address string `json:"address"` + ExpireTime any `json:"expiretm"` // this is an int when new is specified + Tag string `json:"tag"` + New bool `json:"new"` } // WithdrawStatusResponse defines a withdrawal status response @@ -504,7 +504,7 @@ type WebsocketSubRequest struct { Event string `json:"event"` RequestID int64 `json:"reqid,omitempty"` Pairs []string `json:"pair,omitempty"` - Subscription WebsocketSubscriptionData `json:"subscription,omitempty"` + Subscription WebsocketSubscriptionData `json:"subscription"` } // WebsocketSubscriptionData contains details on WS channel @@ -519,9 +519,9 @@ type WebsocketSubscriptionData struct { type WebsocketEventResponse struct { Event string `json:"event"` Status string `json:"status"` - Pair currency.Pair `json:"pair,omitempty"` + Pair currency.Pair `json:"pair"` RequestID int64 `json:"reqid,omitempty"` - Subscription WebsocketSubscriptionResponseData `json:"subscription,omitempty"` + Subscription WebsocketSubscriptionResponseData `json:"subscription"` ChannelName string `json:"channelName,omitempty"` WebsocketSubscriptionEventResponse WebsocketErrorResponse @@ -723,7 +723,7 @@ func (e *errorResponse) UnmarshalJSON(data []byte) error { } else { e.warnings = append(e.warnings, d) } - case []interface{}: + case []any: for x := range d { errStr, ok := d[x].(string) if !ok { diff --git a/exchanges/kraken/kraken_websocket.go b/exchanges/kraken/kraken_websocket.go index ea2f3925..a21f1b42 100644 --- a/exchanges/kraken/kraken_websocket.go +++ b/exchanges/kraken/kraken_websocket.go @@ -292,8 +292,8 @@ func (k *Kraken) wsProcessSystemStatus(respRaw []byte) error { return nil } -func (k *Kraken) wsProcessOwnTrades(ownOrders interface{}) error { - if data, ok := ownOrders.([]interface{}); ok { +func (k *Kraken) wsProcessOwnTrades(ownOrders any) error { + if data, ok := ownOrders.([]any); ok { for i := range data { trades, err := json.Marshal(data[i]) if err != nil { @@ -343,8 +343,8 @@ func (k *Kraken) wsProcessOwnTrades(ownOrders interface{}) error { return errors.New(k.Name + " - Invalid own trades data") } -func (k *Kraken) wsProcessOpenOrders(ownOrders interface{}) error { - if data, ok := ownOrders.([]interface{}); ok { +func (k *Kraken) wsProcessOpenOrders(ownOrders any) error { + if data, ok := ownOrders.([]any); ok { for i := range data { orders, err := json.Marshal(data[i]) if err != nil { @@ -541,7 +541,7 @@ func (k *Kraken) wsProcessTrades(response []any, pair currency.Pair) error { } trades := make([]trade.Data, len(data)) for i := range data { - t, ok := data[i].([]interface{}) + t, ok := data[i].([]any) if !ok { return errors.New("unidentified trade data received") } @@ -642,8 +642,8 @@ func (k *Kraken) wsProcessOrderBook(c string, response []any, pair currency.Pair } // NOTE: Updates are a priority so check if it's an update first as we don't // need multiple map lookups to check for snapshot. - askData, asksExist := ob["a"].([]interface{}) - bidData, bidsExist := ob["b"].([]interface{}) + askData, asksExist := ob["a"].([]any) + bidData, bidsExist := ob["b"].([]any) if asksExist || bidsExist { checksum, ok := ob["c"].(string) if !ok { @@ -662,8 +662,8 @@ func (k *Kraken) wsProcessOrderBook(c string, response []any, pair currency.Pair return err } - askSnapshot, askSnapshotExists := ob["as"].([]interface{}) - bidSnapshot, bidSnapshotExists := ob["bs"].([]interface{}) + askSnapshot, askSnapshotExists := ob["as"].([]any) + bidSnapshot, bidSnapshotExists := ob["bs"].([]any) if !askSnapshotExists && !bidSnapshotExists { return fmt.Errorf("%w for %v %v", errNoWebsocketOrderbookData, pair, asset.Spot) } @@ -687,9 +687,9 @@ func (k *Kraken) wsProcessOrderBookPartial(pair currency.Pair, askData, bidData // to respect both within a reasonable degree var highestLastUpdate time.Time for i := range askData { - asks, ok := askData[i].([]interface{}) + asks, ok := askData[i].([]any) if !ok { - return common.GetTypeAssertError("[]interface{}", askData[i], "asks") + return common.GetTypeAssertError("[]any", askData[i], "asks") } if len(asks) < 3 { return errors.New("unexpected asks length") @@ -731,9 +731,9 @@ func (k *Kraken) wsProcessOrderBookPartial(pair currency.Pair, askData, bidData } for i := range bidData { - bids, ok := bidData[i].([]interface{}) + bids, ok := bidData[i].([]any) if !ok { - return common.GetTypeAssertError("[]interface{}", bidData[i], "bids") + return common.GetTypeAssertError("[]any", bidData[i], "bids") } if len(bids) < 3 { return errors.New("unexpected bids length") @@ -796,7 +796,7 @@ func (k *Kraken) wsProcessOrderBookUpdate(pair currency.Pair, askData, bidData [ var highestLastUpdate time.Time // Ask data is not always sent for i := range askData { - asks, ok := askData[i].([]interface{}) + asks, ok := askData[i].([]any) if !ok { return errors.New("asks type assertion failure") } @@ -846,9 +846,9 @@ func (k *Kraken) wsProcessOrderBookUpdate(pair currency.Pair, askData, bidData [ // Bid data is not always sent for i := range bidData { - bids, ok := bidData[i].([]interface{}) + bids, ok := bidData[i].([]any) if !ok { - return common.GetTypeAssertError("[]interface{}", bidData[i], "bids") + return common.GetTypeAssertError("[]any", bidData[i], "bids") } priceStr, ok := bids[0].(string) diff --git a/exchanges/kucoin/kucoin.go b/exchanges/kucoin/kucoin.go index c5f43986..64e13624 100644 --- a/exchanges/kucoin/kucoin.go +++ b/exchanges/kucoin/kucoin.go @@ -1092,7 +1092,7 @@ func (ku *Kucoin) PostStopOrder(ctx context.Context, clientOID, side, symbol, or if symbol == "" { return "", currency.ErrSymbolStringEmpty } - arg := make(map[string]interface{}) + arg := make(map[string]any) arg["clientOid"] = clientOID arg["side"] = strings.ToLower(side) arg["symbol"] = symbol @@ -2377,7 +2377,7 @@ func (ku *Kucoin) ModifySubscriptionOrder(ctx context.Context, ccy currency.Code if purchaseOrderNo == "" { return nil, errMissingPurchaseOrderNumber } - arg := map[string]interface{}{ + arg := map[string]any{ "currency": ccy.String(), "interestRate": interestRate, "purchaseOrderNo": purchaseOrderNo, @@ -2436,7 +2436,7 @@ func (ku *Kucoin) GetSubscriptionOrders(ctx context.Context, ccy currency.Code, } // SendHTTPRequest sends an unauthenticated HTTP request -func (ku *Kucoin) SendHTTPRequest(ctx context.Context, ePath exchange.URL, epl request.EndpointLimit, path string, result interface{}) error { +func (ku *Kucoin) SendHTTPRequest(ctx context.Context, ePath exchange.URL, epl request.EndpointLimit, path string, result any) error { value := reflect.ValueOf(result) if value.Kind() != reflect.Pointer { return errInvalidResultInterface @@ -2470,7 +2470,7 @@ func (ku *Kucoin) SendHTTPRequest(ctx context.Context, ePath exchange.URL, epl r // SendAuthHTTPRequest sends an authenticated HTTP request // Request parameters are added to path variable for GET and DELETE request and for other requests its passed in params variable -func (ku *Kucoin) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, epl request.EndpointLimit, method, path string, arg, result interface{}) error { +func (ku *Kucoin) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, epl request.EndpointLimit, method, path string, arg, result any) error { value := reflect.ValueOf(result) if value.Kind() != reflect.Pointer { return errInvalidResultInterface @@ -2622,7 +2622,7 @@ func (ku *Kucoin) SubscribeToEarnFixedIncomeProduct(ctx context.Context, product } var resp *SusbcribeEarn return resp, ku.SendAuthHTTPRequest(ctx, exchange.RestSpot, subscribeToEarnEPL, http.MethodPost, "/v1/earn/orders", - &map[string]interface{}{ + &map[string]any{ "productId": productID, "accountType": accountType, "amount,string": amount, diff --git a/exchanges/kucoin/kucoin_convert.go b/exchanges/kucoin/kucoin_convert.go index 807c4ef9..7bfb3729 100644 --- a/exchanges/kucoin/kucoin_convert.go +++ b/exchanges/kucoin/kucoin_convert.go @@ -9,7 +9,7 @@ import ( // UnmarshalJSON valid data to SubAccountsResponse of return nil if the data is empty list. // this is added to handle the empty list returned when there are no accounts. func (a *SubAccountsResponse) UnmarshalJSON(data []byte) error { - var result interface{} + var result any err := json.Unmarshal(data, &result) if err != nil { return err @@ -20,7 +20,7 @@ func (a *SubAccountsResponse) UnmarshalJSON(data []byte) error { return errNoValidResponseFromServer } return nil - } else if _, ok := result.([]interface{}); ok { + } else if _, ok := result.([]any); ok { return nil } return fmt.Errorf("%w can not unmarshal to SubAccountsResponse", errMalformedData) diff --git a/exchanges/kucoin/kucoin_futures.go b/exchanges/kucoin/kucoin_futures.go index 9d9acfe0..62c8dc9d 100644 --- a/exchanges/kucoin/kucoin_futures.go +++ b/exchanges/kucoin/kucoin_futures.go @@ -622,7 +622,7 @@ func (ku *Kucoin) SetAutoDepositMargin(ctx context.Context, symbol string, statu if symbol == "" { return false, currency.ErrSymbolStringEmpty } - params := make(map[string]interface{}) + params := make(map[string]any) params["symbol"] = symbol params["status"] = status var resp bool @@ -658,7 +658,7 @@ func (ku *Kucoin) AddMargin(ctx context.Context, symbol, uniqueID string, margin if symbol == "" { return nil, currency.ErrSymbolStringEmpty } - params := make(map[string]interface{}) + params := make(map[string]any) params["symbol"] = symbol if uniqueID == "" { return nil, errors.New("uniqueID cannot be empty") @@ -686,7 +686,7 @@ func (ku *Kucoin) FuturesUpdateRiskLmitLevel(ctx context.Context, symbol string, if symbol == "" { return false, currency.ErrSymbolStringEmpty } - params := make(map[string]interface{}) + params := make(map[string]any) params["symbol"] = symbol params["level"] = strconv.FormatInt(level, 10) var resp bool @@ -765,7 +765,7 @@ func (ku *Kucoin) CreateFuturesSubAccountAPIKey(ctx context.Context, ipWhitelist if passphrase == "" { return nil, errInvalidPassPhraseInstance } - params := make(map[string]interface{}) + params := make(map[string]any) params["passphrase"] = passphrase params["remark"] = remark params["subName"] = subName @@ -790,7 +790,7 @@ func (ku *Kucoin) TransferFuturesFundsToMainAccount(ctx context.Context, amount if recAccountType == "" { return nil, fmt.Errorf("%w, invalid receive account type", errAccountTypeMissing) } - params := make(map[string]interface{}) + params := make(map[string]any) params["amount"] = amount params["currency"] = ccy.String() params["recAccountType"] = recAccountType @@ -809,7 +809,7 @@ func (ku *Kucoin) TransferFundsToFuturesAccount(ctx context.Context, amount floa if payAccountType == "" { return fmt.Errorf("%w, payAccountType cannot be empty", errAccountTypeMissing) } - params := make(map[string]interface{}) + params := make(map[string]any) params["amount"] = amount params["currency"] = ccy.String() params["payAccountType"] = payAccountType diff --git a/exchanges/kucoin/kucoin_types.go b/exchanges/kucoin/kucoin_types.go index 986decba..f55dbe8a 100644 --- a/exchanges/kucoin/kucoin_types.go +++ b/exchanges/kucoin/kucoin_types.go @@ -1773,7 +1773,7 @@ type IsolatedMarginBorrowing struct { // Response represents response model and implements UnmarshalTo interface type Response struct { - Data interface{} `json:"data"` + Data any `json:"data"` Error } diff --git a/exchanges/kucoin/kucoin_websocket.go b/exchanges/kucoin/kucoin_websocket.go index 7d630d8b..bc73c5c9 100644 --- a/exchanges/kucoin/kucoin_websocket.go +++ b/exchanges/kucoin/kucoin_websocket.go @@ -344,7 +344,7 @@ func (ku *Kucoin) wsHandleData(respData []byte) error { } // processData used to deserialize and forward the data to DataHandler. -func (ku *Kucoin) processData(respData []byte, resp interface{}) error { +func (ku *Kucoin) processData(respData []byte, resp any) error { if err := json.Unmarshal(respData, &resp); err != nil { return err } diff --git a/exchanges/lbank/lbank.go b/exchanges/lbank/lbank.go index 068e7ba9..7ff03da3 100644 --- a/exchanges/lbank/lbank.go +++ b/exchanges/lbank/lbank.go @@ -475,7 +475,7 @@ func ErrorCapture(code int64) error { } // SendHTTPRequest sends an unauthenticated HTTP request -func (l *Lbank) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error { +func (l *Lbank) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { endpoint, err := l.API.Endpoints.GetURL(ep) if err != nil { return err @@ -545,7 +545,7 @@ func (l *Lbank) sign(data string) (string, error) { } // SendAuthHTTPRequest sends an authenticated request -func (l *Lbank) SendAuthHTTPRequest(ctx context.Context, method, endpoint string, vals url.Values, result interface{}) error { +func (l *Lbank) SendAuthHTTPRequest(ctx context.Context, method, endpoint string, vals url.Values, result any) error { creds, err := l.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/lbank/lbank_types.go b/exchanges/lbank/lbank_types.go index 62b5d945..b13309b1 100644 --- a/exchanges/lbank/lbank_types.go +++ b/exchanges/lbank/lbank_types.go @@ -26,8 +26,8 @@ type TickerResponse struct { // MarketDepthResponse stores arrays for asks, bids and a timestamp for a currency pair type MarketDepthResponse struct { - ErrCapture `json:",omitempty"` - Data struct { + ErrCapture + Data struct { Asks [][2]string `json:"asks"` Bids [][2]string `json:"bids"` Timestamp int64 `json:"timestamp"` @@ -62,22 +62,22 @@ type InfoResponse struct { // InfoFinalResponse stores info type InfoFinalResponse struct { - ErrCapture `json:",omitempty"` - Info InfoResponse `json:"info"` + ErrCapture + Info InfoResponse `json:"info"` } // CreateOrderResponse stores the result of the Order and type CreateOrderResponse struct { - ErrCapture `json:",omitempty"` - OrderID string `json:"order_id"` + ErrCapture + OrderID string `json:"order_id"` } // RemoveOrderResponse stores the result when an order is cancelled type RemoveOrderResponse struct { - ErrCapture `json:",omitempty"` - Err string `json:"error"` - OrderID string `json:"order_id"` - Success string `json:"success"` + ErrCapture + Err string `json:"error"` + OrderID string `json:"order_id"` + Success string `json:"success"` } // OrderResponse stores the data related to the given OrderIDs @@ -95,8 +95,8 @@ type OrderResponse struct { // QueryOrderResponse stores the data from queries type QueryOrderResponse struct { - ErrCapture `json:",omitempty"` - Orders json.RawMessage `json:"orders"` + ErrCapture + Orders json.RawMessage `json:"orders"` } // QueryOrderFinalResponse stores data from queries @@ -117,7 +117,7 @@ type OrderHistory struct { // OrderHistoryResponse stores past orders type OrderHistoryResponse struct { - ErrCapture `json:",omitempty"` + ErrCapture PageLength uint8 `json:"page_length"` Orders json.RawMessage `json:"orders"` CurrentPage uint8 `json:"current_page"` @@ -154,13 +154,13 @@ type TransactionTemp struct { // TransactionHistoryResp stores details about past transactions type TransactionHistoryResp struct { - ErrCapture `json:",omitempty"` + ErrCapture Transaction []TransactionTemp `json:"transaction"` } // OpenOrderResponse stores information about the opening orders type OpenOrderResponse struct { - ErrCapture `json:",omitempty"` + ErrCapture PageLength uint8 `json:"page_length"` PageNumber uint8 `json:"page_number"` Total string `json:"total"` @@ -191,33 +191,33 @@ type WithdrawConfigResponse struct { // WithdrawResponse stores info about the withdrawal type WithdrawResponse struct { - ErrCapture `json:",omitempty"` + ErrCapture WithdrawID string `json:"withdrawId"` Fee float64 `json:"fee"` } // RevokeWithdrawResponse stores info about the revoked withdrawal type RevokeWithdrawResponse struct { - ErrCapture `json:",omitempty"` + ErrCapture WithdrawID string `json:"string"` } // ListDataResponse contains some of withdrawal data type ListDataResponse struct { - ErrCapture `json:",omitempty"` - Amount float64 `json:"amount"` - AssetCode string `json:"assetCode"` - Address string `json:"address"` - Fee float64 `json:"fee"` - ID int64 `json:"id"` - Time int64 `json:"time"` - TXHash string `json:"txhash"` - Status string `json:"status"` + ErrCapture + Amount float64 `json:"amount"` + AssetCode string `json:"assetCode"` + Address string `json:"address"` + Fee float64 `json:"fee"` + ID int64 `json:"id"` + Time int64 `json:"time"` + TXHash string `json:"txhash"` + Status string `json:"status"` } // WithdrawalResponse stores data for withdrawals type WithdrawalResponse struct { - ErrCapture `json:",omitempty"` + ErrCapture TotalPages int64 `json:"totalPages"` PageSize int64 `json:"pageSize"` PageNo int64 `json:"pageNo"` diff --git a/exchanges/mock/common.go b/exchanges/mock/common.go index f5869fb6..d4d6ab7a 100644 --- a/exchanges/mock/common.go +++ b/exchanges/mock/common.go @@ -46,7 +46,7 @@ func DeriveURLValsFromJSONMap(payload []byte) (url.Values, error) { if len(payload) == 0 { return vals, nil } - intermediary := make(map[string]interface{}) + intermediary := make(map[string]any) err := json.Unmarshal(payload, &intermediary) if err != nil { return vals, err @@ -60,7 +60,7 @@ func DeriveURLValsFromJSONMap(payload []byte) (url.Values, error) { vals.Add(k, strconv.FormatBool(val)) case float64: vals.Add(k, strconv.FormatFloat(val, 'f', -1, 64)) - case map[string]interface{}, []interface{}, nil: + case map[string]any, []any, nil: vals.Add(k, fmt.Sprintf("%v", val)) default: log.Println(reflect.TypeOf(val)) diff --git a/exchanges/mock/recording.go b/exchanges/mock/recording.go index deb84f93..451ed611 100644 --- a/exchanges/mock/recording.go +++ b/exchanges/mock/recording.go @@ -9,6 +9,7 @@ import ( "os" "path/filepath" "reflect" + "slices" "strings" "sync" @@ -153,7 +154,7 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error { } if MatchURLVals(mockQuery, res.Request.URL.Query()) { - mockResponses = append(mockResponses[:i], mockResponses[i+1:]...) // Delete Old + mockResponses = slices.Delete(mockResponses, i, i+1) break } } @@ -179,7 +180,7 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error { if MatchURLVals(respQueryVals, mockRespVals) { // if found will delete instance and overwrite with new // data - mockResponses = append(mockResponses[:i], mockResponses[i+1:]...) + mockResponses = slices.Delete(mockResponses, i, i+1) found = true } @@ -197,7 +198,7 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error { if MatchURLVals(reqVals, mockVals) { // if found will delete instance and overwrite with new // data - mockResponses = append(mockResponses[:i], mockResponses[i+1:]...) + mockResponses = slices.Delete(mockResponses, i, i+1) found = true } case "": @@ -210,7 +211,7 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error { if MatchURLVals(mockQuery, res.Request.URL.Query()) { // if found will delete instance and overwrite with new data - mockResponses = append(mockResponses[:i], mockResponses[i+1:]...) + mockResponses = slices.Delete(mockResponses, i, i+1) found = true } @@ -285,7 +286,7 @@ func CheckResponsePayload(data []byte) ([]byte, error) { return nil, err } - var intermediary interface{} + var intermediary any err = json.Unmarshal(data, &intermediary) if err != nil { return nil, err @@ -310,13 +311,13 @@ const ( ) // CheckJSON recursively parses json data to retract keywords, quite intensive. -func CheckJSON(data interface{}, excluded *Exclusion) (interface{}, error) { - if d, ok := data.([]interface{}); ok { - var sData []interface{} +func CheckJSON(data any, excluded *Exclusion) (any, error) { + if d, ok := data.([]any); ok { + var sData []any for i := range d { v := d[i] switch v.(type) { - case map[string]interface{}, []interface{}: + case map[string]any, []any: checkedData, err := CheckJSON(v, excluded) if err != nil { return nil, err @@ -336,7 +337,7 @@ func CheckJSON(data interface{}, excluded *Exclusion) (interface{}, error) { return nil, err } - var context map[string]interface{} + var context map[string]any err = json.Unmarshal(conv, &context) if err != nil { return nil, err @@ -362,16 +363,16 @@ func CheckJSON(data interface{}, excluded *Exclusion) (interface{}, error) { context[key] = 0.0 // Zero val float } case Slice: - slice, ok := val.([]interface{}) + slice, ok := val.([]any) if !ok { - return nil, common.GetTypeAssertError("[]interface{}", val) + return nil, common.GetTypeAssertError("[]any", val) } if len(slice) < 1 { // Empty slice found context[key] = slice } else { - if _, ok := slice[0].(map[string]interface{}); ok { - var cleanSlice []interface{} + if _, ok := slice[0].(map[string]any); ok { + var cleanSlice []any for i := range slice { cleanMap, sErr := CheckJSON(slice[i], excluded) if sErr != nil { diff --git a/exchanges/mock/recording_test.go b/exchanges/mock/recording_test.go index 01de889a..be14d599 100644 --- a/exchanges/mock/recording_test.go +++ b/exchanges/mock/recording_test.go @@ -69,7 +69,7 @@ type TestStructLevel0 struct { FloatVal float64 `json:"floatVal"` IntVal int64 `json:"intVal"` StructVal TestStructLevel1 `json:"structVal"` - MixedSlice []interface{} `json:"mixedSlice"` + MixedSlice []any `json:"mixedSlice"` } type TestStructLevel1 struct { @@ -119,9 +119,9 @@ func TestCheckJSON(t *testing.T) { OtherData: level2, } - sliceOfPrimitives := []interface{}{ - []interface{}{float64(1586994000000), "6615.23000000"}, - []interface{}{float64(1586994300000), "6624.74000000"}, + sliceOfPrimitives := []any{ + []any{float64(1586994000000), "6615.23000000"}, + []any{float64(1586994300000), "6624.74000000"}, } testVal := TestStructLevel0{ @@ -187,7 +187,7 @@ func TestCheckJSON(t *testing.T) { t.Fatal("json marshal error", err) } - var newSlice []interface{} + var newSlice []any err = json.Unmarshal(payload, &newSlice) if err != nil { t.Fatal("Unmarshal error", err) diff --git a/exchanges/mock/server.go b/exchanges/mock/server.go index 820c0897..e42e62d0 100644 --- a/exchanges/mock/server.go +++ b/exchanges/mock/server.go @@ -222,7 +222,7 @@ func RegisterHandler(pattern string, mock map[string][]HTTPResponse, mux *http.S } // MessageWriteJSON writes JSON to a connection -func MessageWriteJSON(w http.ResponseWriter, status int, data interface{}) { +func MessageWriteJSON(w http.ResponseWriter, status int, data any) { w.Header().Set(contentType, applicationJSON) w.WriteHeader(status) if data != nil { @@ -252,7 +252,7 @@ func MatchAndGetResponse(mockData []HTTPResponse, requestVals url.Values, isQuer mockVals := url.Values{} var err error if json.Valid([]byte(data)) { - something := make(map[string]interface{}) + something := make(map[string]any) err = json.Unmarshal([]byte(data), &something) if err != nil { return nil, err @@ -266,7 +266,7 @@ func MatchAndGetResponse(mockData []HTTPResponse, requestVals url.Values, isQuer mockVals.Add(k, strconv.FormatBool(val)) case float64: mockVals.Add(k, strconv.FormatFloat(val, 'f', -1, 64)) - case map[string]interface{}, []interface{}, nil: + case map[string]any, []any, nil: mockVals.Add(k, fmt.Sprintf("%v", val)) default: log.Println(reflect.TypeOf(val)) diff --git a/exchanges/okx/okx_types.go b/exchanges/okx/okx_types.go index 1364acc8..785c9a7a 100644 --- a/exchanges/okx/okx_types.go +++ b/exchanges/okx/okx_types.go @@ -789,7 +789,7 @@ type PlaceOrderRequestParam struct { QuantityType string `json:"tgtCcy,omitempty"` // values base_ccy and quote_ccy // Added in the websocket requests BanAmend bool `json:"banAmend,omitempty"` // Whether the SPOT Market Order size can be amended by the system. - ExpiryTime types.Time `json:"expTime,omitempty"` + ExpiryTime types.Time `json:"expTime,omitzero"` } // OrderData response message for place, cancel, and amend an order requests. @@ -1570,8 +1570,8 @@ type ConvertCurrencyPair struct { // EstimateQuoteRequestInput represents estimate quote request parameters type EstimateQuoteRequestInput struct { - BaseCurrency currency.Code `json:"baseCcy,omitempty"` - QuoteCurrency currency.Code `json:"quoteCcy,omitempty"` + BaseCurrency currency.Code `json:"baseCcy,omitzero"` + QuoteCurrency currency.Code `json:"quoteCcy,omitzero"` Side string `json:"side,omitempty"` RFQAmount float64 `json:"rfqSz,omitempty"` RFQSzCurrency string `json:"rfqSzCcy,omitempty"` @@ -1954,7 +1954,7 @@ type SetLeverageInput struct { Leverage float64 `json:"lever,string"` // set leverage for isolated MarginMode string `json:"mgnMode"` // Margin Mode "cross" and "isolated" InstrumentID string `json:"instId,omitempty"` // Optional: - Currency currency.Code `json:"ccy,omitempty"` // Optional: + Currency currency.Code `json:"ccy,omitzero"` // Optional: PositionSide string `json:"posSide,omitempty"` AssetType asset.Item `json:"-"` @@ -2153,10 +2153,10 @@ type MaximumWithdrawal struct { // AccountRiskState represents account risk state type AccountRiskState struct { - IsTheAccountAtRisk string `json:"atRisk"` - AtRiskIdx []interface{} `json:"atRiskIdx"` // derivatives risk unit list - AtRiskMgn []interface{} `json:"atRiskMgn"` // margin risk unit list - Timestamp types.Time `json:"ts"` + IsTheAccountAtRisk string `json:"atRisk"` + AtRiskIdx []any `json:"atRiskIdx"` // derivatives risk unit list + AtRiskMgn []any `json:"atRiskMgn"` // margin risk unit list + Timestamp types.Time `json:"ts"` } // LoanBorrowAndReplayInput represents currency VIP borrow or repay request params @@ -3138,15 +3138,15 @@ type wsRequestInfo struct { } type wsIncomingData struct { - Event string `json:"event,omitempty"` - Argument SubscriptionInfo `json:"arg,omitempty"` - StatusCode string `json:"code,omitempty"` - Message string `json:"msg,omitempty"` + Event string `json:"event"` + Argument SubscriptionInfo `json:"arg"` + StatusCode string `json:"code"` + Message string `json:"msg"` // For Websocket Trading Endpoints websocket responses - ID string `json:"id,omitempty"` - Operation string `json:"op,omitempty"` - Data json.RawMessage `json:"data,omitempty"` + ID string `json:"id"` + Operation string `json:"op"` + Data json.RawMessage `json:"data"` } // copyToPlaceOrderResponse returns WSPlaceOrderResponse struct instance @@ -3169,7 +3169,7 @@ func (w *wsIncomingData) copyToPlaceOrderResponse() (*WsPlaceOrderResponse, erro } // copyResponseToInterface unmarshals the response data into the dataHolder interface. -func (w *wsIncomingData) copyResponseToInterface(dataHolder interface{}) error { +func (w *wsIncomingData) copyResponseToInterface(dataHolder any) error { rv := reflect.ValueOf(dataHolder) if rv.Kind() != reflect.Pointer { return errInvalidResponseParam diff --git a/exchanges/okx/okx_websocket.go b/exchanges/okx/okx_websocket.go index 7144f203..dc6d82d5 100644 --- a/exchanges/okx/okx_websocket.go +++ b/exchanges/okx/okx_websocket.go @@ -1519,7 +1519,7 @@ func (ok *Okx) wsProcessBlockPublicTrades(data []byte) error { } // wsProcessPushData processes push data coming through the websocket channel -func (ok *Okx) wsProcessPushData(data []byte, resp interface{}) error { +func (ok *Okx) wsProcessPushData(data []byte, resp any) error { if err := json.Unmarshal(data, resp); err != nil { return err } diff --git a/exchanges/order/orders.go b/exchanges/order/orders.go index 08190165..905e19b2 100644 --- a/exchanges/order/orders.go +++ b/exchanges/order/orders.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "reflect" + "slices" "sort" "strings" "time" @@ -971,12 +972,11 @@ func FilterOrdersByPairs(orders *[]Detail, pairs []currency.Pair) { continue } - for y := range pairs { - if (*orders)[x].Pair.EqualIncludeReciprocal(pairs[y]) { - (*orders)[target] = (*orders)[x] - target++ - break - } + if slices.ContainsFunc(pairs, func(p currency.Pair) bool { + return (*orders)[x].Pair.EqualIncludeReciprocal(p) + }) { + (*orders)[target] = (*orders)[x] + target++ } } *orders = (*orders)[:target] diff --git a/exchanges/orderbook/orderbook_test.go b/exchanges/orderbook/orderbook_test.go index f1d36701..368b501d 100644 --- a/exchanges/orderbook/orderbook_test.go +++ b/exchanges/orderbook/orderbook_test.go @@ -5,6 +5,7 @@ import ( "log" "math/rand" "os" + "slices" "strconv" "sync" "testing" @@ -570,35 +571,22 @@ func deploySliceOrdered() Tranches { } func TestReverse(t *testing.T) { - var b Base - b.VerifyOrderbook = true - - if b.Bids = deploySliceOrdered(); len(b.Bids) != 1000 { - t.Fatal("incorrect length") + b := Base{ + VerifyOrderbook: true, } - err := b.Verify() - if !errors.Is(err, errPriceOutOfOrder) { - t.Fatalf("error expected %v received %v", errPriceOutOfOrder, err) - } + b.Bids = deploySliceOrdered() + require.Len(t, b.Bids, 1000) + assert.ErrorIs(t, b.Verify(), errPriceOutOfOrder) b.Bids.Reverse() - err = b.Verify() - if err != nil { - t.Fatal(err) - } + assert.NoError(t, b.Verify()) - b.Asks = append(b.Bids[:0:0], b.Bids...) //nolint:gocritic // Short hand - err = b.Verify() - if !errors.Is(err, errPriceOutOfOrder) { - t.Fatalf("error expected %v received %v", errPriceOutOfOrder, err) - } + b.Asks = slices.Clone(b.Bids) + assert.ErrorIs(t, b.Verify(), errPriceOutOfOrder) b.Asks.Reverse() - err = b.Verify() - if err != nil { - t.Fatal(err) - } + assert.NoError(t, b.Verify()) } // 705985 1856 ns/op 0 B/op 0 allocs/op diff --git a/exchanges/orderbook/tranches.go b/exchanges/orderbook/tranches.go index a3290e51..09ce05ae 100644 --- a/exchanges/orderbook/tranches.go +++ b/exchanges/orderbook/tranches.go @@ -84,18 +84,13 @@ updates: continue } - if y < len(*ts) { - copy((*ts)[y:], (*ts)[y+1:]) - *ts = (*ts)[:len(*ts)-1] - } else { - *ts = append((*ts)[:y], (*ts)[y+1:]...) - } + copy((*ts)[y:], (*ts)[y+1:]) + *ts = (*ts)[:len(*ts)-1] + continue updates } if !bypassErr { - return fmt.Errorf("delete error: %w %d not found", - errIDCannotBeMatched, - updts[x].ID) + return fmt.Errorf("delete error: %w %d not found", errIDCannotBeMatched, updts[x].ID) } } return nil @@ -117,7 +112,9 @@ func (ts Tranches) retrieve(count int) Tranches { if count == 0 || count >= len(ts) { count = len(ts) } - return append(Tranches{}, ts[:count]...) + result := make(Tranches, count) + copy(result, ts) + return result } // updateInsertByPrice amends, inserts, moves and cleaves length of depth by diff --git a/exchanges/orderbook/tranches_test.go b/exchanges/orderbook/tranches_test.go index af3fd92c..425b5aab 100644 --- a/exchanges/orderbook/tranches_test.go +++ b/exchanges/orderbook/tranches_test.go @@ -1107,7 +1107,7 @@ func TestInsertUpdatesAsk(t *testing.T) { } // check checks depth values after an update has taken place -func Check(t *testing.T, depth interface{}, liquidity, value float64, expectedLen int) { +func Check(t *testing.T, depth any, liquidity, value float64, expectedLen int) { t.Helper() b, isBid := depth.(bidTranches) a, isAsk := depth.(askTranches) diff --git a/exchanges/poloniex/poloniex.go b/exchanges/poloniex/poloniex.go index 194c0dcf..602d98b5 100644 --- a/exchanges/poloniex/poloniex.go +++ b/exchanges/poloniex/poloniex.go @@ -80,8 +80,8 @@ func (p *Poloniex) GetTicker(ctx context.Context) (map[string]Ticker, error) { } // GetVolume returns a list of currencies with associated volume -func (p *Poloniex) GetVolume(ctx context.Context) (interface{}, error) { - var resp interface{} +func (p *Poloniex) GetVolume(ctx context.Context) (any, error) { + var resp any path := "/public?command=return24hVolume" return resp, p.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp) @@ -258,7 +258,7 @@ func (p *Poloniex) GetBalances(ctx context.Context) (Balance, error) { data, ok := result.(map[string]any) if !ok { - return Balance{}, common.GetTypeAssertError("map[string]interface{}", result, "balance result") + return Balance{}, common.GetTypeAssertError("map[string]any", result, "balance result") } balance := Balance{ @@ -296,7 +296,7 @@ func (p *Poloniex) GetCompleteBalances(ctx context.Context) (CompleteBalances, e // GetDepositAddresses returns deposit addresses for all enabled cryptos. func (p *Poloniex) GetDepositAddresses(ctx context.Context) (DepositAddresses, error) { - var result interface{} + var result any addresses := DepositAddresses{} err := p.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexDepositAddresses, url.Values{}, &result) @@ -305,9 +305,9 @@ func (p *Poloniex) GetDepositAddresses(ctx context.Context) (DepositAddresses, e } addresses.Addresses = make(map[string]string) - data, ok := result.(map[string]interface{}) + data, ok := result.(map[string]any) if !ok { - return addresses, errors.New("return val not map[string]interface{}") + return addresses, errors.New("return val not map[string]any") } for x, y := range data { @@ -424,7 +424,7 @@ func (p *Poloniex) GetAuthenticatedTradeHistory(ctx context.Context, start, end, return AuthenticatedTradeHistoryAll{}, err } - var nodata []interface{} + var nodata []any err = json.Unmarshal(result, &nodata) if err == nil { return AuthenticatedTradeHistoryAll{}, nil @@ -632,7 +632,7 @@ func (p *Poloniex) GetFeeInfo(ctx context.Context) (Fee, error) { // GetTradableBalances returns tradable balances func (p *Poloniex) GetTradableBalances(ctx context.Context) (map[string]map[string]float64, error) { type Response struct { - Data map[string]map[string]interface{} + Data map[string]map[string]any } result := Response{} @@ -712,7 +712,7 @@ func (p *Poloniex) PlaceMarginOrder(ctx context.Context, currency string, rate, } // GetMarginPosition returns a position on a margin order -func (p *Poloniex) GetMarginPosition(ctx context.Context, currency string) (interface{}, error) { +func (p *Poloniex) GetMarginPosition(ctx context.Context, currency string) (any, error) { values := url.Values{} if currency != "" && currency != "all" { @@ -901,7 +901,7 @@ func (p *Poloniex) CancelMultipleOrdersByIDs(ctx context.Context, orderIDs, clie } // SendHTTPRequest sends an unauthenticated HTTP request -func (p *Poloniex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error { +func (p *Poloniex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { endpoint, err := p.API.Endpoints.GetURL(ep) if err != nil { return err @@ -922,7 +922,7 @@ func (p *Poloniex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st } // SendAuthenticatedHTTPRequest sends an authenticated HTTP request -func (p *Poloniex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, result interface{}) error { +func (p *Poloniex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, result any) error { creds, err := p.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/poloniex/poloniex_types.go b/exchanges/poloniex/poloniex_types.go index bc27ff95..170dddde 100644 --- a/exchanges/poloniex/poloniex_types.go +++ b/exchanges/poloniex/poloniex_types.go @@ -361,11 +361,11 @@ const ( // wsCommand defines the request params after a websocket connection has been established type wsCommand struct { - Command wsOp `json:"command"` - Channel interface{} `json:"channel"` - APIKey string `json:"key,omitempty"` - Payload string `json:"payload,omitempty"` - Sign string `json:"sign,omitempty"` + Command wsOp `json:"command"` + Channel any `json:"channel"` + APIKey string `json:"key,omitempty"` + Payload string `json:"payload,omitempty"` + Sign string `json:"sign,omitempty"` } // WsTicker defines the websocket ticker response diff --git a/exchanges/poloniex/poloniex_websocket.go b/exchanges/poloniex/poloniex_websocket.go index 0a7d85d2..f9276957 100644 --- a/exchanges/poloniex/poloniex_websocket.go +++ b/exchanges/poloniex/poloniex_websocket.go @@ -116,15 +116,15 @@ func (p *Poloniex) wsReadData() { } func (p *Poloniex) wsHandleData(respRaw []byte) error { - var result interface{} + var result any err := json.Unmarshal(respRaw, &result) if err != nil { return err } - data, ok := result.([]interface{}) + data, ok := result.([]any) if !ok { - return fmt.Errorf("%w data is not []interface{}", + return fmt.Errorf("%w data is not []any", errTypeAssertionFailure) } @@ -146,17 +146,17 @@ func (p *Poloniex) wsHandleData(respRaw []byte) error { case ws24HourExchangeVolumeID, wsHeartbeat: return nil case wsAccountNotificationID: - var notificationsArray []interface{} - notificationsArray, ok = data[2].([]interface{}) + var notificationsArray []any + notificationsArray, ok = data[2].([]any) if !ok { - return fmt.Errorf("%w account notification is not a []interface{}", + return fmt.Errorf("%w account notification is not a []any", errTypeAssertionFailure) } for i := range notificationsArray { - var notification []interface{} - notification, ok = (notificationsArray[i]).([]interface{}) + var notification []any + notification, ok = (notificationsArray[i]).([]any) if !ok { - return fmt.Errorf("%w notification array element is not a []interface{}", + return fmt.Errorf("%w notification array element is not a []any", errTypeAssertionFailure) } var updateType string @@ -215,16 +215,16 @@ func (p *Poloniex) wsHandleData(respRaw []byte) error { return nil } - priceAggBook, ok := data[2].([]interface{}) + priceAggBook, ok := data[2].([]any) if !ok { - return fmt.Errorf("%w price aggregated book not []interface{}", + return fmt.Errorf("%w price aggregated book not []any", errTypeAssertionFailure) } for x := range priceAggBook { - subData, ok := priceAggBook[x].([]interface{}) + subData, ok := priceAggBook[x].([]any) if !ok { - return fmt.Errorf("%w price aggregated book element not []interface{}", + return fmt.Errorf("%w price aggregated book element not []any", errTypeAssertionFailure) } @@ -270,10 +270,10 @@ func (p *Poloniex) wsHandleData(respRaw []byte) error { return nil } -func (p *Poloniex) wsHandleTickerData(data []interface{}) error { - tickerData, ok := data[2].([]interface{}) +func (p *Poloniex) wsHandleTickerData(data []any) error { + tickerData, ok := data[2].([]any) if !ok { - return fmt.Errorf("%w ticker data is not []interface{}", + return fmt.Errorf("%w ticker data is not []any", errTypeAssertionFailure) } @@ -375,10 +375,10 @@ func (p *Poloniex) wsHandleTickerData(data []interface{}) error { // WsProcessOrderbookSnapshot processes a new orderbook snapshot into a local // of orderbooks -func (p *Poloniex) WsProcessOrderbookSnapshot(data []interface{}) error { - subDataMap, ok := data[1].(map[string]interface{}) +func (p *Poloniex) WsProcessOrderbookSnapshot(data []any) error { + subDataMap, ok := data[1].(map[string]any) if !ok { - return fmt.Errorf("%w subData element is not map[string]interface{}", + return fmt.Errorf("%w subData element is not map[string]any", errTypeAssertionFailure) } @@ -389,7 +389,7 @@ func (p *Poloniex) WsProcessOrderbookSnapshot(data []interface{}) error { pair, ok := pMap.(string) if !ok { - return fmt.Errorf("%w subData element is not map[string]interface{}", + return fmt.Errorf("%w subData element is not map[string]any", errTypeAssertionFailure) } @@ -412,9 +412,9 @@ func (p *Poloniex) WsProcessOrderbookSnapshot(data []interface{}) error { return errors.New("could not find orderbook data in map") } - ob, ok := oMap.([]interface{}) + ob, ok := oMap.([]any) if !ok { - return fmt.Errorf("%w orderbook data is not []interface{}", + return fmt.Errorf("%w orderbook data is not []any", errTypeAssertionFailure) } @@ -422,15 +422,15 @@ func (p *Poloniex) WsProcessOrderbookSnapshot(data []interface{}) error { return errNotEnoughData } - askData, ok := ob[0].(map[string]interface{}) + askData, ok := ob[0].(map[string]any) if !ok { - return fmt.Errorf("%w ask data is not map[string]interface{}", + return fmt.Errorf("%w ask data is not map[string]any", errTypeAssertionFailure) } - bidData, ok := ob[1].(map[string]interface{}) + bidData, ok := ob[1].(map[string]any) if !ok { - return fmt.Errorf("%w bid data is not map[string]interface{}", + return fmt.Errorf("%w bid data is not map[string]any", errTypeAssertionFailure) } @@ -491,7 +491,7 @@ func (p *Poloniex) WsProcessOrderbookSnapshot(data []interface{}) error { } // WsProcessOrderbookUpdate processes new orderbook updates -func (p *Poloniex) WsProcessOrderbookUpdate(sequenceNumber float64, data []interface{}, pair currency.Pair) error { +func (p *Poloniex) WsProcessOrderbookUpdate(sequenceNumber float64, data []any, pair currency.Pair) error { if len(data) < 5 { return errNotEnoughData } @@ -639,7 +639,7 @@ func (p *Poloniex) wsSendAuthorisedCommand(secret, key string, op wsOp) error { return p.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, req) } -func (p *Poloniex) processAccountMarginPosition(notification []interface{}) error { +func (p *Poloniex) processAccountMarginPosition(notification []any) error { if len(notification) < 5 { return errNotEnoughData } @@ -687,7 +687,7 @@ func (p *Poloniex) processAccountMarginPosition(notification []interface{}) erro return nil } -func (p *Poloniex) processAccountPendingOrder(notification []interface{}) error { +func (p *Poloniex) processAccountPendingOrder(notification []any) error { if len(notification) < 7 { return errNotEnoughData } @@ -755,7 +755,7 @@ func (p *Poloniex) processAccountPendingOrder(notification []interface{}) error return nil } -func (p *Poloniex) processAccountOrderUpdate(notification []interface{}) error { +func (p *Poloniex) processAccountOrderUpdate(notification []any) error { if len(notification) < 5 { return errNotEnoughData } @@ -825,7 +825,7 @@ func (p *Poloniex) processAccountOrderUpdate(notification []interface{}) error { return nil } -func (p *Poloniex) processAccountOrderLimit(notification []interface{}) error { +func (p *Poloniex) processAccountOrderLimit(notification []any) error { if len(notification) != 9 { return errNotEnoughData } @@ -916,7 +916,7 @@ func (p *Poloniex) processAccountOrderLimit(notification []interface{}) error { return nil } -func (p *Poloniex) processAccountBalanceUpdate(notification []interface{}) error { +func (p *Poloniex) processAccountBalanceUpdate(notification []any) error { if len(notification) < 4 { return errNotEnoughData } @@ -970,7 +970,7 @@ func deriveWalletType(s string) string { } } -func (p *Poloniex) processAccountTrades(notification []interface{}) error { +func (p *Poloniex) processAccountTrades(notification []any) error { if len(notification) < 11 { return errNotEnoughData } @@ -1056,7 +1056,7 @@ func (p *Poloniex) processAccountTrades(notification []interface{}) error { return nil } -func (p *Poloniex) processAccountKilledOrder(notification []interface{}) error { +func (p *Poloniex) processAccountKilledOrder(notification []any) error { if len(notification) < 3 { return errNotEnoughData } @@ -1079,7 +1079,7 @@ func (p *Poloniex) processAccountKilledOrder(notification []interface{}) error { return nil } -func (p *Poloniex) processTrades(currencyID float64, subData []interface{}) error { +func (p *Poloniex) processTrades(currencyID float64, subData []any) error { if !p.IsSaveTradeDataEnabled() { return nil } diff --git a/exchanges/request/client.go b/exchanges/request/client.go index 53647281..9193fa5f 100644 --- a/exchanges/request/client.go +++ b/exchanges/request/client.go @@ -4,6 +4,7 @@ import ( "errors" "net/http" "net/url" + "slices" "sync" "time" ) @@ -32,11 +33,11 @@ func (c *clientTracker) checkAndRegister(newClient *http.Client) error { } c.Lock() defer c.Unlock() - for x := range c.clients { - if newClient == c.clients[x] { - return errCannotReuseHTTPClient - } + + if slices.Contains(c.clients, newClient) { + return errCannotReuseHTTPClient } + c.clients = append(c.clients, newClient) return nil } diff --git a/exchanges/request/client_test.go b/exchanges/request/client_test.go index a68f7f87..83f5b8c7 100644 --- a/exchanges/request/client_test.go +++ b/exchanges/request/client_test.go @@ -4,6 +4,7 @@ import ( "errors" "net/http" "net/url" + "slices" "testing" "time" @@ -14,12 +15,7 @@ import ( func (c *clientTracker) contains(check *http.Client) bool { c.Lock() defer c.Unlock() - for x := range c.clients { - if check == c.clients[x] { - return true - } - } - return false + return slices.Contains(c.clients, check) } func TestCheckAndRegister(t *testing.T) { diff --git a/exchanges/request/limit.go b/exchanges/request/limit.go index 1a25bf41..963cbea6 100644 --- a/exchanges/request/limit.go +++ b/exchanges/request/limit.go @@ -37,7 +37,7 @@ type EndpointLimit uint16 type Weight uint8 // RateLimitDefinitions is a map of endpoint limits to rate limiters -type RateLimitDefinitions map[interface{}]*RateLimiterWithWeight +type RateLimitDefinitions map[any]*RateLimiterWithWeight // RateLimiterWithWeight is a rate limiter coupled with a weight count which // refers to the number or weighting of the request. This is used to define diff --git a/exchanges/request/request.go b/exchanges/request/request.go index db4a10b6..7ef053b5 100644 --- a/exchanges/request/request.go +++ b/exchanges/request/request.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "maps" "net/http" "net/http/httputil" "net/url" @@ -217,10 +218,7 @@ func (r *Requester) doRequest(ctx context.Context, endpoint EndpointLimit, newRe after := RetryAfter(resp, time.Now()) backoff := r.backoff(attempt) - delay := backoff - if after > backoff { - delay = after - } + delay := max(backoff, after) if dl, ok := req.Context().Deadline(); ok && dl.Before(time.Now().Add(delay)) { if err != nil { @@ -265,9 +263,7 @@ func (r *Requester) doRequest(ctx context.Context, endpoint EndpointLimit, newRe } if p.HeaderResponse != nil { - for k, v := range resp.Header { - (*p.HeaderResponse)[k] = v - } + maps.Copy(*p.HeaderResponse, resp.Header) } if resp.StatusCode < http.StatusOK || diff --git a/exchanges/request/request_test.go b/exchanges/request/request_test.go index 6001ca24..c5de115b 100644 --- a/exchanges/request/request_test.go +++ b/exchanges/request/request_test.go @@ -565,7 +565,7 @@ func TestEnableDisableRateLimit(t *testing.T) { } ctx := context.Background() - var resp interface{} + var resp any err = r.SendPayload(ctx, Auth, func() (*Item, error) { return &Item{ Method: http.MethodGet, diff --git a/exchanges/request/request_types.go b/exchanges/request/request_types.go index bf1c258f..460a4170 100644 --- a/exchanges/request/request_types.go +++ b/exchanges/request/request_types.go @@ -45,7 +45,7 @@ type Item struct { Path string Headers map[string]string Body io.Reader - Result interface{} + Result any NonceEnabled bool Verbose bool HTTPDebugging bool diff --git a/exchanges/sharedtestvalues/sharedtestvalues.go b/exchanges/sharedtestvalues/sharedtestvalues.go index 51c0e40e..d5a93d12 100644 --- a/exchanges/sharedtestvalues/sharedtestvalues.go +++ b/exchanges/sharedtestvalues/sharedtestvalues.go @@ -40,8 +40,8 @@ const ( // GetWebsocketInterfaceChannelOverride returns a new interface based channel // with the capacity set to WebsocketChannelOverrideCapacity -func GetWebsocketInterfaceChannelOverride() chan interface{} { - return make(chan interface{}, WebsocketChannelOverrideCapacity) +func GetWebsocketInterfaceChannelOverride() chan any { + return make(chan any, WebsocketChannelOverrideCapacity) } // GetWebsocketStructChannelOverride returns a new struct based channel @@ -53,8 +53,8 @@ func GetWebsocketStructChannelOverride() chan struct{} { // NewTestWebsocket returns a test websocket object func NewTestWebsocket() *stream.Websocket { w := stream.NewWebsocket() - w.DataHandler = make(chan interface{}, WebsocketChannelOverrideCapacity) - w.ToRoutine = make(chan interface{}, 1000) + w.DataHandler = make(chan any, WebsocketChannelOverrideCapacity) + w.ToRoutine = make(chan any, 1000) return w } diff --git a/exchanges/stream/buffer/buffer.go b/exchanges/stream/buffer/buffer.go index e49e793d..5cc0915b 100644 --- a/exchanges/stream/buffer/buffer.go +++ b/exchanges/stream/buffer/buffer.go @@ -34,7 +34,7 @@ var ( ) // Setup sets private variables -func (w *Orderbook) Setup(exchangeConfig *config.Exchange, c *Config, dataHandler chan<- interface{}) error { +func (w *Orderbook) Setup(exchangeConfig *config.Exchange, c *Config, dataHandler chan<- any) error { if exchangeConfig == nil { // exchange config fields are checked in stream package // prior to calling this, so further checks are not needed. return fmt.Errorf(packageError, errExchangeConfigNil) diff --git a/exchanges/stream/buffer/buffer_test.go b/exchanges/stream/buffer/buffer_test.go index bec27989..da4df937 100644 --- a/exchanges/stream/buffer/buffer_test.go +++ b/exchanges/stream/buffer/buffer_test.go @@ -54,8 +54,8 @@ func createSnapshot(pair currency.Pair, bookVerifiy ...bool) (holder *Orderbook, newBook := make(map[key.PairAsset]*orderbookHolder) - ch := make(chan interface{}) - go func(<-chan interface{}) { // reader + ch := make(chan any) + go func(<-chan any) { // reader for range ch { continue } @@ -529,7 +529,7 @@ func TestRunSnapshotWithNoData(t *testing.T) { var obl Orderbook obl.ob = make(map[key.PairAsset]*orderbookHolder) - obl.dataHandler = make(chan interface{}, 1) + obl.dataHandler = make(chan any, 1) var snapShot1 orderbook.Base snapShot1.Asset = asset.Spot snapShot1.Pair = cp @@ -546,7 +546,7 @@ func TestLoadSnapshot(t *testing.T) { require.NoError(t, err) var obl Orderbook - obl.dataHandler = make(chan interface{}, 100) + obl.dataHandler = make(chan any, 100) obl.ob = make(map[key.PairAsset]*orderbookHolder) var snapShot1 orderbook.Base snapShot1.Exchange = "SnapshotWithOverride" @@ -581,7 +581,7 @@ func TestInsertingSnapShots(t *testing.T) { require.NoError(t, err) var holder Orderbook - holder.dataHandler = make(chan interface{}, 100) + holder.dataHandler = make(chan any, 100) holder.ob = make(map[key.PairAsset]*orderbookHolder) var snapShot1 orderbook.Base snapShot1.Exchange = "WSORDERBOOKTEST1" @@ -762,7 +762,7 @@ func TestSetup(t *testing.T) { require.ErrorIs(t, err, errUnsetDataHandler) exchangeConfig.Orderbook.WebsocketBufferEnabled = true - err = w.Setup(exchangeConfig, bufferConf, make(chan interface{})) + err = w.Setup(exchangeConfig, bufferConf, make(chan any)) require.ErrorIs(t, err, errIssueBufferEnabledButNoLimit) exchangeConfig.Orderbook.WebsocketBufferLimit = 1337 @@ -771,7 +771,7 @@ func TestSetup(t *testing.T) { bufferConf.SortBuffer = true bufferConf.SortBufferByUpdateIDs = true bufferConf.UpdateEntriesByID = true - err = w.Setup(exchangeConfig, bufferConf, make(chan interface{})) + err = w.Setup(exchangeConfig, bufferConf, make(chan any)) require.NoError(t, err) if w.obBufferLimit != 1337 || @@ -963,7 +963,7 @@ func TestFlushOrderbook(t *testing.T) { require.NoError(t, err) w := &Orderbook{} - err = w.Setup(&config.Exchange{Name: "test"}, &Config{}, make(chan interface{}, 2)) + err = w.Setup(&config.Exchange{Name: "test"}, &Config{}, make(chan any, 2)) require.NoError(t, err) var snapShot1 orderbook.Base diff --git a/exchanges/stream/buffer/buffer_types.go b/exchanges/stream/buffer/buffer_types.go index 3451e413..d59e1fcd 100644 --- a/exchanges/stream/buffer/buffer_types.go +++ b/exchanges/stream/buffer/buffer_types.go @@ -35,7 +35,7 @@ type Orderbook struct { sortBufferByUpdateIDs bool // When timestamps aren't provided, an id can help sort updateEntriesByID bool // Use the update IDs to match ob entries exchangeName string - dataHandler chan<- interface{} + dataHandler chan<- any verbose bool // updateIDProgression requires that the new update ID be greater than the diff --git a/exchanges/stream/websocket.go b/exchanges/stream/websocket.go index 90ef8e6f..2a436604 100644 --- a/exchanges/stream/websocket.go +++ b/exchanges/stream/websocket.go @@ -84,8 +84,8 @@ func SetupGlobalReporter(r Reporter) { // NewWebsocket initialises the websocket struct func NewWebsocket() *Websocket { return &Websocket{ - DataHandler: make(chan interface{}, jobBuffer), - ToRoutine: make(chan interface{}, jobBuffer), + DataHandler: make(chan any, jobBuffer), + ToRoutine: make(chan any, jobBuffer), ShutdownC: make(chan struct{}), TrafficAlert: make(chan struct{}, 1), // ReadMessageErrors is buffered for an edge case when `Connect` fails diff --git a/exchanges/stream/websocket_test.go b/exchanges/stream/websocket_test.go index 60a15933..e37ef020 100644 --- a/exchanges/stream/websocket_test.go +++ b/exchanges/stream/websocket_test.go @@ -43,7 +43,7 @@ type testRequest struct { Event string `json:"event"` RequestID int64 `json:"reqid,omitempty"` Pairs []string `json:"pair"` - Subscription testRequestData `json:"subscription,omitempty"` + Subscription testRequestData `json:"subscription"` } // testRequestData contains details on WS channel @@ -96,7 +96,7 @@ func TestSetup(t *testing.T) { err := w.Setup(nil) assert.ErrorIs(t, err, errWebsocketIsNil) - w = &Websocket{DataHandler: make(chan interface{})} + w = &Websocket{DataHandler: make(chan any)} err = w.Setup(nil) assert.ErrorIs(t, err, errWebsocketSetupIsNil) @@ -1455,7 +1455,7 @@ func TestMonitorFrame(t *testing.T) { func TestMonitorData(t *testing.T) { t.Parallel() - ws := Websocket{ShutdownC: make(chan struct{}), DataHandler: make(chan interface{}, 10)} + ws := Websocket{ShutdownC: make(chan struct{}), DataHandler: make(chan any, 10)} // Handle shutdown signal close(ws.ShutdownC) require.True(t, ws.observeData(nil)) @@ -1466,7 +1466,7 @@ func TestMonitorData(t *testing.T) { require.False(t, ws.observeData(&dropped)) require.Equal(t, 1, dropped) // Handle reinstate of ToRoutine functionality which will reset dropped counter - ws.ToRoutine = make(chan interface{}, 10) + ws.ToRoutine = make(chan any, 10) go func() { ws.DataHandler <- nil }() require.False(t, ws.observeData(&dropped)) require.Empty(t, dropped) @@ -1500,7 +1500,7 @@ func TestMonitorConnection(t *testing.T) { require.False(t, ws.observeConnection(timer)) // Connect is intentionally erroring // Handle error from a connection which will then trigger a reconnect ws.setState(connectedState) - ws.DataHandler = make(chan interface{}, 1) + ws.DataHandler = make(chan any, 1) ws.ReadMessageErrors <- errConnectionFault timer = time.NewTimer(time.Second) require.False(t, ws.observeConnection(timer)) diff --git a/exchanges/stream/websocket_types.go b/exchanges/stream/websocket_types.go index 26b20f1e..c42a6b39 100644 --- a/exchanges/stream/websocket_types.go +++ b/exchanges/stream/websocket_types.go @@ -69,8 +69,8 @@ type Websocket struct { useMultiConnectionManagement bool - DataHandler chan interface{} - ToRoutine chan interface{} + DataHandler chan any + ToRoutine chan any Match *Match diff --git a/exchanges/subscription/template.go b/exchanges/subscription/template.go index d35d8a5e..69c88fa7 100644 --- a/exchanges/subscription/template.go +++ b/exchanges/subscription/template.go @@ -20,11 +20,9 @@ const ( ) var ( - errInvalidAssetExpandPairs = errors.New("subscription template containing PairSeparator with must contain either specific Asset or AssetSeparator") errAssetRecords = errors.New("subscription template did not generate the expected number of asset records") errPairRecords = errors.New("subscription template did not generate the expected number of pair records") errTooManyBatchSizePerAsset = errors.New("more than one BatchSize directive inside an AssetSeparator") - errAssetTemplateWithoutAll = errors.New("sub.Asset must be set to All if AssetSeparator is used in Channel template") errNoTemplateContent = errors.New("subscription template did not generate content") errInvalidTemplate = errors.New("GetSubscriptionTemplate did not return a template") ) diff --git a/exchanges/trade/trade.go b/exchanges/trade/trade.go index 3582e658..6dc7f153 100644 --- a/exchanges/trade/trade.go +++ b/exchanges/trade/trade.go @@ -3,6 +3,7 @@ package trade import ( "errors" "fmt" + "slices" "sort" "sync" "sync/atomic" @@ -29,7 +30,7 @@ func (p *Processor) setup(wg *sync.WaitGroup) { // Setup configures necessary fields to the `Trade` structure that govern trade data // processing. -func (t *Trade) Setup(tradeFeedEnabled bool, c chan interface{}) { +func (t *Trade) Setup(tradeFeedEnabled bool, c chan any) { t.dataHandler = c t.tradeFeedEnabled = tradeFeedEnabled } @@ -125,8 +126,7 @@ func (p *Processor) Run(wg *sync.WaitGroup) { for { <-ticker.C p.mutex.Lock() - //nolint: gocritic - bufferCopy := append(p.buffer[:0:0], p.buffer...) + bufferCopy := slices.Clone(p.buffer) p.buffer = nil p.mutex.Unlock() if len(bufferCopy) == 0 { diff --git a/exchanges/trade/trade_types.go b/exchanges/trade/trade_types.go index c80db297..a2d0a184 100644 --- a/exchanges/trade/trade_types.go +++ b/exchanges/trade/trade_types.go @@ -27,7 +27,7 @@ var ( // Trade used to hold data and methods related to trade dissemination and // storage type Trade struct { - dataHandler chan interface{} + dataHandler chan any tradeFeedEnabled bool } diff --git a/exchanges/yobit/yobit.go b/exchanges/yobit/yobit.go index ed98367a..39e71303 100644 --- a/exchanges/yobit/yobit.go +++ b/exchanges/yobit/yobit.go @@ -269,7 +269,7 @@ func (y *Yobit) RedeemCoupon(ctx context.Context, coupon string) (RedeemCoupon, } // SendHTTPRequest sends an unauthenticated HTTP request -func (y *Yobit) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error { +func (y *Yobit) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { endpoint, err := y.API.Endpoints.GetURL(ep) if err != nil { return err @@ -290,7 +290,7 @@ func (y *Yobit) SendHTTPRequest(ctx context.Context, ep exchange.URL, path strin } // SendAuthenticatedHTTPRequest sends an authenticated HTTP request to Yobit -func (y *Yobit) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, path string, params url.Values, result interface{}) (err error) { +func (y *Yobit) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, path string, params url.Values, result any) (err error) { creds, err := y.GetCredentials(ctx) if err != nil { return err diff --git a/exchanges/yobit/yobit_types.go b/exchanges/yobit/yobit_types.go index 8f5fc2da..a08deb95 100644 --- a/exchanges/yobit/yobit_types.go +++ b/exchanges/yobit/yobit_types.go @@ -4,9 +4,9 @@ import "github.com/thrasher-corp/gocryptotrader/currency" // Response is a generic struct used for exchange API request result type Response struct { - Return interface{} `json:"return"` - Success int `json:"success"` - Error string `json:"error"` + Return any `json:"return"` + Success int `json:"success"` + Error string `json:"error"` } // Info holds server time and pair information diff --git a/gctscript/modules/gct/errors.go b/gctscript/modules/gct/errors.go index fc202c88..6f4f057d 100644 --- a/gctscript/modules/gct/errors.go +++ b/gctscript/modules/gct/errors.go @@ -17,7 +17,7 @@ var ( // errorResponsef is a helper function to apply error details to a return object // for better script side error handling -func errorResponsef(format string, a ...interface{}) (objects.Object, error) { +func errorResponsef(format string, a ...any) (objects.Object, error) { if format == "" { return nil, fmt.Errorf("cannot generate tengo error object %w", errFormatStringIsEmpty) } @@ -31,7 +31,7 @@ func errorResponsef(format string, a ...interface{}) (objects.Object, error) { }, nil } -func constructRuntimeError(argPosition int, funcName, expectedType string, unexpectedData interface{}) error { +func constructRuntimeError(argPosition int, funcName, expectedType string, unexpectedData any) error { return fmt.Errorf("function [%s] argument position [%d] - %w", funcName, argPosition, diff --git a/gctscript/modules/ta/indicators/atr.go b/gctscript/modules/ta/indicators/atr.go index 2b191d31..9b16bd62 100644 --- a/gctscript/modules/ta/indicators/atr.go +++ b/gctscript/modules/ta/indicators/atr.go @@ -40,7 +40,7 @@ func atr(args ...objects.Object) (objects.Object, error) { } ohlcvInput := objects.ToInterface(args[0]) - ohlcvInputData, valid := ohlcvInput.([]interface{}) + ohlcvInputData, valid := ohlcvInput.([]any) if !valid { return nil, fmt.Errorf(modules.ErrParameterConvertFailed, OHLCV) } @@ -48,7 +48,7 @@ func atr(args ...objects.Object) (objects.Object, error) { ohlcvData := make([][]float64, 6) var allErrors []string for x := range ohlcvInputData { - t, ok := ohlcvInputData[x].([]interface{}) + t, ok := ohlcvInputData[x].([]any) if !ok { return nil, errors.New("ohlcvInputData type assert failed") } diff --git a/gctscript/modules/ta/indicators/bbands.go b/gctscript/modules/ta/indicators/bbands.go index 523cc7c8..6c7432e0 100644 --- a/gctscript/modules/ta/indicators/bbands.go +++ b/gctscript/modules/ta/indicators/bbands.go @@ -53,7 +53,7 @@ func bbands(args ...objects.Object) (objects.Object, error) { } ohlcvInput := objects.ToInterface(args[1]) - ohlcvInputData, valid := ohlcvInput.([]interface{}) + ohlcvInputData, valid := ohlcvInput.([]any) if !valid { return nil, fmt.Errorf(modules.ErrParameterConvertFailed, OHLCV) } @@ -61,8 +61,8 @@ func bbands(args ...objects.Object) (objects.Object, error) { ohlcvData := make([][]float64, 6) var allErrors []string for x := range ohlcvInputData { - var t []interface{} - t, ok = ohlcvInputData[x].([]interface{}) + var t []any + t, ok = ohlcvInputData[x].([]any) if !ok { return nil, errors.New("ohlcvInputData type assert failed") } diff --git a/gctscript/modules/ta/indicators/correlation.go b/gctscript/modules/ta/indicators/correlation.go index e637070e..3051c24c 100644 --- a/gctscript/modules/ta/indicators/correlation.go +++ b/gctscript/modules/ta/indicators/correlation.go @@ -43,14 +43,14 @@ func correlationCoefficient(args ...objects.Object) (objects.Object, error) { var allErrors []string ohlcvProcessor := func(args []objects.Object, idx int) ([]float64, error) { ohlcvInput := objects.ToInterface(args[idx]) - ohlcvInputData, valid := ohlcvInput.([]interface{}) + ohlcvInputData, valid := ohlcvInput.([]any) if !valid { return nil, fmt.Errorf(modules.ErrParameterConvertFailed, OHLCV) } var ohlcvClose []float64 for x := range ohlcvInputData { - t, ok := ohlcvInputData[x].([]interface{}) + t, ok := ohlcvInputData[x].([]any) if !ok { return nil, errors.New("ohlcvInputData type assert failed") } diff --git a/gctscript/modules/ta/indicators/ema.go b/gctscript/modules/ta/indicators/ema.go index 73af7ac8..51e69b2d 100644 --- a/gctscript/modules/ta/indicators/ema.go +++ b/gctscript/modules/ta/indicators/ema.go @@ -41,7 +41,7 @@ func ema(args ...objects.Object) (objects.Object, error) { } ohlcvInput := objects.ToInterface(args[0]) - ohlcvInputData, valid := ohlcvInput.([]interface{}) + ohlcvInputData, valid := ohlcvInput.([]any) if !valid { return nil, fmt.Errorf(modules.ErrParameterConvertFailed, OHLCV) } @@ -49,7 +49,7 @@ func ema(args ...objects.Object) (objects.Object, error) { ohlcvClose := make([]float64, len(ohlcvInputData)) var allErrors []string for x := range ohlcvInputData { - t, ok := ohlcvInputData[x].([]interface{}) + t, ok := ohlcvInputData[x].([]any) if !ok { return nil, errors.New("ohlcvInputData type assert failed") } diff --git a/gctscript/modules/ta/indicators/indicators.go b/gctscript/modules/ta/indicators/indicators.go index d9d95c7a..44c9be04 100644 --- a/gctscript/modules/ta/indicators/indicators.go +++ b/gctscript/modules/ta/indicators/indicators.go @@ -14,7 +14,7 @@ const OHLCV = "OHLCV data" var errInvalidSelector = errors.New("invalid selector") -func toFloat64(data interface{}) (float64, error) { +func toFloat64(data any) (float64, error) { switch d := data.(type) { case float64: return d, nil diff --git a/gctscript/modules/ta/indicators/macd.go b/gctscript/modules/ta/indicators/macd.go index e8675414..a1022a03 100644 --- a/gctscript/modules/ta/indicators/macd.go +++ b/gctscript/modules/ta/indicators/macd.go @@ -42,7 +42,7 @@ func macd(args ...objects.Object) (objects.Object, error) { } ohlcvInput := objects.ToInterface(args[0]) - ohlcvInputData, valid := ohlcvInput.([]interface{}) + ohlcvInputData, valid := ohlcvInput.([]any) if !valid { return nil, fmt.Errorf(modules.ErrParameterConvertFailed, OHLCV) } @@ -50,7 +50,7 @@ func macd(args ...objects.Object) (objects.Object, error) { ohlcvClose := make([]float64, len(ohlcvInputData)) var allErrors []string for x := range ohlcvInputData { - t, ok := ohlcvInputData[x].([]interface{}) + t, ok := ohlcvInputData[x].([]any) if !ok { return nil, errors.New("ohlcvInputData type assert failed") } diff --git a/gctscript/modules/ta/indicators/mfi.go b/gctscript/modules/ta/indicators/mfi.go index 955499be..221e68c8 100644 --- a/gctscript/modules/ta/indicators/mfi.go +++ b/gctscript/modules/ta/indicators/mfi.go @@ -41,7 +41,7 @@ func mfi(args ...objects.Object) (objects.Object, error) { } ohlcvInput := objects.ToInterface(args[0]) - ohlcvInputData, valid := ohlcvInput.([]interface{}) + ohlcvInputData, valid := ohlcvInput.([]any) if !valid { return nil, fmt.Errorf(modules.ErrParameterConvertFailed, OHLCV) } @@ -49,7 +49,7 @@ func mfi(args ...objects.Object) (objects.Object, error) { var allErrors []string for x := range ohlcvInputData { - t, ok := ohlcvInputData[x].([]interface{}) + t, ok := ohlcvInputData[x].([]any) if !ok { return nil, errors.New("ohlcvInputData type assert failed") } diff --git a/gctscript/modules/ta/indicators/obv.go b/gctscript/modules/ta/indicators/obv.go index 68643a7e..2b5a76b6 100644 --- a/gctscript/modules/ta/indicators/obv.go +++ b/gctscript/modules/ta/indicators/obv.go @@ -40,7 +40,7 @@ func obv(args ...objects.Object) (objects.Object, error) { } ohlcvInput := objects.ToInterface(args[0]) - ohlcvInputData, valid := ohlcvInput.([]interface{}) + ohlcvInputData, valid := ohlcvInput.([]any) if !valid { return nil, fmt.Errorf(modules.ErrParameterConvertFailed, OHLCV) } @@ -48,7 +48,7 @@ func obv(args ...objects.Object) (objects.Object, error) { ohlcvData := make([][]float64, 6) var allErrors []string for x := range ohlcvInputData { - t, ok := ohlcvInputData[x].([]interface{}) + t, ok := ohlcvInputData[x].([]any) if !ok { return nil, errors.New("ohlcvInputData type assert failed") } diff --git a/gctscript/modules/ta/indicators/rsi.go b/gctscript/modules/ta/indicators/rsi.go index 19b1f738..f6a08b23 100644 --- a/gctscript/modules/ta/indicators/rsi.go +++ b/gctscript/modules/ta/indicators/rsi.go @@ -41,7 +41,7 @@ func rsi(args ...objects.Object) (objects.Object, error) { } ohlcvInput := objects.ToInterface(args[0]) - ohlcvInputData, valid := ohlcvInput.([]interface{}) + ohlcvInputData, valid := ohlcvInput.([]any) if !valid { return nil, fmt.Errorf(modules.ErrParameterConvertFailed, OHLCV) } @@ -49,7 +49,7 @@ func rsi(args ...objects.Object) (objects.Object, error) { ohlcvClose := make([]float64, len(ohlcvInputData)) var allErrors []string for x := range ohlcvInputData { - t, ok := ohlcvInputData[x].([]interface{}) + t, ok := ohlcvInputData[x].([]any) if !ok { return nil, errors.New("ohlcvInputData type assert failed") } diff --git a/gctscript/modules/ta/indicators/sma.go b/gctscript/modules/ta/indicators/sma.go index 6770fd56..ab13fb4f 100644 --- a/gctscript/modules/ta/indicators/sma.go +++ b/gctscript/modules/ta/indicators/sma.go @@ -42,7 +42,7 @@ func sma(args ...objects.Object) (objects.Object, error) { } ohlcvInput := objects.ToInterface(args[0]) - ohlcvInputData, valid := ohlcvInput.([]interface{}) + ohlcvInputData, valid := ohlcvInput.([]any) if !valid { return nil, fmt.Errorf(modules.ErrParameterConvertFailed, OHLCV) } @@ -50,9 +50,9 @@ func sma(args ...objects.Object) (objects.Object, error) { ohlcvClose := make([]float64, len(ohlcvInputData)) var allErrors []string for x := range ohlcvInputData { - t, ok := ohlcvInputData[x].([]interface{}) + t, ok := ohlcvInputData[x].([]any) if !ok { - return nil, common.GetTypeAssertError("[]interface{}", ohlcvInputData[x]) + return nil, common.GetTypeAssertError("[]any", ohlcvInputData[x]) } if len(t) < 5 { return nil, errors.New("ohlcvInputData invalid data length") diff --git a/gctscript/vm/autoload.go b/gctscript/vm/autoload.go index cf80a6dc..fa06decc 100644 --- a/gctscript/vm/autoload.go +++ b/gctscript/vm/autoload.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path/filepath" + "slices" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/log" @@ -19,7 +20,7 @@ func (g *GctScriptManager) Autoload(name string, remove bool) error { if g.config.AutoLoad[x] != name { continue } - g.config.AutoLoad = append(g.config.AutoLoad[:x], g.config.AutoLoad[x+1:]...) + g.config.AutoLoad = slices.Delete(g.config.AutoLoad, x, x+1) if g.config.Verbose { log.Debugf(log.GCTScriptMgr, "Removing script: %s from autoload", name) } diff --git a/gctscript/vm/gctscript.go b/gctscript/vm/gctscript.go index 4f66d974..88e2ac7a 100644 --- a/gctscript/vm/gctscript.go +++ b/gctscript/vm/gctscript.go @@ -52,7 +52,7 @@ func (g *GctScriptManager) ShutdownAll() (err error) { } var shutdownErrors []error - AllVMSync.Range(func(_, v interface{}) bool { + AllVMSync.Range(func(_, v any) bool { vm, ok := v.(*VM) if !ok { shutdownErrors = append(shutdownErrors, common.GetTypeAssertError("*VM", v)) diff --git a/gctscript/vm/vm_types.go b/gctscript/vm/vm_types.go index 14113eb4..b39850f4 100644 --- a/gctscript/vm/vm_types.go +++ b/gctscript/vm/vm_types.go @@ -34,7 +34,7 @@ const ( type vmscount uint64 var ( - pool = &sync.Pool{New: func() interface{} { return new(tengo.Script) }} + pool = &sync.Pool{New: func() any { return new(tengo.Script) }} // AllVMSync stores all current Virtual Machine instances AllVMSync = &sync.Map{} // VMSCount running total count of Virtual Machines diff --git a/go.mod b/go.mod index 3a636717..1f056a36 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,7 @@ module github.com/thrasher-corp/gocryptotrader -go 1.24.0 +go 1.24.1 + require ( github.com/Masterminds/sprig/v3 v3.3.0 github.com/buger/jsonparser v1.1.1 diff --git a/log/custom_log_hooks_test.go b/log/custom_log_hooks_test.go index a872b9d8..1944eb42 100644 --- a/log/custom_log_hooks_test.go +++ b/log/custom_log_hooks_test.go @@ -4,7 +4,7 @@ import "testing" func TestSetCustomLoghook(t *testing.T) { t.Parallel() - logHook := func(_, _ string, _ ...interface{}) (bypassLibraryLogSystem bool) { + logHook := func(_, _ string, _ ...any) (bypassLibraryLogSystem bool) { return false } SetCustomLogHook(logHook) diff --git a/log/logger_multiwriter.go b/log/logger_multiwriter.go index 794ae912..f432ba99 100644 --- a/log/logger_multiwriter.go +++ b/log/logger_multiwriter.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "log" + "slices" "time" "github.com/thrasher-corp/gocryptotrader/encoding/json" @@ -100,7 +101,7 @@ type deferral func() string // StageLogEvent stages a new logger event in a jobs channel to be processed by // a worker pool. This segregates the need to process the log string and the // writes to the required io.Writer. -func (mw *multiWriterHolder) StageLogEvent(fn deferral, header, slName, spacer, timestampFormat, instance, level string, showLogSystemName, bypassWarning, structuredLog bool, fields map[Key]interface{}) { +func (mw *multiWriterHolder) StageLogEvent(fn deferral, header, slName, spacer, timestampFormat, instance, level string, showLogSystemName, bypassWarning, structuredLog bool, fields map[Key]any) { newJob := jobsPool.Get().(*job) //nolint:forcetypeassert // Not necessary from a pool newJob.Writers = mw.writers newJob.fn = fn @@ -143,11 +144,11 @@ func (mw *multiWriterHolder) add(writer io.Writer) error { if writer == nil { return errWriterIsNil } - for i := range mw.writers { - if mw.writers[i] == writer { - return errWriterAlreadyLoaded - } + + if slices.Contains(mw.writers, writer) { + return errWriterAlreadyLoaded } + mw.writers = append(mw.writers, writer) return nil } diff --git a/log/logger_types.go b/log/logger_types.go index 4c3f9469..97059af1 100644 --- a/log/logger_types.go +++ b/log/logger_types.go @@ -26,12 +26,12 @@ var ( // GlobalLogFile hold global configuration options for file logger globalLogFile = &Rotate{} - jobsPool = &sync.Pool{New: func() interface{} { return new(job) }} + jobsPool = &sync.Pool{New: func() any { return new(job) }} jobsChannel = make(chan *job, defaultJobChannelCapacity) // Note: Logger state within logFields will be persistent until it's garbage // collected. This is a little bit more efficient. - logFieldsPool = &sync.Pool{New: func() interface{} { return &fields{logger: logger} }} + logFieldsPool = &sync.Pool{New: func() any { return &fields{logger: logger} }} // LogPath system path to store log files in logPath string @@ -49,7 +49,7 @@ type job struct { TimestampFormat string ShowLogSystemName bool Instance string - StructuredFields map[Key]interface{} + StructuredFields map[Key]any StructuredLogging bool Severity string Passback chan<- struct{} @@ -115,7 +115,7 @@ type multiWriterHolder struct { // ExtraFields is a map of key value pairs that can be added to a structured // log output. -type ExtraFields map[Key]interface{} +type ExtraFields map[Key]any // Key is used for structured logging fields to ensure no collisions occur. // Unexported keys are default fields which cannot be overwritten. diff --git a/log/loggers.go b/log/loggers.go index e7731b39..22b37050 100644 --- a/log/loggers.go +++ b/log/loggers.go @@ -6,10 +6,10 @@ import ( ) // Infoln is a logging function that takes a sublogger and an arbitrary number -// of interface{} arguments. This writes to configured io.Writer(s) as an +// of any arguments. This writes to configured io.Writer(s) as an // information message using default formats for its operands. A new line is // automatically added to the output. -func Infoln(sl *SubLogger, a ...interface{}) { +func Infoln(sl *SubLogger, a ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -18,11 +18,11 @@ func Infoln(sl *SubLogger, a ...interface{}) { } // InfolnWithFields is a logging function that takes a sublogger, additional -// structured logging fields and an arbitrary number of interface{} arguments. +// structured logging fields and an arbitrary number of any arguments. // This writes to configured io.Writer(s) as an information message using // default formats for its operands. A new line is automatically added to the // output. If structured logging is not enabled, the fields will be ignored. -func InfolnWithFields(sl *SubLogger, extra ExtraFields, a ...interface{}) { +func InfolnWithFields(sl *SubLogger, extra ExtraFields, a ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -35,7 +35,7 @@ func InfolnWithFields(sl *SubLogger, extra ExtraFields, a ...interface{}) { // with optional arguments. This writes to configured io.Writer(s) as an // information message which formats according to the format specifier. // A new line is automatically added to the output. -func Infof(sl *SubLogger, format string, a ...interface{}) { +func Infof(sl *SubLogger, format string, a ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -49,7 +49,7 @@ func Infof(sl *SubLogger, format string, a ...interface{}) { // formats according to the format specifier. A new line is automatically added // to the output. If structured logging is not enabled, the fields will be // ignored. -func InfofWithFields(sl *SubLogger, extra ExtraFields, format string, a ...interface{}) { //nolint:goprintffuncname // False positive +func InfofWithFields(sl *SubLogger, extra ExtraFields, format string, a ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -59,10 +59,10 @@ func InfofWithFields(sl *SubLogger, extra ExtraFields, format string, a ...inter } // Debugln is a logging function that takes a sublogger and an arbitrary number -// of interface{} arguments. This writes to configured io.Writer(s) as an +// of any arguments. This writes to configured io.Writer(s) as an // debug message using default formats for its operands. A new line is // automatically added to the output. -func Debugln(sl *SubLogger, v ...interface{}) { +func Debugln(sl *SubLogger, v ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -71,11 +71,11 @@ func Debugln(sl *SubLogger, v ...interface{}) { } // DebuglnWithFields is a logging function that takes a sublogger, additional -// structured logging fields and an arbitrary number of interface{} arguments. +// structured logging fields and an arbitrary number of any arguments. // This writes to configured io.Writer(s) as an debug message using default // formats for its operands. A new line is automatically added to the // output. If structured logging is not enabled, the fields will be ignored. -func DebuglnWithFields(sl *SubLogger, extra ExtraFields, a ...interface{}) { +func DebuglnWithFields(sl *SubLogger, extra ExtraFields, a ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -88,7 +88,7 @@ func DebuglnWithFields(sl *SubLogger, extra ExtraFields, a ...interface{}) { // with optional arguments. This writes to configured io.Writer(s) as an // debug message which formats according to the format specifier. A new line is // automatically added to the output. -func Debugf(sl *SubLogger, data string, v ...interface{}) { +func Debugf(sl *SubLogger, data string, v ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -101,7 +101,7 @@ func Debugf(sl *SubLogger, data string, v ...interface{}) { // This writes to configured io.Writer(s) as an debug message which formats // according to the format specifier. A new line is automatically added to the // output. If structured logging is not enabled, the fields will be ignored. -func DebugfWithFields(sl *SubLogger, extra ExtraFields, format string, a ...interface{}) { //nolint:goprintffuncname // False positive +func DebugfWithFields(sl *SubLogger, extra ExtraFields, format string, a ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -111,10 +111,10 @@ func DebugfWithFields(sl *SubLogger, extra ExtraFields, format string, a ...inte } // Warnln is a logging function that takes a sublogger and an arbitrary number -// of interface{} arguments. This writes to configured io.Writer(s) as an +// of any arguments. This writes to configured io.Writer(s) as an // warning message using default formats for its operands. A new line is // automatically added to the output. -func Warnln(sl *SubLogger, v ...interface{}) { +func Warnln(sl *SubLogger, v ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -123,11 +123,11 @@ func Warnln(sl *SubLogger, v ...interface{}) { } // WarnlnWithFields is a logging function that takes a sublogger, additional -// structured logging fields and an arbitrary number of interface{} arguments. +// structured logging fields and an arbitrary number of any arguments. // This writes to configured io.Writer(s) as an warning message using default // formats for its operands. A new line is automatically added to the // output. If structured logging is not enabled, the fields will be ignored. -func WarnlnWithFields(sl *SubLogger, extra ExtraFields, a ...interface{}) { +func WarnlnWithFields(sl *SubLogger, extra ExtraFields, a ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -140,7 +140,7 @@ func WarnlnWithFields(sl *SubLogger, extra ExtraFields, a ...interface{}) { // with optional arguments. This writes to configured io.Writer(s) as an // warning message which formats according to the format specifier. A new line // is automatically added to the output. -func Warnf(sl *SubLogger, data string, v ...interface{}) { +func Warnf(sl *SubLogger, data string, v ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -153,7 +153,7 @@ func Warnf(sl *SubLogger, data string, v ...interface{}) { // This writes to configured io.Writer(s) as an warning message which formats // according to the format specifier. A new line is automatically added to the // output. If structured logging is not enabled, the fields will be ignored. -func WarnfWithFields(sl *SubLogger, extra ExtraFields, format string, a ...interface{}) { //nolint:goprintffuncname // False positive +func WarnfWithFields(sl *SubLogger, extra ExtraFields, format string, a ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -163,10 +163,10 @@ func WarnfWithFields(sl *SubLogger, extra ExtraFields, format string, a ...inter } // Errorln is a logging function that takes a sublogger and an arbitrary number -// of interface{} arguments. This writes to configured io.Writer(s) as an +// of any arguments. This writes to configured io.Writer(s) as an // error message using default formats for its operands. A new line is // automatically added to the output. -func Errorln(sl *SubLogger, v ...interface{}) { +func Errorln(sl *SubLogger, v ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -175,11 +175,11 @@ func Errorln(sl *SubLogger, v ...interface{}) { } // ErrorlnWithFields is a logging function that takes a sublogger, additional -// structured logging fields and an arbitrary number of interface{} arguments. +// structured logging fields and an arbitrary number of any arguments. // This writes to configured io.Writer(s) as an error message using default // formats for its operands. A new line is automatically added to the // output. If structured logging is not enabled, the fields will be ignored. -func ErrorlnWithFields(sl *SubLogger, extra ExtraFields, a ...interface{}) { +func ErrorlnWithFields(sl *SubLogger, extra ExtraFields, a ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -192,7 +192,7 @@ func ErrorlnWithFields(sl *SubLogger, extra ExtraFields, a ...interface{}) { // with optional arguments. This writes to configured io.Writer(s) as an // error message which formats according to the format specifier. A new line // is automatically added to the output. -func Errorf(sl *SubLogger, data string, v ...interface{}) { +func Errorf(sl *SubLogger, data string, v ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { @@ -205,7 +205,7 @@ func Errorf(sl *SubLogger, data string, v ...interface{}) { // This writes to configured io.Writer(s) as an error message which formats // according to the format specifier. A new line is automatically added to the // output. If structured logging is not enabled, the fields will be ignored. -func ErrorfWithFields(sl *SubLogger, extra ExtraFields, format string, a ...interface{}) { //nolint:goprintffuncname // False positive +func ErrorfWithFields(sl *SubLogger, extra ExtraFields, format string, a ...any) { mu.RLock() defer mu.RUnlock() if f := sl.getFields(); f != nil { diff --git a/portfolio/portfolio.go b/portfolio/portfolio.go index 7f17b144..f185785d 100644 --- a/portfolio/portfolio.go +++ b/portfolio/portfolio.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "maps" "net/http" "slices" "strings" @@ -179,12 +180,9 @@ func (b *Base) UpdateAddressBalance(address string, amount float64) { // RemoveExchangeAddress removes an exchange address from the portfolio. func (b *Base) RemoveExchangeAddress(exchangeName string, coinType currency.Code) { - for x := range b.Addresses { - if b.Addresses[x].Address == exchangeName && b.Addresses[x].CoinType.Equal(coinType) { - b.Addresses = append(b.Addresses[:x], b.Addresses[x+1:]...) - return - } - } + b.Addresses = slices.Clip(slices.DeleteFunc(b.Addresses, func(a Address) bool { + return a.Address == exchangeName && a.CoinType.Equal(coinType) + })) } // UpdateExchangeAddressBalance updates the portfolio balance when checked @@ -242,16 +240,14 @@ func (b *Base) RemoveAddress(address, description string, coinType currency.Code return errors.New("coin type is empty") } - for x := range b.Addresses { - if b.Addresses[x].Address == address && - b.Addresses[x].CoinType.Equal(coinType) && - b.Addresses[x].Description == description { - b.Addresses = append(b.Addresses[:x], b.Addresses[x+1:]...) - return nil - } + idx := slices.IndexFunc(b.Addresses, func(a Address) bool { + return a.Address == address && a.CoinType.Equal(coinType) && a.Description == description + }) + if idx == -1 { + return errors.New("portfolio item does not exist") } - - return errors.New("portfolio item does not exist") + b.Addresses = slices.Clip(slices.Delete(b.Addresses, idx, idx+1)) + return nil } // UpdatePortfolio adds to the portfolio addresses by coin type @@ -380,11 +376,7 @@ func getPercentageSpecific(input float64, target currency.Code, totals map[curre func (b *Base) GetPortfolioSummary() Summary { personalHoldings := b.GetPersonalPortfolio() exchangeHoldings := b.GetExchangePortfolio() - totalCoins := make(map[currency.Code]float64) - - for x, y := range personalHoldings { - totalCoins[x] = y - } + totalCoins := maps.Clone(personalHoldings) for x, y := range exchangeHoldings { balance, ok := totalCoins[x] diff --git a/portfolio/portfolio_types.go b/portfolio/portfolio_types.go index 15c5d382..85655ce9 100644 --- a/portfolio/portfolio_types.go +++ b/portfolio/portfolio_types.go @@ -29,13 +29,13 @@ type Address struct { type EtherchainBalanceResponse struct { Status int `json:"status"` Data []struct { - Address string `json:"address"` - Balance float64 `json:"balance"` - Nonce interface{} `json:"nonce"` - Code string `json:"code"` - Name interface{} `json:"name"` - Storage interface{} `json:"storage"` - FirstSeen interface{} `json:"firstSeen"` + Address string `json:"address"` + Balance float64 `json:"balance"` + Nonce any `json:"nonce"` + Code string `json:"code"` + Name any `json:"name"` + Storage any `json:"storage"` + FirstSeen any `json:"firstSeen"` } `json:"data"` } @@ -147,7 +147,7 @@ type XRPScanAccount struct { TxHash string `json:"tx_hash"` AccountName AccountInfo `json:"accountName"` ParentName AccountInfo `json:"parentName"` - Advisory interface{} `json:"advisory"` + Advisory any `json:"advisory"` } // AccountInfo is a XRPScan subtype for account associations diff --git a/portfolio/withdraw/validate_test.go b/portfolio/withdraw/validate_test.go index e2a95698..46fc4271 100644 --- a/portfolio/withdraw/validate_test.go +++ b/portfolio/withdraw/validate_test.go @@ -163,7 +163,7 @@ func TestValidateFiat(t *testing.T) { request *Request requestType RequestType bankAccountID string - output interface{} + output any validate validate.Checker }{ { @@ -256,7 +256,7 @@ func TestValidateCrypto(t *testing.T) { testCases := []struct { name string request *Request - output interface{} + output any }{ { "Valid", diff --git a/portfolio/withdraw/withdraw_types.go b/portfolio/withdraw/withdraw_types.go index 8cd98029..2dc5d1a7 100644 --- a/portfolio/withdraw/withdraw_types.go +++ b/portfolio/withdraw/withdraw_types.go @@ -101,8 +101,8 @@ type Request struct { OneTimePassword int64 PIN int64 - Crypto CryptoRequest `json:",omitempty"` - Fiat FiatRequest `json:",omitempty"` + Crypto CryptoRequest `json:"crypto"` + Fiat FiatRequest `json:"fiat"` } // Response holds complete details for Response