Skip to content

Commit

Permalink
Add proxy endpoint to vaa payload parser
Browse files Browse the repository at this point in the history
  • Loading branch information
walker-16 committed Aug 1, 2023
1 parent d846e81 commit 9cdd866
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 2 deletions.
26 changes: 26 additions & 0 deletions api/docs/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions api/docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,32 @@
}
}
},
"/api/v1/vaas/parse": {
"post": {
"description": "Parse a VAA.",
"tags": [
"Wormscan"
],
"operationId": "parse-vaa",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response-array_vaa_VaaStats"
}
},
"400": {
"description": "Bad Request"
},
"404": {
"description": "Not Found"
},
"500": {
"description": "Internal Server Error"
}
}
}
},
"/api/v1/vaas/vaa-counts": {
"get": {
"description": "Returns the total number of VAAs emitted for each blockchain.",
Expand Down
17 changes: 17 additions & 0 deletions api/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1672,6 +1672,23 @@ paths:
description: Internal Server Error
tags:
- Wormscan
/api/v1/vaas/parse:
post:
description: Parse a VAA.
operationId: parse-vaa
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.Response-array_vaa_VaaStats'
"400":
description: Bad Request
"404":
description: Not Found
"500":
description: Internal Server Error
tags:
- Wormscan
/api/v1/vaas/vaa-counts:
get:
description: Returns the total number of VAAs emitted for each blockchain.
Expand Down
28 changes: 27 additions & 1 deletion api/handlers/vaa/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/wormhole-foundation/wormhole-explorer/api/response"
"github.com/wormhole-foundation/wormhole-explorer/api/types"
"github.com/wormhole-foundation/wormhole-explorer/common/client/cache"
vaaPayloadParser "github.com/wormhole-foundation/wormhole-explorer/common/client/parser"
"github.com/wormhole-foundation/wormhole/sdk/vaa"
"go.uber.org/zap"
)
Expand All @@ -19,15 +20,17 @@ import (
type Service struct {
repo *Repository
getCacheFunc cache.CacheGetFunc
parseVaaFunc vaaPayloadParser.ParseVaaFunc
logger *zap.Logger
}

// NewService creates a new VAA Service.
func NewService(r *Repository, getCacheFunc cache.CacheGetFunc, logger *zap.Logger) *Service {
func NewService(r *Repository, getCacheFunc cache.CacheGetFunc, parseVaaFunc vaaPayloadParser.ParseVaaFunc, logger *zap.Logger) *Service {

s := Service{
repo: r,
getCacheFunc: getCacheFunc,
parseVaaFunc: parseVaaFunc,
logger: logger.With(zap.String("module", "VaaService")),
}

Expand Down Expand Up @@ -228,3 +231,26 @@ func (s *Service) discardVaaNotIndexed(ctx context.Context, chain vaa.ChainID, e
}
return true
}

// ParseVaa parse a vaa payload.
func (s *Service) ParseVaa(ctx context.Context, vaaByte []byte) (any, error) {
// unmarshal vaa
vaa, err := vaa.Unmarshal(vaaByte)
if err != nil {
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
s.logger.Error("error unmarshal vaa to parse", zap.Error(err), zap.String("requestID", requestID))
return nil, errs.ErrInternalError
}

// call vaa payload parser api
parsedVaa, err := s.parseVaaFunc(vaa)
if err != nil {
if errors.Is(err, vaaPayloadParser.ErrNotFound) {
return nil, errs.ErrNotFound
}
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
s.logger.Error("error parse vaa", zap.Error(err), zap.String("requestID", requestID))
return nil, errs.ErrInternalError
}
return parsedVaa, nil
}
5 changes: 5 additions & 0 deletions api/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ type AppConfig struct {
Bucket30Days string
BucketInfinite string
}
VaaPayloadParser struct {
Enabled bool
URL string
Timeout int64
}
RateLimit struct {
Enabled bool
// Max number of requests per minute
Expand Down
25 changes: 24 additions & 1 deletion api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ import (
"github.com/wormhole-foundation/wormhole-explorer/api/routes/wormscan"
rpcApi "github.com/wormhole-foundation/wormhole-explorer/api/rpc"
wormscanCache "github.com/wormhole-foundation/wormhole-explorer/common/client/cache"
vaaPayloadParser "github.com/wormhole-foundation/wormhole-explorer/common/client/parser"
xlogger "github.com/wormhole-foundation/wormhole-explorer/common/logger"
"github.com/wormhole-foundation/wormhole-explorer/common/utils"
sdk "github.com/wormhole-foundation/wormhole/sdk/vaa"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -124,6 +126,12 @@ func main() {
rootLogger.Info("initializing InfluxDB client")
influxCli := newInfluxClient(cfg.Influx.URL, cfg.Influx.Token)

//VaaPayloadParser client
vaaParserFunc, err := NewVaaParserFunc(cfg, rootLogger)
if err != nil {
rootLogger.Fatal("failed to initialize VAA parser", zap.Error(err))
}

// Set up repositories
rootLogger.Info("initializing repositories")
addressRepo := address.NewRepository(db, rootLogger)
Expand All @@ -146,7 +154,7 @@ func main() {
// Set up services
rootLogger.Info("initializing services")
addressService := address.NewService(addressRepo, rootLogger)
vaaService := vaa.NewService(vaaRepo, cache.Get, rootLogger)
vaaService := vaa.NewService(vaaRepo, cache.Get, vaaParserFunc, rootLogger)
obsService := observations.NewService(obsRepo, rootLogger)
governorService := governor.NewService(governorRepo, rootLogger)
infrastructureService := infrastructure.NewService(infrastructureRepo, rootLogger)
Expand Down Expand Up @@ -301,3 +309,18 @@ func NewRateLimiter(ctx context.Context, cfg *config.AppConfig, logger *zap.Logg
return router, nil

}

// NewVaaParserFunc returns a function to parse VAA payload.
func NewVaaParserFunc(cfg *config.AppConfig, logger *zap.Logger) (vaaPayloadParser.ParseVaaFunc, error) {
if cfg.RunMode == config.RunModeDevelopmernt && !cfg.VaaPayloadParser.Enabled {
return func(vaa *sdk.VAA) (*vaaPayloadParser.ParseVaaWithStandarizedPropertiesdResponse, error) {
return &vaaPayloadParser.ParseVaaWithStandarizedPropertiesdResponse{}, nil
}, nil
}
vaaPayloadParserClient, err := vaaPayloadParser.NewParserVAAAPIClient(cfg.VaaPayloadParser.Timeout,
cfg.VaaPayloadParser.URL, logger)
if err != nil {
return nil, fmt.Errorf("failed to initialize VAA parser client: %w", err)
}
return vaaPayloadParserClient.ParseVaaWithStandarizedProperties, nil
}
18 changes: 18 additions & 0 deletions api/response/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,21 @@ func NewInvalidQueryParamError(ctx *fiber.Ctx, message string, err error) APIErr
Details: []ErrorDetail{detail},
}
}

func NewRequestBodyError(ctx *fiber.Ctx, message string, err error) APIError {
if message == "" {
message = "INVALID BODY"
}
detail := ErrorDetail{
RequestID: fmt.Sprintf("%v", ctx.Locals("requestid")),
}
if enableStackTrace && err != nil {
detail.StackTrace = fmt.Sprintf("%+v\n", err)
}
return APIError{
StatusCode: fiber.StatusBadRequest,
Code: InvalidParam,
Message: message,
Details: []ErrorDetail{detail},
}
}
1 change: 1 addition & 0 deletions api/routes/wormscan/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func RegisterRoutes(
vaas.Get("/:chain", vaaCtrl.FindByChain)
vaas.Get("/:chain/:emitter", vaaCtrl.FindByEmitter)
vaas.Get("/:chain/:emitter/:sequence", vaaCtrl.FindById)
vaas.Post("/parse", vaaCtrl.ParseVaa)

// oservations resource
observations := api.Group("/observations")
Expand Down
47 changes: 47 additions & 0 deletions api/routes/wormscan/vaa/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
package vaa

import (
"encoding/base64"
"strconv"

"github.com/gofiber/fiber/v2"
"github.com/pkg/errors"
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/vaa"
"github.com/wormhole-foundation/wormhole-explorer/api/middleware"
"github.com/wormhole-foundation/wormhole-explorer/api/response"
_ "github.com/wormhole-foundation/wormhole-explorer/api/response" // required by swaggo
"go.uber.org/zap"
)
Expand Down Expand Up @@ -190,3 +193,47 @@ func (c *Controller) GetVaaCount(ctx *fiber.Ctx) error {

return ctx.JSON(vaas)
}

// ParseVaa godoc
// @Description Parse a VAA.
// @Tags Wormscan
// @ID parse-vaa
// @Success 200 {object} response.Response[[]vaa.VaaStats]
// @Failure 400
// @Failure 404
// @Failure 500
// @Router /api/v1/vaas/parse [post]
func (c *Controller) ParseVaa(ctx *fiber.Ctx) error {

parseVaaBody := struct {
Vaa string `json:"vaa"`
}{}

err := ctx.BodyParser(&parseVaaBody)
if err != nil {
return response.NewRequestBodyError(ctx,
"invalid vaa request, unable to parse",
errors.WithStack(err))
}

if len(parseVaaBody.Vaa) == 0 {
return response.NewRequestBodyError(
ctx,
"invalid vaa request, vaa is empty",
nil)
}

vaa, err := base64.StdEncoding.DecodeString(parseVaaBody.Vaa)
if err != nil {
return response.NewRequestBodyError(ctx,
"invalid vaa request, vaa is not base64 encoded",
errors.WithStack(err))
}

parsedVaa, err := c.srv.ParseVaa(ctx.Context(), vaa)
if err != nil {
return err
}

return ctx.JSON(parsedVaa)
}
3 changes: 3 additions & 0 deletions common/client/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ type ParserVAAAPIClient struct {
Logger *zap.Logger
}

// ParseVaaFunc represent a parse vaa function.
type ParseVaaFunc func(vaa *sdk.VAA) (*ParseVaaWithStandarizedPropertiesdResponse, error)

// NewParserVAAAPIClient create new instances of ParserVAAAPIClient.
func NewParserVAAAPIClient(timeout int64, baseURL string, logger *zap.Logger) (ParserVAAAPIClient, error) {
if timeout == 0 {
Expand Down

0 comments on commit 9cdd866

Please sign in to comment.