2022-11-23 04:06:29 -08:00
|
|
|
// Package governor handle the request of governor data from governor endpoint defined in the api.
|
2022-11-17 07:37:29 -08:00
|
|
|
package governor
|
|
|
|
|
|
|
|
import (
|
2023-01-03 09:42:29 -08:00
|
|
|
"strconv"
|
|
|
|
|
2022-11-17 07:37:29 -08:00
|
|
|
"github.com/gofiber/fiber/v2"
|
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/api/middleware"
|
2023-01-23 06:45:09 -08:00
|
|
|
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
2022-11-17 07:37:29 -08:00
|
|
|
"go.uber.org/zap"
|
|
|
|
)
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// Controller definition.
|
2022-11-17 07:37:29 -08:00
|
|
|
type Controller struct {
|
|
|
|
srv *Service
|
|
|
|
logger *zap.Logger
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// NewController create a new controler.
|
2022-11-17 07:37:29 -08:00
|
|
|
func NewController(serv *Service, logger *zap.Logger) *Controller {
|
|
|
|
return &Controller{srv: serv, logger: logger.With(zap.String("module", "GovernorController"))}
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// FindGovernorConfigurations handler for the endpoint /governor/config/
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) FindGovernorConfigurations(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
2022-11-17 07:37:29 -08:00
|
|
|
governorConfigs, err := c.srv.FindGovernorConfig(ctx.Context(), p)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(governorConfigs)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// FindGovernorConfigurationByGuardianAddress handler for the endpoint /governor/config/:guardian_address.
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) FindGovernorConfigurationByGuardianAddress(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
|
|
|
guardianAddress, err := middleware.ExtractGuardianAddress(ctx, c.logger)
|
2022-11-17 07:37:29 -08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
govConfig, err := c.srv.FindGovernorConfigByGuardianAddress(ctx.Context(), guardianAddress, p)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(govConfig)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// FindGovernorStatus handler for the endpoint /governor/status/.
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) FindGovernorStatus(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
2022-11-17 07:37:29 -08:00
|
|
|
governorStatus, err := c.srv.FindGovernorStatus(ctx.Context(), p)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(governorStatus)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// FindGovernorStatusByGuardianAddress handler for the endpoint /governor/status/:guardian_address.
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) FindGovernorStatusByGuardianAddress(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
|
|
|
guardianAddress, err := middleware.ExtractGuardianAddress(ctx, c.logger)
|
2022-11-17 07:37:29 -08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
govStatus, err := c.srv.FindGovernorStatusByGuardianAddress(ctx.Context(), guardianAddress, p)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(govStatus)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// GetGovernorLimit handler for the endpoint /governor/limit/
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) GetGovernorLimit(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
2022-11-17 07:37:29 -08:00
|
|
|
governorLimit, err := c.srv.GetGovernorLimit(ctx.Context(), p)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(governorLimit)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// FindNotionalLimit handler for the endpoint governor/notional/limit/
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) FindNotionalLimit(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
2022-11-17 07:37:29 -08:00
|
|
|
notionalLimit, err := c.srv.FindNotionalLimit(ctx.Context(), p)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(notionalLimit)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// GetNotionalLimitByChainID handler for the endpoint governor/notional/limit/:chain.
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) GetNotionalLimitByChainID(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
|
|
|
chainID, err := middleware.ExtractChainID(ctx, c.logger)
|
2022-11-17 07:37:29 -08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
notionalLimit, err := c.srv.GetNotionalLimitByChainID(ctx.Context(), p, chainID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(notionalLimit)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// GetAvailableNotional handler for the endpoint governor/notional/available/
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) GetAvailableNotional(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
2022-11-17 07:37:29 -08:00
|
|
|
notionalAvaialabilies, err := c.srv.GetAvailableNotional(ctx.Context(), p)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(notionalAvaialabilies)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// GetAvailableNotionalByChainID handler for the endpoint governor/notional/available/:chain
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) GetAvailableNotionalByChainID(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
|
|
|
chainID, err := middleware.ExtractChainID(ctx, c.logger)
|
2022-11-17 07:37:29 -08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
response, err := c.srv.GetAvailableNotionalByChainID(ctx.Context(), p, chainID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(response)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// GetMaxNotionalAvailableByChainID handler for the endpoint governor/max_available/:chain.
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) GetMaxNotionalAvailableByChainID(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
|
|
|
chainID, err := middleware.ExtractChainID(ctx, c.logger)
|
2022-11-17 07:37:29 -08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
response, err := c.srv.GetMaxNotionalAvailableByChainID(ctx.Context(), p, chainID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(response)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// GetEnqueueVass handler for the endpoint governor/enqueued_vaas/
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) GetEnqueueVass(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
2022-11-17 07:37:29 -08:00
|
|
|
enqueuedVaas, err := c.srv.GetEnqueueVass(ctx.Context(), p)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(enqueuedVaas)
|
|
|
|
}
|
|
|
|
|
2022-11-23 04:06:29 -08:00
|
|
|
// GetEnqueueVassByChainID handler for the endpoint governor/enqueued_vaas/:chain.
|
2022-11-17 07:37:29 -08:00
|
|
|
func (c *Controller) GetEnqueueVassByChainID(ctx *fiber.Ctx) error {
|
2022-11-23 04:06:29 -08:00
|
|
|
p := middleware.GetPaginationFromContext(ctx)
|
|
|
|
chainID, err := middleware.ExtractChainID(ctx, c.logger)
|
2022-11-17 07:37:29 -08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
enqueuedVaas, err := c.srv.GetEnqueueVassByChainID(ctx.Context(), p, chainID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return ctx.JSON(enqueuedVaas)
|
|
|
|
}
|
2023-01-03 09:42:29 -08:00
|
|
|
|
|
|
|
// AvailableNotionalResponse response compatible with grpc api.
|
|
|
|
type AvailableNotionalResponse struct {
|
|
|
|
Entries []*AvailableNotionalItemResponse `json:"entries"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type AvailableNotionalItemResponse struct {
|
|
|
|
ChainID vaa.ChainID `json:"chainId"`
|
|
|
|
AvailableNotional string `json:"remainingAvailableNotional"`
|
|
|
|
NotionalLimit string `json:"notionalLimit"`
|
|
|
|
MaxTransactionSize string `json:"bigTransactionSize"`
|
|
|
|
}
|
|
|
|
|
2023-01-10 07:32:07 -08:00
|
|
|
// GetAvailNotionByChain godoc
|
|
|
|
// @Description Get available notional by chainID
|
|
|
|
// @Description Since from the wormhole-explorer point of view it is not a node, but has the information of all nodes,
|
|
|
|
// @Description in order to build the endpoints it was assumed:
|
|
|
|
// @Description There are N number of remainingAvailableNotional values in the GovernorConfig collection. N = number of guardians
|
|
|
|
// @Description for a chainID. The smallest remainingAvailableNotional value for a chainID is used for the endpoint response.
|
|
|
|
// @Tags Guardian
|
|
|
|
// @ID governor-available-notional-by-chain
|
|
|
|
// @Success 200 {object} AvailableNotionalResponse
|
|
|
|
// @Failure 400
|
|
|
|
// @Failure 500
|
|
|
|
// @Router /v1/governor/available_notional_by_chain [get]
|
2023-01-03 09:42:29 -08:00
|
|
|
func (c *Controller) GetAvailNotionByChain(ctx *fiber.Ctx) error {
|
|
|
|
// call service to get available notional by chainID
|
|
|
|
availableNotional, err := c.srv.GetAvailNotionByChain(ctx.Context())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// build response compatible with node grpc api.
|
|
|
|
entries := make([]*AvailableNotionalItemResponse, 0, len(availableNotional))
|
|
|
|
for _, v := range availableNotional {
|
|
|
|
r := AvailableNotionalItemResponse{
|
|
|
|
ChainID: v.ChainID,
|
|
|
|
AvailableNotional: v.AvailableNotional.String(),
|
|
|
|
NotionalLimit: v.NotionalLimit.String(),
|
|
|
|
MaxTransactionSize: v.MaxTransactionSize.String(),
|
|
|
|
}
|
|
|
|
entries = append(entries, &r)
|
|
|
|
}
|
|
|
|
response := AvailableNotionalResponse{
|
|
|
|
Entries: entries,
|
|
|
|
}
|
|
|
|
return ctx.JSON(response)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AvailableNotionalResponse response compatible with grpc api.
|
|
|
|
type EnqueuedVaaResponse struct {
|
|
|
|
Entries []*EnqueuedVaaItemResponse `json:"entries"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type EnqueuedVaaItemResponse struct {
|
|
|
|
EmitterChain vaa.ChainID `json:"emitterChain"`
|
|
|
|
EmitterAddress string `json:"emitterAddress"`
|
|
|
|
Sequence uint64 `json:"sequence"`
|
|
|
|
ReleaseTime int64 `json:"releaseTime"`
|
|
|
|
NotionalValue string `json:"notionalValue"`
|
|
|
|
TxHash string `json:"txHash"`
|
|
|
|
}
|
|
|
|
|
2023-01-10 07:32:07 -08:00
|
|
|
// GetEnqueuedVaas godoc
|
|
|
|
// @Description Get enqueued vaa's
|
|
|
|
// @Tags Guardian
|
|
|
|
// @ID guardians-enqueued-vaas
|
|
|
|
// @Success 200 {object} EnqueuedVaaResponse
|
|
|
|
// @Failure 400
|
|
|
|
// @Failure 500
|
|
|
|
// @Router /v1/governor/enqueued_vaas [get]
|
2023-01-03 09:42:29 -08:00
|
|
|
func (c *Controller) GetEnqueuedVaas(ctx *fiber.Ctx) error {
|
|
|
|
enqueuedVaa, err := c.srv.GetEnqueuedVaas(ctx.Context())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// build response compatible with node grpc api.
|
|
|
|
entries := make([]*EnqueuedVaaItemResponse, 0, len(enqueuedVaa))
|
|
|
|
for _, v := range enqueuedVaa {
|
|
|
|
seqUint64, err := strconv.ParseUint(v.Sequence, 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
r := EnqueuedVaaItemResponse{
|
|
|
|
EmitterChain: v.EmitterChain,
|
|
|
|
EmitterAddress: v.EmitterAddress,
|
|
|
|
Sequence: seqUint64,
|
|
|
|
ReleaseTime: v.ReleaseTime,
|
|
|
|
NotionalValue: v.NotionalValue.String(),
|
|
|
|
TxHash: v.TxHash,
|
|
|
|
}
|
|
|
|
entries = append(entries, &r)
|
|
|
|
}
|
|
|
|
response := EnqueuedVaaResponse{
|
|
|
|
Entries: entries,
|
|
|
|
}
|
|
|
|
|
|
|
|
return ctx.JSON(response)
|
|
|
|
}
|
|
|
|
|
2023-01-10 07:32:07 -08:00
|
|
|
// IsVaaEnqueued godoc
|
|
|
|
// @Description Check if vaa is enqueued
|
|
|
|
// @Tags Guardian
|
|
|
|
// @ID guardians-is-vaa-enqueued
|
|
|
|
// @Param chain_id path integer true "id of the blockchain"
|
|
|
|
// @Param emitter path string true "address of the emitter"
|
|
|
|
// @Param seq path integer true "sequence of the vaa"
|
|
|
|
// @Success 200 {object} EnqueuedVaaResponse
|
|
|
|
// @Failure 400
|
|
|
|
// @Failure 500
|
|
|
|
// @Router /v1/governor/is_vaa_enqueued/{chain_id}/{emitter}/{seq} [get]
|
2023-01-03 09:42:29 -08:00
|
|
|
func (c *Controller) IsVaaEnqueued(ctx *fiber.Ctx) error {
|
|
|
|
chainID, emitter, seq, err := middleware.ExtractVAAParams(ctx, c.logger)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
isEnqueued, err := c.srv.IsVaaEnqueued(ctx.Context(), chainID, *emitter, strconv.FormatUint(seq, 10))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// build reponse compatible with node grpc api.
|
|
|
|
response := struct {
|
|
|
|
IsEnqueued bool `json:"isEnqueued"`
|
|
|
|
}{
|
|
|
|
IsEnqueued: isEnqueued,
|
|
|
|
}
|
|
|
|
return ctx.JSON(response)
|
|
|
|
}
|
|
|
|
|
2023-01-10 07:32:07 -08:00
|
|
|
// GetTokenList godoc
|
|
|
|
// @Description Get token list
|
|
|
|
// @Description Since from the wormhole-explorer point of view it is not a node, but has the information of all nodes,
|
|
|
|
// @Description in order to build the endpoints it was assumed:
|
|
|
|
// @Description For tokens with the same originChainId and originAddress and different price values for each node,
|
|
|
|
// @Description the price that has most occurrences in all the nodes for an originChainId and originAddress is returned.
|
|
|
|
// @Tags Guardian
|
|
|
|
// @ID guardians-token-list
|
|
|
|
// @Success 200 {object} []TokenList
|
|
|
|
// @Failure 400
|
|
|
|
// @Failure 500
|
|
|
|
// @Router /v1/governor/token_list [get]
|
2023-01-03 09:42:29 -08:00
|
|
|
func (c *Controller) GetTokenList(ctx *fiber.Ctx) error {
|
|
|
|
tokenList, err := c.srv.GetTokenList(ctx.Context())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// build reponse compatible with node grpc api.
|
|
|
|
response := struct {
|
|
|
|
Entries []*TokenList `json:"entries"`
|
|
|
|
}{
|
|
|
|
Entries: tokenList,
|
|
|
|
}
|
|
|
|
return ctx.JSON(response)
|
|
|
|
}
|