diff --git a/cmd/exchange_wrapper_coverage/main.go b/cmd/exchange_wrapper_coverage/main.go index 166b0b43..ddc241ba 100644 --- a/cmd/exchange_wrapper_coverage/main.go +++ b/cmd/exchange_wrapper_coverage/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "errors" "fmt" "log" @@ -30,6 +31,10 @@ func main() { log.Printf("Loading exchanges..") var wg sync.WaitGroup for x := range exchange.Exchanges { + if exchange.Exchanges[x] == "ftx" { + log.Println("Skipping exchange FTX...") + continue + } err = engine.Bot.LoadExchange(exchange.Exchanges[x], &wg) if err != nil { log.Printf("Failed to load exchange %s. Err: %s", @@ -43,18 +48,21 @@ func main() { log.Printf("Testing exchange wrappers..") results := make(map[string][]string) - wg = sync.WaitGroup{} + var mtx sync.Mutex + exchanges := engine.Bot.GetExchanges() for x := range exchanges { - exch := exchanges[x] wg.Add(1) - go func(e exchange.IBotExchange) { - results[e.GetName()], err = testWrappers(e) + go func(exch exchange.IBotExchange) { + strResults, err := testWrappers(exch) if err != nil { - fmt.Printf("failed to test wrappers for %s %s", e.GetName(), err) + log.Printf("Failed to test wrappers for %s. Err: %s", exch.GetName(), err) } + mtx.Lock() + results[exch.GetName()] = strResults + mtx.Unlock() wg.Done() - }(exch) + }(exchanges[x]) } wg.Wait() log.Println("Done.") @@ -88,17 +96,33 @@ func testWrappers(e exchange.IBotExchange) ([]string, error) { actualExchange := reflect.ValueOf(e) errType := reflect.TypeOf(common.ErrNotYetImplemented) + contextParam := reflect.TypeOf((*context.Context)(nil)).Elem() + var funcs []string for x := 0; x < iExchange.NumMethod(); x++ { name := iExchange.Method(x).Name method := actualExchange.MethodByName(name) inputs := make([]reflect.Value, method.Type().NumIn()) + for y := 0; y < method.Type().NumIn(); y++ { input := method.Type().In(y) + + if input.Implements(contextParam) { + // Need to deploy a context.Context value as nil value is not + // checked throughout codebase. + inputs[y] = reflect.ValueOf(context.Background()) + continue + } inputs[y] = reflect.Zero(input) } outputs := method.Call(inputs) + if method.Type().NumIn() == 0 { + // Some empty functions will reset the exchange struct to defaults, + // so turn off verbosity. + e.GetBase().Verbose = false + } + for y := range outputs { incoming := outputs[y].Interface() if reflect.TypeOf(incoming) == errType { diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 69d68a62..05b4b4d1 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -634,6 +634,8 @@ func (b *Binance) FetchTicker(ctx context.Context, p currency.Pair, assetType as func (b *Binance) FetchOrderbook(ctx context.Context, p currency.Pair, assetType asset.Item) (*orderbook.Base, error) { ob, err := orderbook.Get(b.Name, p, assetType) if err != nil { + // TODO: Disconnect update orderbook functionality from fetch orderbook + // functionality across all wrappers as this mutes potential errors. return b.UpdateOrderbook(ctx, p, assetType) } return ob, nil @@ -659,6 +661,8 @@ func (b *Binance) UpdateOrderbook(ctx context.Context, p currency.Pair, assetTyp orderbookNew, err = b.UFuturesOrderbook(ctx, p, 1000) case asset.CoinMarginedFutures: orderbookNew, err = b.GetFuturesOrderbook(ctx, p, 1000) + default: + return nil, fmt.Errorf("[%s] %w", assetType, asset.ErrNotSupported) } if err != nil { return book, err diff --git a/exchanges/bybit/bybit_wrapper.go b/exchanges/bybit/bybit_wrapper.go index fc1b01e0..ef625f40 100644 --- a/exchanges/bybit/bybit_wrapper.go +++ b/exchanges/bybit/bybit_wrapper.go @@ -182,12 +182,17 @@ func (by *Bybit) SetDefaults() { // Setup takes in the supplied exchange configuration details and sets params func (by *Bybit) Setup(exch *config.Exchange) error { + err := exch.Validate() + if err != nil { + return err + } + if !exch.Enabled { by.SetEnabled(false) return nil } - err := by.SetupDefaults(exch) + err = by.SetupDefaults(exch) if err != nil { return err }