mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-03 23:16:53 +00:00
tool/exchange_wrapper_coverage: fix regression and implement reflection (#837)
* cmd/tools/exchange: fix regression and implement reflection so as this can dynamically scale to our interface * exchanges: add comment and fix whoopsie * exchanges: fix linter issues * wrapper_cov_tool: add actual full interface method count to get a better perceived deployment * exchanges/tool: addr glorious nits * kraken: remove string in test * exchange_template_tool: fix tmpl issue
This commit is contained in:
@@ -1,23 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/engine"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
||||
)
|
||||
|
||||
const (
|
||||
totalWrappers = 25
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -29,12 +21,16 @@ func main() {
|
||||
|
||||
engine.Bot.Settings = engine.Settings{
|
||||
DisableExchangeAutoPairUpdates: true,
|
||||
EnableDryRun: true,
|
||||
}
|
||||
|
||||
engine.Bot.Config.PurgeExchangeAPICredentials()
|
||||
engine.Bot.ExchangeManager = engine.SetupExchangeManager()
|
||||
|
||||
log.Printf("Loading exchanges..")
|
||||
var wg sync.WaitGroup
|
||||
for x := range exchange.Exchanges {
|
||||
err := engine.Bot.LoadExchange(exchange.Exchanges[x], &wg)
|
||||
err = engine.Bot.LoadExchange(exchange.Exchanges[x], &wg)
|
||||
if err != nil {
|
||||
log.Printf("Failed to load exchange %s. Err: %s",
|
||||
exchange.Exchanges[x],
|
||||
@@ -53,17 +49,28 @@ func main() {
|
||||
exch := exchanges[x]
|
||||
wg.Add(1)
|
||||
go func(e exchange.IBotExchange) {
|
||||
results[e.GetName()] = testWrappers(e)
|
||||
results[e.GetName()], err = testWrappers(e)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to test wrappers for %s %s", e.GetName(), err)
|
||||
}
|
||||
wg.Done()
|
||||
}(exch)
|
||||
}
|
||||
wg.Wait()
|
||||
log.Println("Done.")
|
||||
|
||||
var dummyInterface exchange.IBotExchange
|
||||
totalWrappers := reflect.TypeOf(&dummyInterface).Elem().NumMethod()
|
||||
|
||||
log.Println()
|
||||
for name, funcs := range results {
|
||||
pct := float64(totalWrappers-len(funcs)) / float64(totalWrappers) * 100
|
||||
log.Printf("Exchange %s wrapper coverage [%d/%d - %.2f%%] | Total missing: %d", name, totalWrappers-len(funcs), totalWrappers, pct, len(funcs))
|
||||
log.Printf("Exchange %s wrapper coverage [%d/%d - %.2f%%] | Total missing: %d",
|
||||
name,
|
||||
totalWrappers-len(funcs),
|
||||
totalWrappers,
|
||||
pct,
|
||||
len(funcs))
|
||||
log.Printf("\t Wrappers not implemented:")
|
||||
|
||||
for x := range funcs {
|
||||
@@ -73,149 +80,39 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func testWrappers(e exchange.IBotExchange) []string {
|
||||
p := currency.NewPair(currency.BTC, currency.USD)
|
||||
assetType := asset.Spot
|
||||
if !e.SupportsAsset(assetType) {
|
||||
assets := e.GetAssetTypes(false)
|
||||
rand.Seed(time.Now().Unix())
|
||||
assetType = assets[rand.Intn(len(assets))] // nolint:gosec // basic number generation required, no need for crypo/rand
|
||||
}
|
||||
// testWrappers executes and checks each IBotExchange's function return for the
|
||||
// error common.ErrNotYetImplemented to verify whether the wrapper function has
|
||||
// been implemented yet.
|
||||
func testWrappers(e exchange.IBotExchange) ([]string, error) {
|
||||
iExchange := reflect.TypeOf(&e).Elem()
|
||||
actualExchange := reflect.ValueOf(e)
|
||||
errType := reflect.TypeOf(common.ErrNotYetImplemented)
|
||||
|
||||
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)
|
||||
inputs[y] = reflect.Zero(input)
|
||||
}
|
||||
|
||||
_, err := e.FetchTicker(context.TODO(), p, assetType)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "FetchTicker")
|
||||
outputs := method.Call(inputs)
|
||||
for y := range outputs {
|
||||
incoming := outputs[y].Interface()
|
||||
if reflect.TypeOf(incoming) == errType {
|
||||
err, ok := incoming.(error)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s type assertion failure for %v", name, incoming)
|
||||
}
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, name)
|
||||
}
|
||||
// found error; there should not be another error in this slice.
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err = e.UpdateTicker(context.TODO(), p, assetType)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "UpdateTicker")
|
||||
}
|
||||
|
||||
_, err = e.FetchOrderbook(context.TODO(), p, assetType)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "FetchOrderbook")
|
||||
}
|
||||
|
||||
_, err = e.UpdateOrderbook(context.TODO(), p, assetType)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "UpdateOrderbook")
|
||||
}
|
||||
|
||||
_, err = e.FetchTradablePairs(context.TODO(), asset.Spot)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "FetchTradablePairs")
|
||||
}
|
||||
|
||||
err = e.UpdateTradablePairs(context.TODO(), false)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "UpdateTradablePairs")
|
||||
}
|
||||
|
||||
_, err = e.FetchAccountInfo(context.TODO(), assetType)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "GetAccountInfo")
|
||||
}
|
||||
|
||||
_, err = e.GetRecentTrades(context.TODO(), p, assetType)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "GetRecentTrades")
|
||||
}
|
||||
|
||||
_, err = e.GetHistoricTrades(context.TODO(), p, assetType, time.Time{}, time.Time{})
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "GetHistoricTrades")
|
||||
}
|
||||
|
||||
_, err = e.GetFundingHistory(context.TODO())
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "GetFundingHistory")
|
||||
}
|
||||
|
||||
_, err = e.SubmitOrder(context.TODO(), nil)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "SubmitOrder")
|
||||
}
|
||||
|
||||
_, err = e.ModifyOrder(context.TODO(), nil)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "ModifyOrder")
|
||||
}
|
||||
|
||||
err = e.CancelOrder(context.TODO(), nil)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "CancelOrder")
|
||||
}
|
||||
|
||||
_, err = e.CancelBatchOrders(context.TODO(), nil)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "CancelBatchOrders")
|
||||
}
|
||||
|
||||
_, err = e.CancelAllOrders(context.TODO(), nil)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "CancelAllOrders")
|
||||
}
|
||||
|
||||
_, err = e.GetOrderInfo(context.TODO(), "1", p, assetType)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "GetOrderInfo")
|
||||
}
|
||||
|
||||
_, err = e.GetOrderHistory(context.TODO(), nil)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "GetOrderHistory")
|
||||
}
|
||||
|
||||
_, err = e.GetActiveOrders(context.TODO(), nil)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "GetActiveOrders")
|
||||
}
|
||||
|
||||
_, err = e.GetDepositAddress(context.TODO(), currency.BTC, "", "")
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "GetDepositAddress")
|
||||
}
|
||||
|
||||
_, err = e.WithdrawCryptocurrencyFunds(context.TODO(), nil)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "WithdrawCryptocurrencyFunds")
|
||||
}
|
||||
|
||||
_, err = e.WithdrawFiatFunds(context.TODO(), nil)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "WithdrawFiatFunds")
|
||||
}
|
||||
_, err = e.WithdrawFiatFundsToInternationalBank(context.TODO(), nil)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "WithdrawFiatFundsToInternationalBank")
|
||||
}
|
||||
|
||||
_, err = e.GetHistoricCandles(context.TODO(), currency.Pair{}, asset.Spot, time.Unix(0, 0), time.Unix(0, 0), kline.OneDay)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "GetHistoricCandles")
|
||||
}
|
||||
|
||||
_, err = e.GetHistoricCandlesExtended(context.TODO(), currency.Pair{}, asset.Spot, time.Unix(0, 0), time.Unix(0, 0), kline.OneDay)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "GetHistoricCandlesExtended")
|
||||
}
|
||||
|
||||
_, err = e.UpdateAccountInfo(context.TODO(), assetType)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "UpdateAccountInfo")
|
||||
}
|
||||
|
||||
_, err = e.GetFeeByType(context.TODO(), &exchange.FeeBuilder{})
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "GetFeeByType")
|
||||
}
|
||||
|
||||
err = e.UpdateOrderExecutionLimits(context.TODO(), asset.DownsideProfitContract)
|
||||
if errors.Is(err, common.ErrNotYetImplemented) {
|
||||
funcs = append(funcs, "UpdateOrderExecutionLimits")
|
||||
}
|
||||
return funcs
|
||||
return funcs, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user