From b4d7e3284e0881a9241d57ad0285a99729e398cf Mon Sep 17 00:00:00 2001 From: Mariano <9205080+marianososto@users.noreply.github.com> Date: Thu, 25 Apr 2024 17:46:09 -0300 Subject: [PATCH] refactor to accept multiple sourceChains,targetChains and appIds --- api/handlers/operations/repository.go | 61 ++++++++++++-------- api/handlers/operations/service.go | 12 ++-- api/middleware/extract_parameters.go | 59 +++++++++++++++++++ api/routes/wormscan/operations/controller.go | 13 +++-- 4 files changed, 111 insertions(+), 34 deletions(-) diff --git a/api/handlers/operations/repository.go b/api/handlers/operations/repository.go index 0a87c419..5c4f4498 100644 --- a/api/handlers/operations/repository.go +++ b/api/handlers/operations/repository.go @@ -111,51 +111,66 @@ type OperationQuery struct { Pagination pagination.Pagination TxHash string Address string - SourceChainID *vaa.ChainID - TargetChainID *vaa.ChainID - AppID string + SourceChainIDs []vaa.ChainID + TargetChainIDs []vaa.ChainID + AppID []string ExclusiveAppId bool } -func buildQueryOperationsByChain(sourceChainID, targetChainID *vaa.ChainID) bson.D { +func buildQueryOperationsByChain(sourceChainIDs, targetChainIDs []vaa.ChainID) bson.D { var allMatch bson.A - if sourceChainID != nil { - matchSourceChain := bson.M{"rawStandardizedProperties.fromChain": *sourceChainID} + if len(sourceChainIDs) > 0 { + matchSourceChain := bson.M{"rawStandardizedProperties.fromChain": bson.M{"$in": sourceChainIDs}} allMatch = append(allMatch, matchSourceChain) } - if targetChainID != nil { - matchTargetChain := bson.M{"rawStandardizedProperties.toChain": *targetChainID} + if len(targetChainIDs) > 0 { + matchTargetChain := bson.M{"rawStandardizedProperties.toChain": bson.M{"$in": targetChainIDs}} allMatch = append(allMatch, matchTargetChain) } - if (sourceChainID != nil && targetChainID != nil) && (*sourceChainID == *targetChainID) { + if (len(sourceChainIDs) == 1 && len(targetChainIDs) == 1) && (sourceChainIDs[0] == targetChainIDs[0]) { return bson.D{{Key: "$match", Value: bson.M{"$or": allMatch}}} } return bson.D{{Key: "$match", Value: bson.M{"$and": allMatch}}} } -func buildQueryOperationsByAppID(appID string, exclusive bool) []bson.D { +func buildQueryOperationsByAppID(appIDs []string, exclusive bool) []bson.D { var result []bson.D - if appID == "" { - result = append(result, bson.D{{Key: "$match", Value: bson.M{}}}) - return result - } + /* + if appID == "" { + result = append(result, bson.D{{Key: "$match", Value: bson.M{}}}) + return result + } + */ if exclusive { - result = append(result, bson.D{{Key: "$match", Value: bson.M{ - "$and": bson.A{ - bson.M{"rawStandardizedProperties.appIds": bson.M{"$eq": []string{appID}}}, - bson.M{"rawStandardizedProperties.appIds": bson.M{"$size": 1}}, - }}}}) - return result + if len(appIDs) == 1 { + result = append(result, bson.D{{Key: "$match", Value: bson.M{ + "$and": bson.A{ + bson.M{"rawStandardizedProperties.appIds": bson.M{"$eq": appIDs}}, + bson.M{"rawStandardizedProperties.appIds": bson.M{"$size": 1}}, + }}}}) + } else { + a := bson.A{} + for _, appID := range appIDs { + cond := bson.M{ + "$and": bson.A{ + bson.M{"rawStandardizedProperties.appIds": bson.M{"$eq": appID}}, + bson.M{"rawStandardizedProperties.appIds": bson.M{"$size": 1}}, + }} + a = append(a, cond) + } + result = append(result, bson.D{{Key: "$match", Value: bson.M{ + "$or": a}}}) + } } else { - result = append(result, bson.D{{Key: "$match", Value: bson.M{"rawStandardizedProperties.appIds": bson.M{"$in": []string{appID}}}}}) + result = append(result, bson.D{{Key: "$match", Value: bson.M{"rawStandardizedProperties.appIds": bson.M{"$in": appIDs}}}}) } return result } @@ -238,8 +253,8 @@ func (r *Repository) FindByChainAndAppId(ctx context.Context, query OperationQue var pipeline mongo.Pipeline - if query.SourceChainID != nil || query.TargetChainID != nil { - matchBySourceTargetChain := buildQueryOperationsByChain(query.SourceChainID, query.TargetChainID) + if len(query.SourceChainIDs) != 0 || len(query.TargetChainIDs) != 0 { + matchBySourceTargetChain := buildQueryOperationsByChain(query.SourceChainIDs, query.TargetChainIDs) pipeline = append(pipeline, matchBySourceTargetChain) } diff --git a/api/handlers/operations/service.go b/api/handlers/operations/service.go index 340a2efa..77f49b8d 100644 --- a/api/handlers/operations/service.go +++ b/api/handlers/operations/service.go @@ -34,9 +34,9 @@ func (s *Service) FindById(ctx context.Context, chainID vaa.ChainID, type OperationFilter struct { TxHash *types.TxHash Address string - SourceChainID *vaa.ChainID - TargetChainID *vaa.ChainID - AppID string + SourceChainIDs []vaa.ChainID + TargetChainIDs []vaa.ChainID + AppID []string ExclusiveAppId bool Pagination pagination.Pagination } @@ -52,13 +52,13 @@ func (s *Service) FindAll(ctx context.Context, filter OperationFilter) ([]*Opera TxHash: txHash, Address: filter.Address, Pagination: filter.Pagination, - SourceChainID: filter.SourceChainID, - TargetChainID: filter.TargetChainID, + SourceChainIDs: filter.SourceChainIDs, + TargetChainIDs: filter.TargetChainIDs, AppID: filter.AppID, ExclusiveAppId: filter.ExclusiveAppId, } - if operationQuery.AppID != "" || operationQuery.SourceChainID != nil || operationQuery.TargetChainID != nil { + if len(operationQuery.AppID) != 0 || len(operationQuery.SourceChainIDs) > 0 || len(operationQuery.TargetChainIDs) > 0 { return s.repo.FindByChainAndAppId(ctx, operationQuery) } diff --git a/api/middleware/extract_parameters.go b/api/middleware/extract_parameters.go index 0ba910a1..45ff7231 100644 --- a/api/middleware/extract_parameters.go +++ b/api/middleware/extract_parameters.go @@ -61,14 +61,73 @@ func ExtractToChain(c *fiber.Ctx, l *zap.Logger) (*sdk.ChainID, error) { return &result, nil } +func ExtractChain(c *fiber.Ctx, l *zap.Logger) (*sdk.ChainID, error) { + return extractChainQueryParam(c, l, "chain") +} + +/* func ExtractSourceChain(c *fiber.Ctx, l *zap.Logger) (*sdk.ChainID, error) { return extractChainQueryParam(c, l, "sourceChain") } + + func ExtractTargetChain(c *fiber.Ctx, l *zap.Logger) (*sdk.ChainID, error) { return extractChainQueryParam(c, l, "targetChain") } +*/ + +func ExtractSourceChain(c *fiber.Ctx, l *zap.Logger) ([]sdk.ChainID, error) { + param := c.Query("sourceChain") + if param == "" { + return nil, nil + } + result := make([]sdk.ChainID, 0, len(param)) + for _, val := range strings.Split(param, ",") { + chain, err := parseChainIDParam(val) + if err != nil { + requestID := fmt.Sprintf("%v", c.Locals("requestid")) + l.Error("failed to parse sourceChain parameter", + zap.Error(err), + zap.String("requestID", requestID), + ) + return nil, response.NewInvalidParamError(c, "INVALID SOURCE_CHAIN VALUE", errors.WithStack(err)) + } + result = append(result, chain) + } + return result, nil +} + +func ExtractTargetChain(c *fiber.Ctx, l *zap.Logger) ([]sdk.ChainID, error) { + param := c.Query("targetChain") + if param == "" { + return nil, nil + } + result := make([]sdk.ChainID, 0, len(param)) + for _, val := range strings.Split(param, ",") { + chain, err := parseChainIDParam(val) + if err != nil { + requestID := fmt.Sprintf("%v", c.Locals("requestid")) + l.Error("failed to parse targetChain parameter", + zap.Error(err), + zap.String("requestID", requestID), + ) + return nil, response.NewInvalidParamError(c, "INVALID TARGET_CHAIN VALUE", errors.WithStack(err)) + } + result = append(result, chain) + } + return result, nil +} + +func parseChainIDParam(param string) (sdk.ChainID, error) { + chain, err := strconv.ParseInt(param, 10, 16) + if err != nil { + return sdk.ChainIDUnset, err + } + return sdk.ChainID(chain), nil +} + func extractChainQueryParam(c *fiber.Ctx, l *zap.Logger, queryParam string) (*sdk.ChainID, error) { param := c.Query(queryParam) if param == "" { diff --git a/api/routes/wormscan/operations/controller.go b/api/routes/wormscan/operations/controller.go index af2a8d41..7062c48e 100644 --- a/api/routes/wormscan/operations/controller.go +++ b/api/routes/wormscan/operations/controller.go @@ -2,6 +2,7 @@ package operations import ( "strconv" + "strings" "github.com/gofiber/fiber/v2" "github.com/wormhole-foundation/wormhole-explorer/api/handlers/operations" @@ -75,14 +76,16 @@ func (c *Controller) FindAll(ctx *fiber.Ctx) error { return err } - appID := middleware.ExtractAppId(ctx, c.logger) + //appID := middleware.ExtractAppId(ctx, c.logger) + appID := strings.Split(ctx.Query("appId"), ",") + exclusiveAppId, err := middleware.ExtractExclusiveAppId(ctx) if err != nil { return err } - searchBySourceTargetChain := sourceChain != nil || targetChain != nil - searchByAppId := appID != "" + searchBySourceTargetChain := len(sourceChain) != 0 || targetChain != nil + searchByAppId := len(appID) != 0 if (searchByAddress || searchByTxHash) && (searchBySourceTargetChain || searchByAppId) { return response.NewInvalidParamError(ctx, "address/txHash cannot be combined with sourceChain/targetChain/appId query filter", nil) @@ -91,8 +94,8 @@ func (c *Controller) FindAll(ctx *fiber.Ctx) error { filter := operations.OperationFilter{ TxHash: txHash, Address: address, - SourceChainID: sourceChain, - TargetChainID: targetChain, + SourceChainIDs: sourceChain, + TargetChainIDs: targetChain, AppID: appID, ExclusiveAppId: exclusiveAppId, Pagination: *pagination,