[API] Accept additional address formats (#170)
### Summary Context: https://github.com/wormhole-foundation/wormhole-explorer/issues/154 This PR modifies all endpoints that receive an emitter/guardian address to accept a wider range of formats. After this pull request, all of these are equivalent: * `0x000000000000000000000000f890982f9310df57d00f659cf4fd87e65aded8d7` * `000000000000000000000000f890982f9310df57d00f659cf4fd87e65aded8d7` * `0xf890982f9310df57d00f659cf4fd87e65aded8d7` * `f890982f9310df57d00f659cf4fd87e65aded8d7` ### Testing plan * Added unit tests for the parsing code. * Tested manually a few of the affected endpoints.
This commit is contained in:
parent
b1583d5e21
commit
533b83ad28
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
errs "github.com/wormhole-foundation/wormhole-explorer/api/internal/errors"
|
errs "github.com/wormhole-foundation/wormhole-explorer/api/internal/errors"
|
||||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
||||||
|
"github.com/wormhole-foundation/wormhole-explorer/api/types"
|
||||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
@ -1603,7 +1604,7 @@ type EnqueuedResponse struct {
|
||||||
func (r *Repository) IsVaaEnqueued(
|
func (r *Repository) IsVaaEnqueued(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chainID vaa.ChainID,
|
chainID vaa.ChainID,
|
||||||
emitter vaa.Address,
|
emitter *types.Address,
|
||||||
sequence string,
|
sequence string,
|
||||||
) (bool, error) {
|
) (bool, error) {
|
||||||
|
|
||||||
|
@ -1636,7 +1637,7 @@ func (r *Repository) IsVaaEnqueued(
|
||||||
matchStage6 := bson.D{
|
matchStage6 := bson.D{
|
||||||
{"$match", bson.D{
|
{"$match", bson.D{
|
||||||
{"chainid", chainID},
|
{"chainid", chainID},
|
||||||
{"emitters.emitteraddress", fmt.Sprintf("0x%s", emitter.String())},
|
{"emitters.emitteraddress", fmt.Sprintf("0x%s", emitter.ShortHex())},
|
||||||
{"emitters.enqueuedvaas.sequence", sequence},
|
{"emitters.enqueuedvaas.sequence", sequence},
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
||||||
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
||||||
|
"github.com/wormhole-foundation/wormhole-explorer/api/types"
|
||||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -62,9 +63,16 @@ func (s *Service) FindGovernorStatus(ctx context.Context, p *pagination.Paginati
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindGovernorStatusByGuardianAddress get a governor status by guardianAddress.
|
// FindGovernorStatusByGuardianAddress get a governor status by guardianAddress.
|
||||||
func (s *Service) FindGovernorStatusByGuardianAddress(ctx context.Context, guardianAddress string, p *pagination.Pagination) (*response.Response[*GovStatus], error) {
|
func (s *Service) FindGovernorStatusByGuardianAddress(
|
||||||
|
ctx context.Context,
|
||||||
|
guardianAddress string,
|
||||||
|
p *pagination.Pagination,
|
||||||
|
) (*response.Response[*GovStatus], error) {
|
||||||
|
|
||||||
query := QueryGovernor().SetID(guardianAddress).SetPagination(p)
|
query := QueryGovernor().SetID(guardianAddress).SetPagination(p)
|
||||||
|
|
||||||
govStatus, err := s.repo.FindOneGovernorStatus(ctx, query)
|
govStatus, err := s.repo.FindOneGovernorStatus(ctx, query)
|
||||||
|
|
||||||
res := response.Response[*GovStatus]{Data: govStatus}
|
res := response.Response[*GovStatus]{Data: govStatus}
|
||||||
return &res, err
|
return &res, err
|
||||||
}
|
}
|
||||||
|
@ -182,7 +190,7 @@ func (s *Service) GetEnqueuedVaas(ctx context.Context) ([]*EnqueuedVaaItem, erro
|
||||||
|
|
||||||
// IsVaaEnqueued check vaa is enqueued.
|
// IsVaaEnqueued check vaa is enqueued.
|
||||||
// Guardian api migration.
|
// Guardian api migration.
|
||||||
func (s *Service) IsVaaEnqueued(ctx context.Context, chainID vaa.ChainID, emitter vaa.Address, seq string) (bool, error) {
|
func (s *Service) IsVaaEnqueued(ctx context.Context, chainID vaa.ChainID, emitter *types.Address, seq string) (bool, error) {
|
||||||
isEnqueued, err := s.repo.IsVaaEnqueued(ctx, chainID, emitter, seq)
|
isEnqueued, err := s.repo.IsVaaEnqueued(ctx, chainID, emitter, seq)
|
||||||
return isEnqueued, err
|
return isEnqueued, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
||||||
|
"github.com/wormhole-foundation/wormhole-explorer/api/types"
|
||||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -32,19 +33,55 @@ func (s *Service) FindByChain(ctx context.Context, chain vaa.ChainID, p *paginat
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindByEmitter get all the observations by chainID and emitter address.
|
// FindByEmitter get all the observations by chainID and emitter address.
|
||||||
func (s *Service) FindByEmitter(ctx context.Context, chain vaa.ChainID, emitter *vaa.Address, p *pagination.Pagination) ([]*ObservationDoc, error) {
|
func (s *Service) FindByEmitter(
|
||||||
query := Query().SetChain(chain).SetEmitter(emitter.String()).SetPagination(p)
|
ctx context.Context,
|
||||||
|
chain vaa.ChainID,
|
||||||
|
emitter *types.Address,
|
||||||
|
p *pagination.Pagination,
|
||||||
|
) ([]*ObservationDoc, error) {
|
||||||
|
|
||||||
|
query := Query().
|
||||||
|
SetChain(chain).
|
||||||
|
SetEmitter(emitter.ShortHex()).
|
||||||
|
SetPagination(p)
|
||||||
|
|
||||||
return s.repo.Find(ctx, query)
|
return s.repo.Find(ctx, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindByVAA get all the observations for a VAA (chainID, emitter addrress and sequence number).
|
// FindByVAA get all the observations for a VAA (chainID, emitter addrress and sequence number).
|
||||||
func (s *Service) FindByVAA(ctx context.Context, chain vaa.ChainID, emitter *vaa.Address, seq string, p *pagination.Pagination) ([]*ObservationDoc, error) {
|
func (s *Service) FindByVAA(
|
||||||
query := Query().SetChain(chain).SetEmitter(emitter.String()).SetSequence(seq).SetPagination(p)
|
ctx context.Context,
|
||||||
|
chain vaa.ChainID,
|
||||||
|
emitter *types.Address,
|
||||||
|
seq string,
|
||||||
|
p *pagination.Pagination,
|
||||||
|
) ([]*ObservationDoc, error) {
|
||||||
|
|
||||||
|
query := Query().
|
||||||
|
SetChain(chain).
|
||||||
|
SetEmitter(emitter.ShortHex()).
|
||||||
|
SetSequence(seq).
|
||||||
|
SetPagination(p)
|
||||||
|
|
||||||
return s.repo.Find(ctx, query)
|
return s.repo.Find(ctx, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindOne get a observation by chainID, emitter address, sequence, signer address and hash.
|
// FindOne get a observation by chainID, emitter address, sequence, signer address and hash.
|
||||||
func (s *Service) FindOne(ctx context.Context, chainID vaa.ChainID, emitterAddr *vaa.Address, seq string, signerAddr *vaa.Address, hash []byte) (*ObservationDoc, error) {
|
func (s *Service) FindOne(
|
||||||
query := Query().SetChain(chainID).SetEmitter(emitterAddr.String()).SetSequence(seq).SetGuardianAddr(signerAddr.String()).SetHash(hash)
|
ctx context.Context,
|
||||||
|
chainID vaa.ChainID,
|
||||||
|
emitterAddr *types.Address,
|
||||||
|
seq string,
|
||||||
|
signerAddr *vaa.Address,
|
||||||
|
hash []byte,
|
||||||
|
) (*ObservationDoc, error) {
|
||||||
|
|
||||||
|
query := Query().
|
||||||
|
SetChain(chainID).
|
||||||
|
SetEmitter(emitterAddr.ShortHex()).
|
||||||
|
SetSequence(seq).
|
||||||
|
SetGuardianAddr(signerAddr.String()).
|
||||||
|
SetHash(hash)
|
||||||
|
|
||||||
return s.repo.FindOne(ctx, query)
|
return s.repo.FindOne(ctx, query)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
errs "github.com/wormhole-foundation/wormhole-explorer/api/internal/errors"
|
errs "github.com/wormhole-foundation/wormhole-explorer/api/internal/errors"
|
||||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
||||||
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
||||||
|
"github.com/wormhole-foundation/wormhole-explorer/api/types"
|
||||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -90,13 +91,13 @@ func (s *Service) FindByChain(
|
||||||
func (s *Service) FindByEmitter(
|
func (s *Service) FindByEmitter(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chain vaa.ChainID,
|
chain vaa.ChainID,
|
||||||
emitter vaa.Address,
|
emitter *types.Address,
|
||||||
p *pagination.Pagination,
|
p *pagination.Pagination,
|
||||||
) (*response.Response[[]*VaaDoc], error) {
|
) (*response.Response[[]*VaaDoc], error) {
|
||||||
|
|
||||||
query := Query().
|
query := Query().
|
||||||
SetChain(chain).
|
SetChain(chain).
|
||||||
SetEmitter(emitter.String()).
|
SetEmitter(emitter.ShortHex()).
|
||||||
SetPagination(p)
|
SetPagination(p)
|
||||||
|
|
||||||
vaas, err := s.repo.Find(ctx, query)
|
vaas, err := s.repo.Find(ctx, query)
|
||||||
|
@ -109,7 +110,7 @@ func (s *Service) FindByEmitter(
|
||||||
func (s *Service) FindById(
|
func (s *Service) FindById(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chain vaa.ChainID,
|
chain vaa.ChainID,
|
||||||
emitter vaa.Address,
|
emitter *types.Address,
|
||||||
seq string,
|
seq string,
|
||||||
includeParsedPayload bool,
|
includeParsedPayload bool,
|
||||||
) (*response.Response[*VaaDoc], error) {
|
) (*response.Response[*VaaDoc], error) {
|
||||||
|
@ -141,24 +142,24 @@ func (s *Service) FindById(
|
||||||
func (s *Service) findById(
|
func (s *Service) findById(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chain vaa.ChainID,
|
chain vaa.ChainID,
|
||||||
emitter vaa.Address,
|
emitter *types.Address,
|
||||||
seq string,
|
seq string,
|
||||||
) (*VaaDoc, error) {
|
) (*VaaDoc, error) {
|
||||||
|
|
||||||
query := Query().
|
query := Query().
|
||||||
SetChain(chain).
|
SetChain(chain).
|
||||||
SetEmitter(emitter.String()).
|
SetEmitter(emitter.ShortHex()).
|
||||||
SetSequence(seq)
|
SetSequence(seq)
|
||||||
|
|
||||||
return s.repo.FindOne(ctx, query)
|
return s.repo.FindOne(ctx, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
// findByIdWithPayload get a vaa with payload data by chainID, emitter address and sequence number.
|
// findByIdWithPayload get a vaa with payload data by chainID, emitter address and sequence number.
|
||||||
func (s *Service) findByIdWithPayload(ctx context.Context, chain vaa.ChainID, emitter vaa.Address, seq string) (*VaaDoc, error) {
|
func (s *Service) findByIdWithPayload(ctx context.Context, chain vaa.ChainID, emitter *types.Address, seq string) (*VaaDoc, error) {
|
||||||
|
|
||||||
query := Query().
|
query := Query().
|
||||||
SetChain(chain).
|
SetChain(chain).
|
||||||
SetEmitter(emitter.String()).
|
SetEmitter(emitter.ShortHex()).
|
||||||
SetSequence(seq)
|
SetSequence(seq)
|
||||||
|
|
||||||
vaas, err := s.repo.FindVaasWithPayload(ctx, query)
|
vaas, err := s.repo.FindVaasWithPayload(ctx, query)
|
||||||
|
@ -192,8 +193,8 @@ func (s *Service) GetVaaCount(ctx context.Context, p *pagination.Pagination) (*r
|
||||||
// discardVaaNotIndexed discard a vaa request if the input sequence for a chainID, address is greatter than or equals
|
// discardVaaNotIndexed discard a vaa request if the input sequence for a chainID, address is greatter than or equals
|
||||||
// the cached value of the sequence for this chainID, address.
|
// the cached value of the sequence for this chainID, address.
|
||||||
// If the sequence does not exist we can not discard the request.
|
// If the sequence does not exist we can not discard the request.
|
||||||
func (s *Service) discardVaaNotIndexed(ctx context.Context, chain vaa.ChainID, emitter vaa.Address, seq string) bool {
|
func (s *Service) discardVaaNotIndexed(ctx context.Context, chain vaa.ChainID, emitter *types.Address, seq string) bool {
|
||||||
key := fmt.Sprintf("%s:%d:%s", "wormscan:vaa-max-sequence", chain, emitter.String())
|
key := fmt.Sprintf("%s:%d:%s", "wormscan:vaa-max-sequence", chain, emitter.ShortHex())
|
||||||
sequence, err := s.getCacheFunc(ctx, key)
|
sequence, err := s.getCacheFunc(ctx, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, errs.ErrInternalError) {
|
if errors.Is(err, errs.ErrInternalError) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
||||||
|
"github.com/wormhole-foundation/wormhole-explorer/api/types"
|
||||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -31,11 +32,11 @@ func ExtractChainID(c *fiber.Ctx, l *zap.Logger) (vaa.ChainID, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractEmitterAddr get emitter parameter from route path.
|
// ExtractEmitterAddr get emitter parameter from route path.
|
||||||
func ExtractEmitterAddr(c *fiber.Ctx, l *zap.Logger) (*vaa.Address, error) {
|
func ExtractEmitterAddr(c *fiber.Ctx, l *zap.Logger) (*types.Address, error) {
|
||||||
|
|
||||||
emitterStr := c.Params("emitter")
|
emitterStr := c.Params("emitter")
|
||||||
|
|
||||||
emitter, err := vaa.StringToAddress(emitterStr)
|
emitter, err := types.StringToAddress(emitterStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
requestID := fmt.Sprintf("%v", c.Locals("requestid"))
|
requestID := fmt.Sprintf("%v", c.Locals("requestid"))
|
||||||
l.Error("failed to convert emitter to address",
|
l.Error("failed to convert emitter to address",
|
||||||
|
@ -46,7 +47,7 @@ func ExtractEmitterAddr(c *fiber.Ctx, l *zap.Logger) (*vaa.Address, error) {
|
||||||
return nil, response.NewInvalidParamError(c, "MALFORMED EMITTER_ADDR", errors.WithStack(err))
|
return nil, response.NewInvalidParamError(c, "MALFORMED EMITTER_ADDR", errors.WithStack(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
return &emitter, nil
|
return emitter, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractSequence get sequence parameter from route path.
|
// ExtractSequence get sequence parameter from route path.
|
||||||
|
@ -69,37 +70,30 @@ func ExtractSequence(c *fiber.Ctx, l *zap.Logger) (uint64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractGuardianAddress get guardian address from route path.
|
// ExtractGuardianAddress get guardian address from route path.
|
||||||
func ExtractGuardianAddress(c *fiber.Ctx, l *zap.Logger) (string, error) {
|
func ExtractGuardianAddress(c *fiber.Ctx, l *zap.Logger) (*types.Address, error) {
|
||||||
|
|
||||||
// read the address from query params
|
// read the address from query params
|
||||||
tmp := c.Params("guardian_address")
|
tmp := c.Params("guardian_address")
|
||||||
if tmp == "" {
|
if tmp == "" {
|
||||||
return "", response.NewInvalidParamError(c, "MALFORMED GUARDIAN ADDR", nil)
|
return nil, response.NewInvalidParamError(c, "MALFORMED GUARDIAN ADDR", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate the address using the SDK
|
// validate the address
|
||||||
guardianAddress, err := vaa.StringToAddress(tmp)
|
guardianAddress, err := types.StringToAddress(tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
requestID := fmt.Sprintf("%v", c.Locals("requestid"))
|
requestID := fmt.Sprintf("%v", c.Locals("requestid"))
|
||||||
l.Error("failed to decode guardian address",
|
l.Error("failed to decode guardian address",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.String("requestID", requestID),
|
zap.String("requestID", requestID),
|
||||||
)
|
)
|
||||||
return "", response.NewInvalidParamError(c, "MALFORMED GUARDIAN ADDR", errors.WithStack(err))
|
return nil, response.NewInvalidParamError(c, "MALFORMED GUARDIAN ADDR", errors.WithStack(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the address length is the expected
|
return guardianAddress, nil
|
||||||
addr := guardianAddress.String()
|
|
||||||
if len(addr) != 64 {
|
|
||||||
return "", response.NewInvalidParamError(c, "MALFORMED GUARDIAN ADDR", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// the address returned by the SDK has 24 leading zeroes
|
|
||||||
return addr[24:], nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractVAAParams get VAA chain, address from route path.
|
// ExtractVAAParams get VAA chain, address from route path.
|
||||||
func ExtractVAAChainIDEmitter(c *fiber.Ctx, l *zap.Logger) (vaa.ChainID, *vaa.Address, error) {
|
func ExtractVAAChainIDEmitter(c *fiber.Ctx, l *zap.Logger) (vaa.ChainID, *types.Address, error) {
|
||||||
|
|
||||||
chainID, err := ExtractChainID(c, l)
|
chainID, err := ExtractChainID(c, l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -115,7 +109,7 @@ func ExtractVAAChainIDEmitter(c *fiber.Ctx, l *zap.Logger) (vaa.ChainID, *vaa.Ad
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractVAAParams get VAAA chain, address and sequence from route path.
|
// ExtractVAAParams get VAAA chain, address and sequence from route path.
|
||||||
func ExtractVAAParams(c *fiber.Ctx, l *zap.Logger) (vaa.ChainID, *vaa.Address, uint64, error) {
|
func ExtractVAAParams(c *fiber.Ctx, l *zap.Logger) (vaa.ChainID, *types.Address, uint64, error) {
|
||||||
|
|
||||||
chainID, err := ExtractChainID(c, l)
|
chainID, err := ExtractChainID(c, l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -139,7 +139,7 @@ func (c *Controller) IsVaaEnqueued(ctx *fiber.Ctx) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
isEnqueued, err := c.srv.IsVaaEnqueued(ctx.Context(), chainID, *emitter, strconv.FormatUint(seq, 10))
|
isEnqueued, err := c.srv.IsVaaEnqueued(ctx.Context(), chainID, emitter, strconv.FormatUint(seq, 10))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ func (c *Controller) FindSignedVAAByID(ctx *fiber.Ctx) error {
|
||||||
vaa, err := c.srv.FindById(
|
vaa, err := c.srv.FindById(
|
||||||
ctx.Context(),
|
ctx.Context(),
|
||||||
chainID,
|
chainID,
|
||||||
*emitter,
|
emitter,
|
||||||
strconv.FormatUint(seq, 10),
|
strconv.FormatUint(seq, 10),
|
||||||
false, /*includeParsedPayload*/
|
false, /*includeParsedPayload*/
|
||||||
)
|
)
|
||||||
|
|
|
@ -65,7 +65,7 @@ func (c *Controller) FindGovernorConfigurationByGuardianAddress(ctx *fiber.Ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// query the database
|
// query the database
|
||||||
govConfigs, err := c.srv.FindGovernorConfigByGuardianAddress(ctx.Context(), guardianAddress)
|
govConfigs, err := c.srv.FindGovernorConfigByGuardianAddress(ctx.Context(), guardianAddress.ShortHex())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if len(govConfigs) == 0 {
|
} else if len(govConfigs) == 0 {
|
||||||
|
@ -127,7 +127,7 @@ func (c *Controller) FindGovernorStatusByGuardianAddress(ctx *fiber.Ctx) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
govStatus, err := c.srv.FindGovernorStatusByGuardianAddress(ctx.Context(), guardianAddress, p)
|
govStatus, err := c.srv.FindGovernorStatusByGuardianAddress(ctx.Context(), guardianAddress.ShortHex(), p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ func (c *Controller) FindByEmitter(ctx *fiber.Ctx) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vaas, err := c.srv.FindByEmitter(ctx.Context(), chainID, *emitter, p)
|
vaas, err := c.srv.FindByEmitter(ctx.Context(), chainID, emitter, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ func (c *Controller) FindById(ctx *fiber.Ctx) error {
|
||||||
vaa, err := c.srv.FindById(
|
vaa, err := c.srv.FindById(
|
||||||
ctx.Context(),
|
ctx.Context(),
|
||||||
chainID,
|
chainID,
|
||||||
*emitter,
|
emitter,
|
||||||
strconv.FormatUint(seq, 10),
|
strconv.FormatUint(seq, 10),
|
||||||
includeParsedPayload,
|
includeParsedPayload,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/heartbeats"
|
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/heartbeats"
|
||||||
vaaservice "github.com/wormhole-foundation/wormhole-explorer/api/handlers/vaa"
|
vaaservice "github.com/wormhole-foundation/wormhole-explorer/api/handlers/vaa"
|
||||||
errs "github.com/wormhole-foundation/wormhole-explorer/api/internal/errors"
|
errs "github.com/wormhole-foundation/wormhole-explorer/api/internal/errors"
|
||||||
|
"github.com/wormhole-foundation/wormhole-explorer/api/types"
|
||||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
|
@ -51,14 +52,16 @@ func (h *Handler) GetSignedVAA(ctx context.Context, request *publicrpcv1.GetSign
|
||||||
|
|
||||||
address, err := hex.DecodeString(request.MessageId.EmitterAddress)
|
address, err := hex.DecodeString(request.MessageId.EmitterAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to decode address: %v", err))
|
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to decode address from hex: %v", err))
|
||||||
}
|
}
|
||||||
if len(address) != 32 {
|
if len(address) != 32 {
|
||||||
return nil, status.Error(codes.InvalidArgument, "address must be 32 bytes")
|
return nil, status.Error(codes.InvalidArgument, "address must be 32 bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := vaa.Address{}
|
addr, err := types.BytesToAddress(address)
|
||||||
copy(addr[:], address)
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to decode address from bytes: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
sequence := strconv.FormatUint(request.MessageId.Sequence, 10)
|
sequence := strconv.FormatUint(request.MessageId.Sequence, 10)
|
||||||
|
|
||||||
|
@ -222,7 +225,7 @@ func (h *Handler) GovernorIsVAAEnqueued(ctx context.Context, request *publicrpcv
|
||||||
return nil, status.Error(codes.InvalidArgument, "Parameters are required")
|
return nil, status.Error(codes.InvalidArgument, "Parameters are required")
|
||||||
}
|
}
|
||||||
chainID := vaa.ChainID(request.MessageId.EmitterChain)
|
chainID := vaa.ChainID(request.MessageId.EmitterChain)
|
||||||
emitterAddress, err := vaa.StringToAddress(request.MessageId.EmitterAddress)
|
emitterAddress, err := types.StringToAddress(request.MessageId.EmitterAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Error(codes.InvalidArgument, "Invalid emitter address")
|
return nil, status.Error(codes.InvalidArgument, "Invalid emitter address")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Address struct {
|
||||||
|
address vaa.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
func BytesToAddress(b []byte) (*Address, error) {
|
||||||
|
|
||||||
|
var a Address
|
||||||
|
|
||||||
|
if len(b) != len(a.address) {
|
||||||
|
return nil, fmt.Errorf("expected byte slice to have len=%d, but got %d instead", len(a.address), len(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(a.address[:], b)
|
||||||
|
|
||||||
|
return &a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToAddress converts a hex-encoded address string into an *Address.
|
||||||
|
func StringToAddress(s string) (*Address, error) {
|
||||||
|
|
||||||
|
a, err := vaa.StringToAddress(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Address{address: a}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hex returns the full 32-byte address, encoded as hex.
|
||||||
|
func (addr *Address) Hex() string {
|
||||||
|
return addr.address.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShortHex returns a hex-encoded address that is usually shorted than Hex().
|
||||||
|
//
|
||||||
|
// If the full address returned by Hex() is prefixed 12 bytes set to zero,
|
||||||
|
// this function will trim those bytes.
|
||||||
|
func (addr *Address) ShortHex() string {
|
||||||
|
|
||||||
|
full := addr.Hex()
|
||||||
|
|
||||||
|
if len(full) == 64 && strings.HasPrefix(full, "000000000000000000000000") {
|
||||||
|
return full[24:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return full
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
// Test_Address_ShortString runs several test cases on the method `Address.ShortString()`.
|
||||||
|
func Test_Address_ShortString(t *testing.T) {
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Input string
|
||||||
|
Hex string
|
||||||
|
ShortHex string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "0x000000000000000000000000f890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
Hex: "000000000000000000000000f890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
ShortHex: "f890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "000000000000000000000000f890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
Hex: "000000000000000000000000f890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
ShortHex: "f890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "0xf890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
Hex: "000000000000000000000000f890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
ShortHex: "f890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "f890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
Hex: "000000000000000000000000f890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
ShortHex: "f890982f9310df57d00f659cf4fd87e65aded8d7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "ec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5",
|
||||||
|
Hex: "ec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5",
|
||||||
|
ShortHex: "ec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "0xec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5",
|
||||||
|
Hex: "ec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5",
|
||||||
|
ShortHex: "ec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range testCases {
|
||||||
|
tc := &testCases[i]
|
||||||
|
|
||||||
|
addr, err := StringToAddress(tc.Input)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to parse address %s: %v", tc.Input, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if addr.Hex() != tc.Hex {
|
||||||
|
t.Fatalf("expected Address.Hex()=%s, but got %s", tc.Hex, addr.Hex())
|
||||||
|
}
|
||||||
|
|
||||||
|
if addr.ShortHex() != tc.ShortHex {
|
||||||
|
t.Fatalf("expected Address.ShortHex()=%s, but got %s", tc.ShortHex, addr.ShortHex())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue