2022-11-17 07:37:29 -08:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/ansrivas/fiberprometheus/v2"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
|
|
"github.com/gofiber/fiber/v2/middleware/cache"
|
|
|
|
"github.com/gofiber/fiber/v2/middleware/cors"
|
|
|
|
"github.com/gofiber/fiber/v2/middleware/logger"
|
|
|
|
"github.com/gofiber/fiber/v2/middleware/requestid"
|
|
|
|
ipfslog "github.com/ipfs/go-log/v2"
|
2022-11-23 04:06:29 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/governor"
|
2022-12-05 12:41:37 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/infraestructure"
|
2022-11-23 04:06:29 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/observations"
|
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/vaa"
|
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/internal/config"
|
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/internal/db"
|
2022-11-17 07:37:29 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/middleware"
|
2022-11-23 04:06:29 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
2022-11-17 07:37:29 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
var cacheConfig = cache.Config{
|
|
|
|
Next: func(c *fiber.Ctx) bool {
|
|
|
|
return c.Query("refresh") == "true"
|
|
|
|
},
|
|
|
|
Expiration: 1 * time.Second,
|
|
|
|
CacheControl: true,
|
|
|
|
StoreResponseHeaders: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
func healthOk(ctx *fiber.Ctx) error {
|
|
|
|
ctx.Status(200)
|
|
|
|
return ctx.SendString("Ok")
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
appCtx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
// Grab config
|
|
|
|
cfg, err := config.Get()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprint(os.Stderr, "Error parsing configuration")
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Logging
|
|
|
|
lvl, err := cfg.GetLogLevel()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(os.Stderr, "Invalid logging level set: %v", cfg.LogLevel)
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
rootLogger := ipfslog.Logger("wormhole-api").Desugar()
|
2022-11-17 07:37:29 -08:00
|
|
|
ipfslog.SetAllLoggers(lvl)
|
|
|
|
|
|
|
|
// Setup DB
|
|
|
|
cli, err := db.Connect(appCtx, cfg.DB.URL)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
db := cli.Database(cfg.DB.Name)
|
|
|
|
|
|
|
|
// Setup repositories
|
|
|
|
vaaRepo := vaa.NewRepository(db, rootLogger)
|
|
|
|
obsRepo := observations.NewRepository(db, rootLogger)
|
|
|
|
governorRepo := governor.NewRepository(db, rootLogger)
|
2022-12-05 12:41:37 -08:00
|
|
|
infraestructureRepo := infraestructure.NewRepository(db, rootLogger)
|
2022-11-17 07:37:29 -08:00
|
|
|
|
|
|
|
// Setup services
|
|
|
|
vaaService := vaa.NewService(vaaRepo, rootLogger)
|
|
|
|
obsService := observations.NewService(obsRepo, rootLogger)
|
|
|
|
governorService := governor.NewService(governorRepo, rootLogger)
|
2022-12-05 12:41:37 -08:00
|
|
|
infraestructureService := infraestructure.NewService(infraestructureRepo, rootLogger)
|
2022-11-17 07:37:29 -08:00
|
|
|
|
|
|
|
// Setup controllers
|
|
|
|
vaaCtrl := vaa.NewController(vaaService, rootLogger)
|
|
|
|
observationsCtrl := observations.NewController(obsService, rootLogger)
|
|
|
|
governorCtrl := governor.NewController(governorService, rootLogger)
|
2022-12-05 12:41:37 -08:00
|
|
|
infraestructureCtrl := infraestructure.NewController(infraestructureService)
|
2022-11-17 07:37:29 -08:00
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// Setup app with custom error handling.
|
|
|
|
response.SetEnableStackTrace(*cfg)
|
|
|
|
app := fiber.New(fiber.Config{ErrorHandler: middleware.ErrorHandler})
|
2022-11-17 07:37:29 -08:00
|
|
|
|
|
|
|
// Middleware
|
|
|
|
prometheus := fiberprometheus.New("wormscan")
|
|
|
|
prometheus.RegisterAt(app, "/metrics")
|
|
|
|
app.Use(prometheus.Middleware)
|
|
|
|
|
|
|
|
app.Use(requestid.New())
|
|
|
|
app.Use(logger.New(logger.Config{
|
|
|
|
Format: "level=info timestamp=${time} method=${method} path=${path} status${status} request_id=${locals:requestid}\n",
|
|
|
|
}))
|
|
|
|
|
|
|
|
api := app.Group("/api")
|
|
|
|
api.Use(cors.New()) // TODO CORS restrictions?
|
|
|
|
api.Use(middleware.ExtractPagination)
|
|
|
|
|
2022-12-05 12:41:37 -08:00
|
|
|
api.Get("/health", infraestructureCtrl.HealthCheck)
|
|
|
|
api.Get("/ready", infraestructureCtrl.ReadyCheck)
|
2022-11-17 07:37:29 -08:00
|
|
|
|
|
|
|
// vaas resource
|
|
|
|
vaas := api.Group("/vaas")
|
|
|
|
vaas.Use(cache.New(cacheConfig))
|
2022-11-23 05:15:16 -08:00
|
|
|
vaas.Get("/vaa-counts", vaaCtrl.GetVaaCount)
|
2022-11-17 07:37:29 -08:00
|
|
|
vaas.Get("/", vaaCtrl.FindAll)
|
|
|
|
vaas.Get("/:chain", vaaCtrl.FindByChain)
|
|
|
|
vaas.Get("/:chain/:emitter", vaaCtrl.FindByEmitter)
|
|
|
|
vaas.Get("/:chain/:emitter/:sequence", vaaCtrl.FindById)
|
2022-11-23 05:15:16 -08:00
|
|
|
vaas.Get("vaas-sans-pythnet", vaaCtrl.FindForPythnet)
|
2022-11-17 07:37:29 -08:00
|
|
|
|
|
|
|
// oservations resource
|
|
|
|
observations := api.Group("/observations")
|
|
|
|
observations.Get("/", observationsCtrl.FindAll)
|
|
|
|
observations.Get("/:chain", observationsCtrl.FindAllByChain)
|
|
|
|
observations.Get("/:chain/:emitter", observationsCtrl.FindAllByEmitter)
|
|
|
|
observations.Get("/:chain/:emitter/:sequence", observationsCtrl.FindAllByVAA)
|
|
|
|
observations.Get("/:chain/:emitter/:sequence/:signer/:hash", observationsCtrl.FindOne)
|
|
|
|
|
|
|
|
// governor resources
|
|
|
|
governor := api.Group("governor")
|
|
|
|
governorLimit := governor.Group("/limit")
|
|
|
|
governorLimit.Get("/", governorCtrl.GetGovernorLimit)
|
|
|
|
|
|
|
|
governorConfigs := governor.Group("/config")
|
|
|
|
governorConfigs.Get("/", governorCtrl.FindGovernorConfigurations)
|
|
|
|
governorConfigs.Get("/:guardian_address", governorCtrl.FindGovernorConfigurationByGuardianAddress)
|
|
|
|
|
|
|
|
governorStatus := governor.Group("/status")
|
|
|
|
governorStatus.Get("/", governorCtrl.FindGovernorStatus)
|
|
|
|
governorStatus.Get("/:guardian_address", governorCtrl.FindGovernorStatusByGuardianAddress)
|
|
|
|
|
|
|
|
governorNotional := governor.Group("/notional")
|
|
|
|
governorNotional.Get("/limit/", governorCtrl.FindNotionalLimit)
|
|
|
|
governorNotional.Get("/limit/:chain", governorCtrl.GetNotionalLimitByChainID)
|
|
|
|
governorNotional.Get("/available/", governorCtrl.GetAvailableNotional)
|
|
|
|
governorNotional.Get("/available/:chain", governorCtrl.GetAvailableNotionalByChainID)
|
|
|
|
governorNotional.Get("/max_available/:chain", governorCtrl.GetMaxNotionalAvailableByChainID)
|
|
|
|
|
|
|
|
enqueueVaas := governor.Group("/enqueued_vaas")
|
|
|
|
enqueueVaas.Get("/", governorCtrl.GetEnqueueVass)
|
|
|
|
enqueueVaas.Get("/:chain", governorCtrl.GetEnqueueVassByChainID)
|
|
|
|
|
|
|
|
// v1 guardian api.
|
|
|
|
apiV1 := api.Group("/v1")
|
|
|
|
signedVAA := apiV1.Group("/signed_vaa")
|
|
|
|
signedVAA.Get("/:chain/:emitter/:sequence", vaaCtrl.FindSignedVAAByID)
|
|
|
|
|
|
|
|
app.Listen(":" + strconv.Itoa(cfg.PORT))
|
|
|
|
}
|