exchanges/qa: Add exchange wrapper testing suite (#1159)

* initial concept of a nice validation tester for exchanges

* adds some datahandler design

* expand testing

* more tests and fixes

* minor end of day fix for bithumb

* fixes implementation issues

* more test coverage and improvements, but not sure if i should continue

* fix more wrapper implementations

* adds error type, more fixes

* changes signature, fixes implementations

* fixes more wrapper implementations

* one more bit

* more cleanup

* WOW things work?

* lintle 1/1337

* mini bump

* fixes all linting

* neaten

* GetOrderInfo+ asset pair fixes+improvements

* adds new websocket test

* expand ws testing

* fix bug, expand tests, improve implementation

* code coverage of a lot of new codes

* fixes everything

* reverts accidental changes

* minor fixes from reviewing code

* removes Bitfinex cancelBatchOrder implementation

* fixes dumb baby typo for babies

* mini nit fixes

* so many nits to address

* addresses all the nits

* Titlecase

* switcheroo

* removes websocket testing for now

* fix appveyor, minor test fix

* fixes typo, re-kindles killed kode

* skip binance wrapper tests when running CI

* expired context, huobi okx fixes

* kodespull

* fix ordering

* time fix because why not

* fix exmo, others

* hopefully this fixes all of my life's problems

* last thing today

* huobi, more like hypotrophy

* golangci-lint, more like mypooroldknee-splint

* fix huobi times by removing them

* should fix okx currency issues

* blocks the application

* adds last little contingency for pairs

* addresses most nits and new problems

* lovely fixed before seeing why okx sucks

* fixes issues with okx websocket

* the classic receieieivaier

* lintle

* adds test and fixes existing tests

* expands error handling messages during setup

* fixes dumb okx bugs introduced

* quick fix for lint and exmo

* fixes nixes

* fix exmo deposit issue

* lint

* fixes issue with extra asset runs missing

* fix surprise race

* all the lint and merge fixes

* fixes surprise bugs in OKx

* fixes issues with times and chains

* fixing all the merge stuff

* merge fix

* rm logs and a panic potential

* lovely lint lament

* an easy demonstration of scenario, but not of initial purpose

* put it in the bin

* Revert "put it in the bin"

This reverts commit 15c6490f713233d43f10957367fcbf18e3818bdd.

* re-add after immediate error popup

* fix mini poor test design

* okx okay

* merge fixes

* fixes issues discovered in lovely test

* I FORGOT TO COMMIT THIS

* nit fixaroonaboo

* forgoetten test fix

* revert old okx asset intrument work

* fixes

* revert problems I didnt understand. update bybit

* fix merge bugs

* test cleanup

* further improvements

* reshuffle and lint

* rm redundant CI_TEST by rm the CI_TEST field that is redundant

* path fix

* move to its own section, dont run on 32 bit + appveyor

* lint

* fix lbank

* address nits

* let it rip

* fix failing test time range

* niteroo boogaloo

* mod tidy, use common.SimpleTimeFormat
This commit is contained in:
Scott
2023-07-03 11:09:43 +10:00
committed by GitHub
parent ef605a3c19
commit fcc5ad4551
210 changed files with 38548 additions and 6519 deletions

View File

@@ -386,7 +386,7 @@ func (g *Gateio) GetIntervalFromString(interval string) (kline.Interval, error)
case "1000ms":
return kline.ThousandMilliseconds, nil
default:
return kline.Interval(0), kline.ErrUnsetInterval
return kline.Interval(0), kline.ErrInvalidInterval
}
}
@@ -1007,12 +1007,11 @@ func (g *Gateio) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U
Headers: headers,
Body: strings.NewReader(payload),
Result: &intermediary,
AuthRequest: true,
Verbose: g.Verbose,
HTTPDebugging: g.HTTPDebugging,
HTTPRecording: g.HTTPRecording,
}, nil
})
}, request.AuthenticatedRequest)
if err != nil {
return err
}
@@ -1050,7 +1049,7 @@ func (g *Gateio) SendHTTPRequest(ctx context.Context, ep exchange.URL, epl reque
}
return g.SendPayload(ctx, epl, func() (*request.Item, error) {
return item, nil
})
}, request.UnauthenticatedRequest)
}
// *********************************** Withdrawals ******************************

View File

@@ -2378,7 +2378,7 @@ func TestGetActiveOrders(t *testing.T) {
if err != nil {
t.Error(err)
}
_, err = g.GetActiveOrders(context.Background(), &order.GetOrdersRequest{
_, err = g.GetActiveOrders(context.Background(), &order.MultiOrderRequest{
Pairs: enabledPairs[:2],
Type: order.AnyType,
Side: order.AnySide,
@@ -2391,7 +2391,7 @@ func TestGetActiveOrders(t *testing.T) {
if err != nil {
t.Error(err)
}
_, err = g.GetActiveOrders(context.Background(), &order.GetOrdersRequest{
_, err = g.GetActiveOrders(context.Background(), &order.MultiOrderRequest{
Pairs: []currency.Pair{cp},
Type: order.AnyType,
Side: order.AnySide,
@@ -2400,7 +2400,7 @@ func TestGetActiveOrders(t *testing.T) {
if err != nil {
t.Errorf(" %s GetActiveOrders() error: %v", g.Name, err)
}
_, err = g.GetActiveOrders(context.Background(), &order.GetOrdersRequest{
_, err = g.GetActiveOrders(context.Background(), &order.MultiOrderRequest{
Pairs: enabledPairs[:2],
Type: order.AnyType,
Side: order.AnySide,
@@ -2409,7 +2409,7 @@ func TestGetActiveOrders(t *testing.T) {
if err != nil {
t.Errorf(" %s GetActiveOrders() error: %v", g.Name, err)
}
_, err = g.GetActiveOrders(context.Background(), &order.GetOrdersRequest{
_, err = g.GetActiveOrders(context.Background(), &order.MultiOrderRequest{
Pairs: enabledPairs[:2],
Type: order.AnyType,
Side: order.AnySide,
@@ -2418,7 +2418,7 @@ func TestGetActiveOrders(t *testing.T) {
if err != nil {
t.Errorf(" %s GetActiveOrders() error: %v", g.Name, err)
}
_, err = g.GetActiveOrders(context.Background(), &order.GetOrdersRequest{
_, err = g.GetActiveOrders(context.Background(), &order.MultiOrderRequest{
Pairs: currency.Pairs{futuresTradablePair},
Type: order.AnyType,
Side: order.AnySide,
@@ -2427,7 +2427,7 @@ func TestGetActiveOrders(t *testing.T) {
if err != nil {
t.Errorf(" %s GetActiveOrders() error: %v", g.Name, err)
}
_, err = g.GetActiveOrders(context.Background(), &order.GetOrdersRequest{
_, err = g.GetActiveOrders(context.Background(), &order.MultiOrderRequest{
Pairs: currency.Pairs{deliveryFuturesTradablePair},
Type: order.AnyType,
Side: order.AnySide,
@@ -2436,7 +2436,7 @@ func TestGetActiveOrders(t *testing.T) {
if err != nil {
t.Errorf(" %s GetActiveOrders() error: %v", g.Name, err)
}
_, err = g.GetActiveOrders(context.Background(), &order.GetOrdersRequest{
_, err = g.GetActiveOrders(context.Background(), &order.MultiOrderRequest{
Pairs: currency.Pairs{optionsTradablePair},
Type: order.AnyType,
Side: order.AnySide,
@@ -2445,7 +2445,7 @@ func TestGetActiveOrders(t *testing.T) {
if err != nil {
t.Errorf(" %s GetActiveOrders() error: %v", g.Name, err)
}
if _, err = g.GetActiveOrders(context.Background(), &order.GetOrdersRequest{
if _, err = g.GetActiveOrders(context.Background(), &order.MultiOrderRequest{
Pairs: currency.Pairs{},
Type: order.AnyType,
Side: order.AnySide,
@@ -2457,7 +2457,7 @@ func TestGetActiveOrders(t *testing.T) {
func TestGetOrderHistory(t *testing.T) {
sharedtestvalues.SkipTestIfCredentialsUnset(t, g)
var getOrdersRequest = order.GetOrdersRequest{
var multiOrderRequest = order.MultiOrderRequest{
Type: order.AnyType,
AssetType: asset.Spot,
Side: order.Buy,
@@ -2466,36 +2466,36 @@ func TestGetOrderHistory(t *testing.T) {
if err != nil {
t.Fatal(err)
}
getOrdersRequest.Pairs = enabledPairs[:3]
_, err = g.GetOrderHistory(context.Background(), &getOrdersRequest)
multiOrderRequest.Pairs = enabledPairs[:3]
_, err = g.GetOrderHistory(context.Background(), &multiOrderRequest)
if err != nil {
t.Errorf("%s GetOrderhistory() error: %v", g.Name, err)
}
getOrdersRequest.AssetType = asset.Futures
getOrdersRequest.Pairs, err = g.GetEnabledPairs(asset.Futures)
multiOrderRequest.AssetType = asset.Futures
multiOrderRequest.Pairs, err = g.GetEnabledPairs(asset.Futures)
if err != nil {
t.Fatal(err)
}
getOrdersRequest.Pairs = getOrdersRequest.Pairs[len(getOrdersRequest.Pairs)-4:]
_, err = g.GetOrderHistory(context.Background(), &getOrdersRequest)
multiOrderRequest.Pairs = multiOrderRequest.Pairs[len(multiOrderRequest.Pairs)-4:]
_, err = g.GetOrderHistory(context.Background(), &multiOrderRequest)
if err != nil {
t.Errorf("%s GetOrderhistory() error: %v", g.Name, err)
}
getOrdersRequest.AssetType = asset.DeliveryFutures
getOrdersRequest.Pairs, err = g.GetEnabledPairs(asset.DeliveryFutures)
multiOrderRequest.AssetType = asset.DeliveryFutures
multiOrderRequest.Pairs, err = g.GetEnabledPairs(asset.DeliveryFutures)
if err != nil {
t.Fatal(err)
}
_, err = g.GetOrderHistory(context.Background(), &getOrdersRequest)
_, err = g.GetOrderHistory(context.Background(), &multiOrderRequest)
if err != nil {
t.Errorf("%s GetOrderhistory() error: %v", g.Name, err)
}
getOrdersRequest.AssetType = asset.Options
getOrdersRequest.Pairs, err = g.GetEnabledPairs(asset.Options)
multiOrderRequest.AssetType = asset.Options
multiOrderRequest.Pairs, err = g.GetEnabledPairs(asset.Options)
if err != nil {
t.Fatal(err)
}
_, err = g.GetOrderHistory(context.Background(), &getOrdersRequest)
_, err = g.GetOrderHistory(context.Background(), &multiOrderRequest)
if err != nil {
t.Errorf("%s GetOrderhistory() error: %v", g.Name, err)
}
@@ -2519,11 +2519,11 @@ func TestGetHistoricCandles(t *testing.T) {
if _, err := g.GetHistoricCandles(context.Background(), deliveryFuturesTradablePair, asset.DeliveryFutures, kline.OneDay, startTime, time.Now()); err != nil {
t.Errorf("%s GetHistoricCandles() error: %v", g.Name, err)
}
if _, err := g.GetHistoricCandles(context.Background(), optionsTradablePair, asset.Options, kline.OneDay, startTime, time.Now()); !errors.Is(err, common.ErrNotYetImplemented) {
t.Errorf("%s GetHistoricCandles() expecting: %v, but found %v", g.Name, common.ErrNotYetImplemented, err)
if _, err := g.GetHistoricCandles(context.Background(), optionsTradablePair, asset.Options, kline.OneDay, startTime, time.Now()); !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("%s GetHistoricCandles() expecting: %v, but found %v", g.Name, asset.ErrNotSupported, err)
}
if _, err := g.GetHistoricCandles(context.Background(), optionsTradablePair, asset.Options, kline.OneDay, startTime, time.Now()); !errors.Is(err, common.ErrNotYetImplemented) {
t.Errorf("%s GetHistoricCandles() expecting: %v, but found %v", g.Name, common.ErrNotYetImplemented, err)
if _, err := g.GetHistoricCandles(context.Background(), optionsTradablePair, asset.Options, kline.OneDay, startTime, time.Now()); !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("%s GetHistoricCandles() expecting: %v, but found %v", g.Name, asset.ErrNotSupported, err)
}
}
@@ -2554,8 +2554,8 @@ func TestGetHistoricCandlesExtended(t *testing.T) {
if err != nil {
t.Error(err)
}
if _, err := g.GetHistoricCandlesExtended(context.Background(), optionsTradablePair, asset.Options, kline.OneDay, startTime, time.Now()); !errors.Is(err, common.ErrNotYetImplemented) {
t.Errorf("%s GetHistoricCandlesExtended() expecting: %v, but found %v", g.Name, common.ErrNotYetImplemented, err)
if _, err = g.GetHistoricCandlesExtended(context.Background(), optionsTradablePair, asset.Options, kline.OneDay, startTime, time.Now()); !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("%s GetHistoricCandlesExtended() expecting: %v, but found %v", g.Name, asset.ErrNotSupported, err)
}
}
func TestGetAvailableTransferTrains(t *testing.T) {

View File

@@ -555,7 +555,7 @@ func (g *Gateio) UpdateTradablePairs(ctx context.Context, forceUpdate bool) erro
return err
}
}
return nil
return g.EnsureOnePairEnabled()
}
// UpdateTickers updates the ticker for all currency pairs of a given asset type
@@ -867,9 +867,9 @@ func (g *Gateio) FetchAccountInfo(ctx context.Context, assetType asset.Item) (ac
return acc, nil
}
// GetFundingHistory returns funding history, deposits and
// GetAccountFundingHistory returns funding history, deposits and
// withdrawals
func (g *Gateio) GetFundingHistory(_ context.Context) ([]exchange.FundHistory, error) {
func (g *Gateio) GetAccountFundingHistory(_ context.Context) ([]exchange.FundingHistory, error) {
return nil, common.ErrFunctionNotSupported
}
@@ -1216,11 +1216,11 @@ func (g *Gateio) CancelOrder(ctx context.Context, o *order.Cancel) error {
}
// CancelBatchOrders cancels an orders by their corresponding ID numbers
func (g *Gateio) CancelBatchOrders(ctx context.Context, o []order.Cancel) (order.CancelBatchResponse, error) {
func (g *Gateio) CancelBatchOrders(ctx context.Context, o []order.Cancel) (*order.CancelBatchResponse, error) {
var response order.CancelBatchResponse
response.Status = map[string]string{}
if len(o) == 0 {
return response, errors.New("no cancel order passed")
return nil, errors.New("no cancel order passed")
}
var err error
var cancelSpotOrdersParam []CancelOrderByIDParam
@@ -1228,11 +1228,11 @@ func (g *Gateio) CancelBatchOrders(ctx context.Context, o []order.Cancel) (order
for x := range o {
o[x].Pair, err = g.FormatExchangeCurrency(o[x].Pair, a)
if err != nil {
return response, err
return nil, err
}
o[x].Pair = o[x].Pair.Upper()
if a != o[x].AssetType {
return response, errors.New("cannot cancel orders of different asset types")
return nil, errors.New("cannot cancel orders of different asset types")
}
if a == asset.Spot || a == asset.Margin || a == asset.CrossMargin {
cancelSpotOrdersParam = append(cancelSpotOrdersParam, CancelOrderByIDParam{
@@ -1243,7 +1243,7 @@ func (g *Gateio) CancelBatchOrders(ctx context.Context, o []order.Cancel) (order
}
err = o[x].Validate(o[x].StandardCancel())
if err != nil {
return response, err
return nil, err
}
}
switch a {
@@ -1259,7 +1259,7 @@ func (g *Gateio) CancelBatchOrders(ctx context.Context, o []order.Cancel) (order
var cancel []CancelOrderByIDResponse
cancel, err = g.CancelBatchOrdersWithIDList(ctx, input)
if err != nil {
return response, err
return nil, err
}
for x := range cancel {
response.Status[cancel[x].OrderID] = func() string {
@@ -1274,7 +1274,7 @@ func (g *Gateio) CancelBatchOrders(ctx context.Context, o []order.Cancel) (order
for a := range o {
cancel, err := g.CancelMultipleFuturesOpenOrders(ctx, o[a].Pair, o[a].Side.Lower(), o[a].Pair.Quote.String())
if err != nil {
return response, err
return nil, err
}
for x := range cancel {
response.Status[strconv.FormatInt(cancel[x].ID, 10)] = cancel[x].Status
@@ -1284,11 +1284,11 @@ func (g *Gateio) CancelBatchOrders(ctx context.Context, o []order.Cancel) (order
for a := range o {
settle, err := g.getSettlementFromCurrency(o[a].Pair, false)
if err != nil {
return response, err
return nil, err
}
cancel, err := g.CancelMultipleDeliveryOrders(ctx, o[a].Pair, o[a].Side.Lower(), settle)
if err != nil {
return response, err
return nil, err
}
for x := range cancel {
response.Status[strconv.FormatInt(cancel[x].ID, 10)] = cancel[x].Status
@@ -1298,16 +1298,16 @@ func (g *Gateio) CancelBatchOrders(ctx context.Context, o []order.Cancel) (order
for a := range o {
cancel, err := g.CancelMultipleOptionOpenOrders(ctx, o[a].Pair, o[a].Pair.String(), o[a].Side.Lower())
if err != nil {
return response, err
return nil, err
}
for x := range cancel {
response.Status[strconv.FormatInt(cancel[x].OptionOrderID, 10)] = cancel[x].Status
}
}
default:
return response, fmt.Errorf("%w asset type: %v", asset.ErrNotSupported, a)
return nil, fmt.Errorf("%w asset type: %v", asset.ErrNotSupported, a)
}
return response, nil
return &response, nil
}
// CancelAllOrders cancels all orders associated with a currency pair
@@ -1388,35 +1388,38 @@ func (g *Gateio) CancelAllOrders(ctx context.Context, o *order.Cancel) (order.Ca
}
// GetOrderInfo returns order information based on order ID
func (g *Gateio) GetOrderInfo(ctx context.Context, orderID string, pair currency.Pair, a asset.Item) (order.Detail, error) {
var orderDetail order.Detail
func (g *Gateio) GetOrderInfo(ctx context.Context, orderID string, pair currency.Pair, a asset.Item) (*order.Detail, error) {
if err := g.CurrencyPairs.IsAssetEnabled(a); err != nil {
return nil, err
}
pair, err := g.FormatExchangeCurrency(pair, a)
if err != nil {
return orderDetail, err
return nil, err
}
switch a {
case asset.Spot, asset.Margin, asset.CrossMargin:
var spotOrder *SpotOrder
spotOrder, err = g.GetSpotOrder(ctx, orderID, pair, a)
if err != nil {
return orderDetail, err
return nil, err
}
var side order.Side
side, err = order.StringToOrderSide(spotOrder.Side)
if err != nil {
return orderDetail, err
return nil, err
}
var orderType order.Type
orderType, err = order.StringToOrderType(spotOrder.Type)
if err != nil {
return orderDetail, err
return nil, err
}
var orderStatus order.Status
orderStatus, err = order.StringToOrderStatus(spotOrder.Status)
if err != nil {
return orderDetail, err
return nil, err
}
return order.Detail{
return &order.Detail{
Amount: spotOrder.Amount,
Exchange: g.Name,
OrderID: spotOrder.OrderID,
@@ -1439,7 +1442,7 @@ func (g *Gateio) GetOrderInfo(ctx context.Context, orderID string, pair currency
settle, err = g.getSettlementFromCurrency(pair, false)
}
if err != nil {
return orderDetail, err
return nil, err
}
var fOrder *Order
var err error
@@ -1449,17 +1452,17 @@ func (g *Gateio) GetOrderInfo(ctx context.Context, orderID string, pair currency
fOrder, err = g.GetSingleDeliveryOrder(ctx, settle, orderID)
}
if err != nil {
return orderDetail, err
return nil, err
}
orderStatus, err := order.StringToOrderStatus(fOrder.Status)
if err != nil {
return orderDetail, err
return nil, err
}
pair, err = currency.NewPairFromString(fOrder.Contract)
if err != nil {
return orderDetail, err
return nil, err
}
return order.Detail{
return &order.Detail{
Amount: fOrder.Size,
ExecutedAmount: fOrder.Size - fOrder.RemainingAmount,
Exchange: g.Name,
@@ -1474,17 +1477,17 @@ func (g *Gateio) GetOrderInfo(ctx context.Context, orderID string, pair currency
case asset.Options:
optionOrder, err := g.GetSingleOptionOrder(ctx, orderID)
if err != nil {
return orderDetail, err
return nil, err
}
orderStatus, err := order.StringToOrderStatus(optionOrder.Status)
if err != nil {
return orderDetail, err
return nil, err
}
pair, err = currency.NewPairFromString(optionOrder.Contract)
if err != nil {
return orderDetail, err
return nil, err
}
return order.Detail{
return &order.Detail{
Amount: optionOrder.Size,
ExecutedAmount: optionOrder.Size - optionOrder.Left,
Exchange: g.Name,
@@ -1497,7 +1500,7 @@ func (g *Gateio) GetOrderInfo(ctx context.Context, orderID string, pair currency
AssetType: a,
}, nil
default:
return orderDetail, fmt.Errorf("%w asset type: %v", asset.ErrNotSupported, a)
return nil, fmt.Errorf("%w asset type: %v", asset.ErrNotSupported, a)
}
}
@@ -1575,7 +1578,7 @@ func (g *Gateio) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuild
}
// GetActiveOrders retrieves any orders that are active/open
func (g *Gateio) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest) (order.FilteredOrders, error) {
func (g *Gateio) GetActiveOrders(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
if err := req.Validate(); err != nil {
return nil, err
}
@@ -1724,7 +1727,7 @@ func (g *Gateio) GetActiveOrders(ctx context.Context, req *order.GetOrdersReques
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (g *Gateio) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest) (order.FilteredOrders, error) {
func (g *Gateio) GetOrderHistory(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
err := req.Validate()
if err != nil {
return nil, err
@@ -1739,7 +1742,7 @@ func (g *Gateio) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques
for x := range req.Pairs {
fPair := req.Pairs[x].Format(format)
var spotOrders []SpotPersonalTradeHistory
spotOrders, err = g.GateIOGetPersonalTradingHistory(ctx, fPair, req.OrderID, 0, 0, req.AssetType == asset.CrossMargin, req.StartTime, req.EndTime)
spotOrders, err = g.GateIOGetPersonalTradingHistory(ctx, fPair, req.FromOrderID, 0, 0, req.AssetType == asset.CrossMargin, req.StartTime, req.EndTime)
if err != nil {
return nil, err
}
@@ -1783,9 +1786,9 @@ func (g *Gateio) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques
}
var futuresOrder []TradingHistoryItem
if req.AssetType == asset.Futures {
futuresOrder, err = g.GetMyPersonalTradingHistory(ctx, settle, "", req.OrderID, fPair, 0, 0, 0)
futuresOrder, err = g.GetMyPersonalTradingHistory(ctx, settle, "", req.FromOrderID, fPair, 0, 0, 0)
} else {
futuresOrder, err = g.GetDeliveryPersonalTradingHistory(ctx, settle, req.OrderID, fPair, 0, 0, 0, "")
futuresOrder, err = g.GetDeliveryPersonalTradingHistory(ctx, settle, req.FromOrderID, fPair, 0, 0, 0, "")
}
if err != nil {
return nil, err
@@ -1890,9 +1893,6 @@ func (g *Gateio) GetHistoricCandles(ctx context.Context, pair currency.Pair, a a
Volume: candles[x].Volume,
}
}
case asset.Options:
// TODO: add support for options when endpoint is returning data
return nil, common.ErrNotYetImplemented
default:
return nil, fmt.Errorf("%w asset type: %v", asset.ErrNotSupported, a)
}
@@ -1956,9 +1956,6 @@ func (g *Gateio) GetHistoricCandlesExtended(ctx context.Context, pair currency.P
Volume: candles[x].Volume,
})
}
case asset.Options:
// TODO: add support for options when endpoint is returning data
return nil, common.ErrNotYetImplemented
default:
return nil, fmt.Errorf("%w asset type: %v", asset.ErrNotSupported, a)
}