From 5b03c9e89914b6a5a00869137da686857728abf5 Mon Sep 17 00:00:00 2001 From: Mariano <9205080+marianososto@users.noreply.github.com> Date: Mon, 25 Mar 2024 14:06:24 -0300 Subject: [PATCH] combine query params filters --- api/handlers/operations/repository.go | 108 +++++++++++++++---- api/handlers/operations/service.go | 4 - api/middleware/extract_parameters.go | 18 ---- api/routes/wormscan/operations/controller.go | 46 +++----- 4 files changed, 100 insertions(+), 76 deletions(-) diff --git a/api/handlers/operations/repository.go b/api/handlers/operations/repository.go index 77274879..cab45537 100644 --- a/api/handlers/operations/repository.go +++ b/api/handlers/operations/repository.go @@ -111,12 +111,61 @@ type OperationQuery struct { Pagination pagination.Pagination TxHash string Address string - ChainID *vaa.ChainID SourceChainID *vaa.ChainID TargetChainID *vaa.ChainID AppID string ExclusiveAppId bool - PayloadType *float64 +} + +func buildQueryOperationsByChain(sourceChainID, targetChainID *vaa.ChainID, strict bool) bson.D { + var allMatch bson.A + + if sourceChainID != nil { + matchSourceChain := bson.D{{Key: "$or", Value: bson.A{ + bson.D{{Key: "rawStandardizedProperties.fromChain", Value: bson.M{"$eq": sourceChainID}}}, + bson.D{{Key: "standardizedProperties.fromChain", Value: bson.M{"$eq": sourceChainID}}}, + }}} + allMatch = append(allMatch, matchSourceChain) + } + if targetChainID != nil { + matchTargetChain := bson.D{{Key: "$or", Value: bson.A{ + bson.D{{Key: "parsedPayload.toChain", Value: bson.M{"$eq": targetChainID}}}, + bson.D{{Key: "parsedPayload.targetChainId", Value: bson.M{"$eq": targetChainID}}}, + bson.D{{Key: "standardizedProperties.toChain", Value: bson.M{"$eq": targetChainID}}}, + bson.D{{Key: "rawStandardizedProperties.toChain", Value: bson.M{"$eq": targetChainID}}}, + }}} + allMatch = append(allMatch, matchTargetChain) + } + + var matchParsedVaa bson.D + if strict { + matchParsedVaa = bson.D{{Key: "$match", Value: bson.D{{Key: "$and", Value: allMatch}}}} + } else { + matchParsedVaa = bson.D{{Key: "$match", Value: bson.D{{Key: "$or", Value: allMatch}}}} + } + return matchParsedVaa +} + +func buildQueryOperationsByAppID(appID string, exclusive bool) bson.D { + + if appID == "" { + return bson.D{{Key: "$match", Value: bson.M{}}} + } + + var appIdsCondition interface{} + if exclusive { + appIdsCondition = bson.M{"$eq": []string{appID}} + } else { + appIdsCondition = bson.M{"$in": []string{appID}} + } + + matchParsedVaa := bson.D{{Key: "$match", Value: bson.D{{Key: "$or", Value: bson.A{ + bson.D{{Key: "appIds", Value: appIdsCondition}}, + bson.D{{Key: "rawStandardizedProperties.appIds", Value: appIdsCondition}}, + bson.D{{Key: "standardizedProperties.appIds", Value: appIdsCondition}}, + }}}}} + + return matchParsedVaa } // strict flag is to force that both source and target chain id must match @@ -199,7 +248,7 @@ func findOperationsIdByChain(ctx context.Context, db *mongo.Database, chainId va } return ids, nil } -*/ + func findOperationsIdByAppID(ctx context.Context, db *mongo.Database, appID string, exclusive bool) ([]string, error) { @@ -232,6 +281,7 @@ func findOperationsIdByAppID(ctx context.Context, db *mongo.Database, appID stri } return ids, nil } +*/ // findOperationsIdByAddress returns all operations filtered by address. func findOperationsIdByAddress(ctx context.Context, db *mongo.Database, address string, pagination *pagination.Pagination) ([]string, error) { @@ -307,6 +357,35 @@ func (r *Repository) matchOperationByTxHash(ctx context.Context, txHash string) }}}}} } +func (r *Repository) findOpsIdByChainAndAppId(ctx context.Context, query OperationQuery) ([]string, error) { + + var pipeline mongo.Pipeline + + if query.SourceChainID != nil || query.TargetChainID != nil { + matchBySourceTargetChain := buildQueryOperationsByChain(query.SourceChainID, query.TargetChainID, true) + pipeline = append(pipeline, matchBySourceTargetChain) + } + if len(query.AppID) > 0 { + matchByAppId := buildQueryOperationsByAppID(query.AppID, query.ExclusiveAppId) + pipeline = append(pipeline, matchByAppId) + } + + cur, err := r.db.Collection("parsedVaa").Aggregate(ctx, pipeline) + if err != nil { + return nil, err + } + var documents []mongoID + err = cur.All(ctx, &documents) + if err != nil { + return nil, err + } + var ids []string + for _, doc := range documents { + ids = append(ids, doc.Id) + } + return ids, nil +} + // FindAll returns all operations filtered by q. func (r *Repository) FindAll(ctx context.Context, query OperationQuery) ([]*OperationDto, error) { @@ -333,26 +412,9 @@ func (r *Repository) FindAll(ctx context.Context, query OperationQuery) ([]*Oper // match operation by txHash (source tx and destination tx) matchByTxHash := r.matchOperationByTxHash(ctx, query.TxHash) pipeline = append(pipeline, matchByTxHash) - } else if query.ChainID != nil { - ids, err := findOperationsIdByChain(ctx, r.db, query.ChainID, query.ChainID, false) - if err != nil { - return nil, err - } - if len(ids) == 0 { - return []*OperationDto{}, nil - } - pipeline = append(pipeline, bson.D{{Key: "$match", Value: bson.D{{Key: "_id", Value: bson.D{{Key: "$in", Value: ids}}}}}}) - } else if query.SourceChainID != nil || query.TargetChainID != nil { - ids, err := findOperationsIdByChain(ctx, r.db, query.SourceChainID, query.TargetChainID, true) - if err != nil { - return nil, err - } - if len(ids) == 0 { - return []*OperationDto{}, nil - } - pipeline = append(pipeline, bson.D{{Key: "$match", Value: bson.D{{Key: "_id", Value: bson.D{{Key: "$in", Value: ids}}}}}}) - } else if len(query.AppID) > 0 { - ids, err := findOperationsIdByAppID(ctx, r.db, query.AppID, query.ExclusiveAppId) + } else if query.SourceChainID != nil || query.TargetChainID != nil || query.AppID != "" { + // find all ids that match by source and target chain id + ids, err := r.findOpsIdByChainAndAppId(ctx, query) if err != nil { return nil, err } diff --git a/api/handlers/operations/service.go b/api/handlers/operations/service.go index 10217484..43b5bf4d 100644 --- a/api/handlers/operations/service.go +++ b/api/handlers/operations/service.go @@ -34,13 +34,11 @@ func (s *Service) FindById(ctx context.Context, chainID vaa.ChainID, type OperationFilter struct { TxHash *types.TxHash Address string - ChainID *vaa.ChainID SourceChainID *vaa.ChainID TargetChainID *vaa.ChainID AppID string ExclusiveAppId bool Pagination pagination.Pagination - PayloadType *float64 } // FindAll returns all operations filtered by q. @@ -54,12 +52,10 @@ func (s *Service) FindAll(ctx context.Context, filter OperationFilter) ([]*Opera TxHash: txHash, Address: filter.Address, Pagination: filter.Pagination, - ChainID: filter.ChainID, SourceChainID: filter.SourceChainID, TargetChainID: filter.TargetChainID, AppID: filter.AppID, ExclusiveAppId: filter.ExclusiveAppId, - PayloadType: filter.PayloadType, } operations, err := s.repo.FindAll(ctx, operationQuery) diff --git a/api/middleware/extract_parameters.go b/api/middleware/extract_parameters.go index a0bddaba..91b3163b 100644 --- a/api/middleware/extract_parameters.go +++ b/api/middleware/extract_parameters.go @@ -299,24 +299,6 @@ func ExtractExclusiveAppId(c *fiber.Ctx, l *zap.Logger) (bool, error) { return strconv.ParseBool(query) } -func ExtractPayloadType(c *fiber.Ctx, l *zap.Logger) (*float64, error) { - payloadTypeParam := c.Query("payloadType") - if payloadTypeParam == "" { - return nil, nil - } - - payloadType, err := strconv.ParseFloat(payloadTypeParam, 64) - if err != nil { - requestID := fmt.Sprintf("%v", c.Locals("requestid")) - l.Error("failed to parse payload type parameter", - zap.Error(err), - zap.String("requestID", requestID), - ) - return nil, response.NewInvalidParamError(c, "INVALID PAYLOAD TYPE", errors.WithStack(err)) - } - return &payloadType, nil -} - func ExtractTimeSpan(c *fiber.Ctx, l *zap.Logger) (string, error) { // get the timeSpan from query params timeSpanStr := c.Query("timeSpan", "1d") diff --git a/api/routes/wormscan/operations/controller.go b/api/routes/wormscan/operations/controller.go index a34bbc20..39a7775a 100644 --- a/api/routes/wormscan/operations/controller.go +++ b/api/routes/wormscan/operations/controller.go @@ -54,17 +54,19 @@ func (c *Controller) FindAll(ctx *fiber.Ctx) error { return err } - chainID, err := middleware.ExtractChain(ctx, c.logger) + searchByAddress := address != "" + searchByTxHash := txHash != nil && txHash.String() != "" + + if searchByAddress && searchByTxHash { + return response.NewInvalidParamError(ctx, "address and txHash cannot be used at the same time", nil) + } + + sourceChain, err := middleware.ExtractSourceChain(ctx, c.logger) if err != nil { return err } - sourceChainID, err := middleware.ExtractSourceChain(ctx, c.logger) - if err != nil { - return err - } - - targeChainID, err := middleware.ExtractTargetChain(ctx, c.logger) + targetChain, err := middleware.ExtractTargetChain(ctx, c.logger) if err != nil { return err } @@ -75,39 +77,21 @@ func (c *Controller) FindAll(ctx *fiber.Ctx) error { return err } - payloadType, err := middleware.ExtractPayloadType(ctx, c.logger) - if err != nil { - return err - } + searchBySourceTargetChain := sourceChain != nil || targetChain != nil + searchByAppId := appID != "" - searchByAddress := address != "" - searchByTxHash := txHash != nil && txHash.String() != "" - searchByChainId := chainID != nil - searchBySourceAndTargetChain := sourceChainID != nil && targeChainID != nil - searchByAppID := len(appID) > 0 - searchByPayloadType := payloadType != nil - searchCriteria := []bool{searchByAddress, searchByTxHash, searchByChainId, searchByAppID, searchByPayloadType, searchBySourceAndTargetChain} - - searchCriteriaCount := 0 - for _, sc := range searchCriteria { - if sc { - searchCriteriaCount++ - } - } - if searchCriteriaCount > 1 { - return response.NewInvalidParamError(ctx, "only one search-criteria can be used at once", nil) + if (searchByAddress || searchByTxHash) && (searchBySourceTargetChain || searchByAppId) { + return response.NewInvalidParamError(ctx, "address/txHash cannot be combined with sourceChain/targetChain/appId query filter", nil) } filter := operations.OperationFilter{ TxHash: txHash, Address: address, - ChainID: chainID, - SourceChainID: sourceChainID, - TargetChainID: targeChainID, + SourceChainID: sourceChain, + TargetChainID: targetChain, AppID: appID, ExclusiveAppId: exclusiveAppId, Pagination: *pagination, - PayloadType: payloadType, } // Find operations by q search param.