2022-11-17 07:37:29 -08:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-01-26 07:04:01 -08:00
|
|
|
_ "embed"
|
2022-11-17 07:37:29 -08:00
|
|
|
"fmt"
|
2023-01-23 06:45:09 -08:00
|
|
|
"net/http"
|
2022-11-17 07:37:29 -08:00
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"github.com/ansrivas/fiberprometheus/v2"
|
2023-01-23 06:45:09 -08:00
|
|
|
"github.com/gofiber/adaptor/v2"
|
2022-11-17 07:37:29 -08:00
|
|
|
"github.com/gofiber/fiber/v2"
|
|
|
|
"github.com/gofiber/fiber/v2/middleware/cors"
|
|
|
|
"github.com/gofiber/fiber/v2/middleware/logger"
|
2023-02-03 10:18:44 -08:00
|
|
|
"github.com/gofiber/fiber/v2/middleware/pprof"
|
2022-11-17 07:37:29 -08:00
|
|
|
"github.com/gofiber/fiber/v2/middleware/requestid"
|
2023-01-23 06:45:09 -08:00
|
|
|
"github.com/improbable-eng/grpc-web/go/grpcweb"
|
|
|
|
|
2023-03-07 11:25:42 -08:00
|
|
|
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
|
2022-11-23 04:06:29 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/governor"
|
2023-01-03 09:42:29 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/heartbeats"
|
2023-01-26 06:00:02 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/infrastructure"
|
2022-11-23 04:06:29 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/observations"
|
2023-03-07 11:25:42 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/transactions"
|
2022-11-23 04:06:29 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/vaa"
|
2023-01-05 11:40:24 -08:00
|
|
|
wormscanCache "github.com/wormhole-foundation/wormhole-explorer/api/internal/cache"
|
2022-11-23 04:06:29 -08:00
|
|
|
"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"
|
2023-01-27 07:58:37 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/routes/guardian"
|
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/routes/wormscan"
|
2023-01-23 06:45:09 -08:00
|
|
|
rpcApi "github.com/wormhole-foundation/wormhole-explorer/api/rpc"
|
2023-03-23 11:36:50 -07:00
|
|
|
xlogger "github.com/wormhole-foundation/wormhole-explorer/common/logger"
|
|
|
|
|
2023-01-05 11:40:24 -08:00
|
|
|
"go.uber.org/zap"
|
2022-11-17 07:37:29 -08:00
|
|
|
)
|
|
|
|
|
2023-01-26 07:04:01 -08:00
|
|
|
//go:embed docs/swagger.json
|
|
|
|
var swagger []byte
|
|
|
|
|
|
|
|
// GetSwagger godoc
|
|
|
|
// @Description Returns the swagger specification for this API.
|
|
|
|
// @Tags Wormscan
|
|
|
|
// @ID swagger
|
|
|
|
// @Success 200 {object} object
|
|
|
|
// @Failure 400
|
|
|
|
// @Failure 500
|
|
|
|
// @Router /swagger.json [get]
|
|
|
|
func GetSwagger(ctx *fiber.Ctx) error {
|
|
|
|
|
|
|
|
written, err := ctx.
|
|
|
|
Response().
|
|
|
|
BodyWriter().
|
|
|
|
Write(swagger)
|
|
|
|
|
|
|
|
if written != len(swagger) {
|
|
|
|
return fmt.Errorf("partial write to response body: wrote %d bytes, expected %d", written, len(swagger))
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-01-10 07:32:07 -08:00
|
|
|
// @title Wormhole Guardian API
|
|
|
|
// @version 1.0
|
|
|
|
// @description Wormhole Guardian API
|
|
|
|
// @description To get information from the Wormhole Network.
|
|
|
|
// @description Check each endpoint documentation for more information.
|
|
|
|
// @termsOfService https://wormhole.com/
|
|
|
|
// @contact.name API Support
|
|
|
|
// @contact.url http://wormhole.com/support
|
|
|
|
// @contact.email info@wormhole.com
|
|
|
|
// @license.name Apache 2.0
|
|
|
|
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
|
|
|
|
// @BasePath /v1
|
2022-11-17 07:37:29 -08:00
|
|
|
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
|
2023-03-23 11:36:50 -07:00
|
|
|
rootLogger := xlogger.New("wormhole-api", xlogger.WithLevel(cfg.LogLevel))
|
2022-11-17 07:37:29 -08:00
|
|
|
|
|
|
|
// Setup DB
|
|
|
|
cli, err := db.Connect(appCtx, cfg.DB.URL)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
db := cli.Database(cfg.DB.Name)
|
|
|
|
|
2023-01-05 11:40:24 -08:00
|
|
|
// Get cache get function
|
|
|
|
cacheGetFunc := NewCache(cfg, rootLogger)
|
|
|
|
|
2023-03-07 11:25:42 -08:00
|
|
|
//InfluxDB client
|
|
|
|
influxCli := newInfluxClient(cfg.Influx.URL, cfg.Influx.Token)
|
|
|
|
|
2023-01-27 07:58:37 -08:00
|
|
|
// Set up repositories
|
2022-11-17 07:37:29 -08:00
|
|
|
vaaRepo := vaa.NewRepository(db, rootLogger)
|
|
|
|
obsRepo := observations.NewRepository(db, rootLogger)
|
|
|
|
governorRepo := governor.NewRepository(db, rootLogger)
|
2023-01-26 06:00:02 -08:00
|
|
|
infrastructureRepo := infrastructure.NewRepository(db, rootLogger)
|
2023-01-03 09:42:29 -08:00
|
|
|
heartbeatsRepo := heartbeats.NewRepository(db, rootLogger)
|
2023-03-15 12:52:50 -07:00
|
|
|
transactionsRepo := transactions.NewRepository(influxCli, cfg.Influx.Organization, cfg.Influx.Bucket, db, rootLogger)
|
2022-11-17 07:37:29 -08:00
|
|
|
|
2023-01-27 07:58:37 -08:00
|
|
|
// Set up services
|
2023-01-05 11:40:24 -08:00
|
|
|
vaaService := vaa.NewService(vaaRepo, cacheGetFunc, rootLogger)
|
2022-11-17 07:37:29 -08:00
|
|
|
obsService := observations.NewService(obsRepo, rootLogger)
|
|
|
|
governorService := governor.NewService(governorRepo, rootLogger)
|
2023-01-26 06:00:02 -08:00
|
|
|
infrastructureService := infrastructure.NewService(infrastructureRepo, rootLogger)
|
2023-01-03 09:42:29 -08:00
|
|
|
heartbeatsService := heartbeats.NewService(heartbeatsRepo, rootLogger)
|
2023-03-07 11:25:42 -08:00
|
|
|
transactionsService := transactions.NewService(transactionsRepo, rootLogger)
|
2022-11-17 07:37:29 -08:00
|
|
|
|
2023-01-27 07:58:37 -08:00
|
|
|
// Set up a custom error handler
|
2022-11-23 04:06:29 -08:00
|
|
|
response.SetEnableStackTrace(*cfg)
|
|
|
|
app := fiber.New(fiber.Config{ErrorHandler: middleware.ErrorHandler})
|
2022-11-17 07:37:29 -08:00
|
|
|
|
2023-01-27 07:58:37 -08:00
|
|
|
// Configure middleware
|
2022-11-17 07:37:29 -08:00
|
|
|
prometheus := fiberprometheus.New("wormscan")
|
|
|
|
prometheus.RegisterAt(app, "/metrics")
|
|
|
|
app.Use(prometheus.Middleware)
|
2023-01-26 09:55:27 -08:00
|
|
|
app.Use(cors.New())
|
2022-11-17 07:37:29 -08:00
|
|
|
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",
|
|
|
|
}))
|
2023-02-03 10:18:44 -08:00
|
|
|
if cfg.PprofEnabled {
|
|
|
|
app.Use(pprof.New())
|
|
|
|
}
|
2022-11-17 07:37:29 -08:00
|
|
|
|
2023-01-27 07:58:37 -08:00
|
|
|
// Set up route handlers
|
2023-01-26 07:04:01 -08:00
|
|
|
app.Get("/swagger.json", GetSwagger)
|
2023-03-07 11:25:42 -08:00
|
|
|
wormscan.RegisterRoutes(app, rootLogger, vaaService, obsService, governorService, infrastructureService, transactionsService)
|
2023-01-31 06:38:17 -08:00
|
|
|
guardian.RegisterRoutes(cfg, app, rootLogger, vaaService, governorService, heartbeatsService)
|
2023-01-26 05:32:20 -08:00
|
|
|
|
2023-01-27 07:58:37 -08:00
|
|
|
// Set up gRPC handlers
|
2023-01-31 06:38:17 -08:00
|
|
|
handler := rpcApi.NewHandler(vaaService, heartbeatsService, governorService, rootLogger, cfg.P2pNetwork)
|
2023-01-23 06:45:09 -08:00
|
|
|
grpcServer := rpcApi.NewServer(handler, rootLogger)
|
|
|
|
grpcWebServer := grpcweb.WrapServer(grpcServer)
|
|
|
|
app.Use(
|
|
|
|
adaptor.HTTPMiddleware(func(next http.Handler) http.Handler {
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if grpcWebServer.IsGrpcWebRequest(r) {
|
|
|
|
grpcWebServer.ServeHTTP(w, r)
|
|
|
|
} else {
|
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}))
|
|
|
|
|
|
|
|
rootLogger.Fatal("http listen", zap.Error(app.Listen(":"+strconv.Itoa(cfg.PORT))))
|
2022-11-17 07:37:29 -08:00
|
|
|
}
|
2023-01-05 11:40:24 -08:00
|
|
|
|
|
|
|
// NewCache return a CacheGetFunc to get a value by a Key from cache.
|
|
|
|
func NewCache(cfg *config.AppConfig, looger *zap.Logger) wormscanCache.CacheGetFunc {
|
|
|
|
if cfg.RunMode == config.RunModeDevelopmernt && !cfg.Cache.Enabled {
|
|
|
|
dummyCacheClient := wormscanCache.NewDummyCacheClient()
|
|
|
|
return dummyCacheClient.Get
|
|
|
|
}
|
|
|
|
cacheClient := wormscanCache.NewCacheClient(cfg.Cache.URL, cfg.Cache.Enabled, looger)
|
|
|
|
return cacheClient.Get
|
|
|
|
}
|
2023-03-07 11:25:42 -08:00
|
|
|
|
|
|
|
func newInfluxClient(url, token string) influxdb2.Client {
|
|
|
|
return influxdb2.NewClient(url, token)
|
|
|
|
}
|