Skip to content

Commit

Permalink
Create an api endpoint to call vaa payload parser component (#596)
Browse files Browse the repository at this point in the history
* move vaa payload parser to common

* Add proxy endpoint to vaa payload parser

* Modify api deployment

* fix docs

* Fix swagger documentation
  • Loading branch information
walker-16 committed Aug 10, 2023
1 parent 0d2b5bd commit 87fd9d1
Show file tree
Hide file tree
Showing 20 changed files with 387 additions and 40 deletions.
76 changes: 76 additions & 0 deletions api/docs/docs.go

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

76 changes: 76 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/parser.ParseVaaWithStandarizedPropertiesdResponse"
}
},
"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 Expand Up @@ -2293,6 +2319,56 @@
}
}
},
"parser.ParseVaaWithStandarizedPropertiesdResponse": {
"type": "object",
"properties": {
"parsedPayload": {},
"standardizedProperties": {
"$ref": "#/definitions/parser.StandardizedProperties"
}
}
},
"parser.StandardizedProperties": {
"type": "object",
"properties": {
"amount": {
"type": "string"
},
"appIds": {
"type": "array",
"items": {
"type": "string"
}
},
"fee": {
"type": "string"
},
"feeAddress": {
"type": "string"
},
"feeChain": {
"$ref": "#/definitions/vaa.ChainID"
},
"fromAddress": {
"type": "string"
},
"fromChain": {
"$ref": "#/definitions/vaa.ChainID"
},
"toAddress": {
"type": "string"
},
"toChain": {
"$ref": "#/definitions/vaa.ChainID"
},
"tokenAddress": {
"type": "string"
},
"tokenChain": {
"$ref": "#/definitions/vaa.ChainID"
}
}
},
"response.Response-address_AddressOverview": {
"type": "object",
"properties": {
Expand Down
50 changes: 50 additions & 0 deletions api/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,39 @@ definitions:
updatedAt:
type: string
type: object
parser.ParseVaaWithStandarizedPropertiesdResponse:
properties:
parsedPayload: {}
standardizedProperties:
$ref: '#/definitions/parser.StandardizedProperties'
type: object
parser.StandardizedProperties:
properties:
amount:
type: string
appIds:
items:
type: string
type: array
fee:
type: string
feeAddress:
type: string
feeChain:
$ref: '#/definitions/vaa.ChainID'
fromAddress:
type: string
fromChain:
$ref: '#/definitions/vaa.ChainID'
toAddress:
type: string
toChain:
$ref: '#/definitions/vaa.ChainID'
tokenAddress:
type: string
tokenChain:
$ref: '#/definitions/vaa.ChainID'
type: object
response.Response-address_AddressOverview:
properties:
data:
Expand Down Expand Up @@ -1676,6 +1709,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/parser.ParseVaaWithStandarizedPropertiesdResponse'
"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"
sdk "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 @@ -245,3 +248,26 @@ func (s *Service) discardVaaNotIndexed(ctx context.Context, chain sdk.ChainID, e
}
return true
}

// ParseVaa parse a vaa payload.
func (s *Service) ParseVaa(ctx context.Context, vaaByte []byte) (vaaPayloadParser.ParseVaaWithStandarizedPropertiesdResponse, error) {
// unmarshal vaa
vaa, err := sdk.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 vaaPayloadParser.ParseVaaWithStandarizedPropertiesdResponse{}, errs.ErrInternalError
}

// call vaa payload parser api
parsedVaa, err := s.parseVaaFunc(vaa)
if err != nil {
if errors.Is(err, vaaPayloadParser.ErrNotFound) {
return vaaPayloadParser.ParseVaaWithStandarizedPropertiesdResponse{}, errs.ErrNotFound
}
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
s.logger.Error("error parse vaa", zap.Error(err), zap.String("requestID", requestID))
return vaaPayloadParser.ParseVaaWithStandarizedPropertiesdResponse{}, 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 @@ -39,9 +39,11 @@ 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"
"github.com/wormhole-foundation/wormhole-explorer/common/dbutil"
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 @@ -123,6 +125,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.Database, rootLogger)
Expand All @@ -145,7 +153,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 @@ -313,3 +321,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
Loading

0 comments on commit 87fd9d1

Please sign in to comment.