Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: filter rollup by category #286

Merged
merged 1 commit into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ linters:
- prealloc
- protogetter
- makezero
linters-settings:
gosec:
excludes:
- G115
18 changes: 18 additions & 0 deletions cmd/api/docs/swagger.json

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

1 change: 1 addition & 0 deletions cmd/api/handler/constant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,5 @@ func (s *ConstantTestSuite) TestEnums() {
s.Require().Len(enums.EventType, 59)
s.Require().Len(enums.MessageType, 74)
s.Require().Len(enums.Status, 2)
s.Require().Len(enums.Categories, 3)
}
38 changes: 0 additions & 38 deletions cmd/api/handler/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,44 +139,6 @@ func (p *namespaceList) SetDefault() {
}
}

type rollupList struct {
Limit int `query:"limit" validate:"omitempty,min=1,max=100"`
Offset int `query:"offset" validate:"omitempty,min=0"`
Sort string `query:"sort" validate:"omitempty,oneof=asc desc"`
SortBy string `query:"sort_by" validate:"omitempty,oneof=time blobs_count size fee"`
}

func (p *rollupList) SetDefault() {
if p.Limit == 0 {
p.Limit = 10
}
if p.Sort == "" {
p.Sort = desc
}
if p.SortBy == "" {
p.SortBy = "size"
}
}

type rollupDayList struct {
Limit int `query:"limit" validate:"omitempty,min=1,max=100"`
Offset int `query:"offset" validate:"omitempty,min=0"`
Sort string `query:"sort" validate:"omitempty,oneof=asc desc"`
SortBy string `query:"sort_by" validate:"omitempty,oneof=avg_size blobs_count total_size total_fee throughput namespace_count pfb_count mb_price"`
}

func (p *rollupDayList) SetDefault() {
if p.Limit == 0 {
p.Limit = 10
}
if p.Sort == "" {
p.Sort = desc
}
if p.SortBy == "" {
p.SortBy = "throughput"
}
}

type getById struct {
Id uint64 `param:"id" validate:"required,min=1"`
}
2 changes: 2 additions & 0 deletions cmd/api/handler/responses/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,14 @@ type Enums struct {
Status []string `json:"status"`
MessageType []string `json:"message_type"`
EventType []string `json:"event_type"`
Categories []string `json:"categories"`
}

func NewEnums() Enums {
return Enums{
Status: types.StatusNames(),
MessageType: types.MsgTypeNames(),
EventType: types.EventTypeNames(),
Categories: types.RollupCategoryNames(),
}
}
95 changes: 80 additions & 15 deletions cmd/api/handler/rollup.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/celenium-io/celestia-indexer/cmd/api/handler/responses"
"github.com/celenium-io/celestia-indexer/internal/storage"
"github.com/celenium-io/celestia-indexer/internal/storage/types"
testsuite "github.com/celenium-io/celestia-indexer/internal/test_suite"
"github.com/labstack/echo/v4"
)
Expand All @@ -31,29 +32,61 @@ func NewRollupHandler(
}
}

type rollupList struct {
Limit int `query:"limit" validate:"omitempty,min=1,max=100"`
Offset int `query:"offset" validate:"omitempty,min=0"`
Sort string `query:"sort" validate:"omitempty,oneof=asc desc"`
SortBy string `query:"sort_by" validate:"omitempty,oneof=time blobs_count size fee"`
Category StringArray `query:"category" validate:"omitempty,dive,category"`
}

func (p *rollupList) SetDefault() {
if p.Limit == 0 {
p.Limit = 10
}
if p.Sort == "" {
p.Sort = desc
}
if p.SortBy == "" {
p.SortBy = "size"
}
}

// Leaderboard godoc
//
// @Summary List rollups info
// @Description List rollups info
// @Tags rollup
// @ID list-rollup
// @Param limit query integer false "Count of requested entities" mininum(1) maximum(100)
// @Param offset query integer false "Offset" mininum(1)
// @Param sort query string false "Sort order. Default: desc" Enums(asc, desc)
// @Param sort_by query string false "Sort field. Default: size" Enums(time, blobs_count, size, fee)
// @Produce json
// @Success 200 {array} responses.RollupWithStats
// @Failure 400 {object} Error
// @Failure 500 {object} Error
// @Router /rollup [get]
// @Summary List rollups info
// @Description List rollups info
// @Tags rollup
// @ID list-rollup
// @Param limit query integer false "Count of requested entities" mininum(1) maximum(100)
// @Param offset query integer false "Offset" mininum(1)
// @Param sort query string false "Sort order. Default: desc" Enums(asc, desc)
// @Param sort_by query string false "Sort field. Default: size" Enums(time, blobs_count, size, fee)
// @Param category query string false "Comma-separated rollup category list"
// @Produce json
// @Success 200 {array} responses.RollupWithStats
// @Failure 400 {object} Error
// @Failure 500 {object} Error
// @Router /rollup [get]
func (handler RollupHandler) Leaderboard(c echo.Context) error {
req, err := bindAndValidate[rollupList](c)
if err != nil {
return badRequestError(c, err)
}
req.SetDefault()

rollups, err := handler.rollups.Leaderboard(c.Request().Context(), req.SortBy, pgSort(req.Sort), req.Limit, req.Offset)
categories := make([]types.RollupCategory, len(req.Category))
for i := range categories {
categories[i] = types.RollupCategory(req.Category[i])
}

rollups, err := handler.rollups.Leaderboard(c.Request().Context(), storage.LeaderboardFilters{
SortField: req.SortBy,
Sort: pgSort(req.Sort),
Limit: req.Limit,
Offset: req.Offset,
Category: categories,
})
if err != nil {
return handleError(c, err, handler.rollups)
}
Expand All @@ -64,6 +97,26 @@ func (handler RollupHandler) Leaderboard(c echo.Context) error {
return returnArray(c, response)
}

type rollupDayList struct {
Limit int `query:"limit" validate:"omitempty,min=1,max=100"`
Offset int `query:"offset" validate:"omitempty,min=0"`
Sort string `query:"sort" validate:"omitempty,oneof=asc desc"`
SortBy string `query:"sort_by" validate:"omitempty,oneof=avg_size blobs_count total_size total_fee throughput namespace_count pfb_count mb_price"`
Category StringArray `query:"category" validate:"omitempty,dive,category"`
}

func (p *rollupDayList) SetDefault() {
if p.Limit == 0 {
p.Limit = 10
}
if p.Sort == "" {
p.Sort = desc
}
if p.SortBy == "" {
p.SortBy = "throughput"
}
}

// LeaderboardDay godoc
//
// @Summary List rollups info with stats by previous 24 hours
Expand All @@ -74,6 +127,7 @@ func (handler RollupHandler) Leaderboard(c echo.Context) error {
// @Param offset query integer false "Offset" mininum(1)
// @Param sort query string false "Sort order. Default: desc" Enums(asc, desc)
// @Param sort_by query string false "Sort field. Default: mb_price" Enums(avg_size, blobs_count, total_size, total_fee, throughput, namespace_count, pfb_count, mb_price)
// @Param category query string false "Comma-separated rollup category list"
// @Produce json
// @Success 200 {array} responses.RollupWithDayStats
// @Failure 400 {object} Error
Expand All @@ -86,7 +140,18 @@ func (handler RollupHandler) LeaderboardDay(c echo.Context) error {
}
req.SetDefault()

rollups, err := handler.rollups.LeaderboardDay(c.Request().Context(), req.SortBy, pgSort(req.Sort), req.Limit, req.Offset)
categories := make([]types.RollupCategory, len(req.Category))
for i := range categories {
categories[i] = types.RollupCategory(req.Category[i])
}

rollups, err := handler.rollups.LeaderboardDay(c.Request().Context(), storage.LeaderboardFilters{
SortField: req.SortBy,
Sort: pgSort(req.Sort),
Limit: req.Limit,
Offset: req.Offset,
Category: categories,
})
if err != nil {
return handleError(c, err, handler.rollups)
}
Expand Down
26 changes: 24 additions & 2 deletions cmd/api/handler/rollup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/celenium-io/celestia-indexer/cmd/api/handler/responses"
"github.com/celenium-io/celestia-indexer/internal/storage"
"github.com/celenium-io/celestia-indexer/internal/storage/mock"
"github.com/celenium-io/celestia-indexer/internal/storage/types"
sdk "github.com/dipdup-net/indexer-sdk/pkg/storage"
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/suite"
Expand All @@ -31,6 +32,7 @@ var (
Twitter: "https://x.com",
Logo: "image.png",
Slug: "test-rollup",
Category: types.RollupCategoryNft,
}
testRollupWithStats = storage.RollupWithStats{
Rollup: testRollup,
Expand Down Expand Up @@ -87,14 +89,24 @@ func (s *RollupTestSuite) TestLeaderboard() {
} {
q := make(url.Values)
q.Add("sort_by", sort)
q.Add("category", "nft,gaming")

req := httptest.NewRequest(http.MethodGet, "/?"+q.Encode(), nil)
rec := httptest.NewRecorder()
c := s.echo.NewContext(req, rec)
c.SetPath("/rollup")

s.rollups.EXPECT().
Leaderboard(gomock.Any(), sort, sdk.SortOrderDesc, 10, 0).
Leaderboard(gomock.Any(), storage.LeaderboardFilters{
SortField: sort,
Sort: sdk.SortOrderDesc,
Limit: 10,
Offset: 0,
Category: []types.RollupCategory{
types.RollupCategoryNft,
types.RollupCategoryGaming,
},
}).
Return([]storage.RollupWithStats{testRollupWithStats}, nil).
Times(1)

Expand Down Expand Up @@ -127,14 +139,24 @@ func (s *RollupTestSuite) TestLeaderboardDay() {
} {
q := make(url.Values)
q.Add("sort_by", sort)
q.Add("category", "nft,gaming")

req := httptest.NewRequest(http.MethodGet, "/?"+q.Encode(), nil)
rec := httptest.NewRecorder()
c := s.echo.NewContext(req, rec)
c.SetPath("/rollup/day")

s.rollups.EXPECT().
LeaderboardDay(gomock.Any(), sort, sdk.SortOrderDesc, 10, 0).
LeaderboardDay(gomock.Any(), storage.LeaderboardFilters{
SortField: sort,
Sort: sdk.SortOrderDesc,
Limit: 10,
Offset: 0,
Category: []types.RollupCategory{
types.RollupCategoryNft,
types.RollupCategoryGaming,
},
}).
Return([]storage.RollupWithDayStats{
{
Rollup: testRollup,
Expand Down
10 changes: 10 additions & 0 deletions cmd/api/handler/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ func NewCelestiaApiValidator() *CelestiaApiValidator {
if err := v.RegisterValidation("namespace", namespaceValidator()); err != nil {
panic(err)
}
if err := v.RegisterValidation("category", categoryValidator()); err != nil {
panic(err)
}
return &CelestiaApiValidator{validator: v}
}

Expand Down Expand Up @@ -99,3 +102,10 @@ func namespaceValidator() validator.Func {
return isNamespace(fl.Field().String())
}
}

func categoryValidator() validator.Func {
return func(fl validator.FieldLevel) bool {
_, err := types.ParseRollupCategory(fl.Field().String())
return err == nil
}
}
6 changes: 3 additions & 3 deletions cmd/api/handler/ws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ func TestWebsocket(t *testing.T) {
dispatcher.Start(ctx)
observer := dispatcher.Observe(storage.ChannelHead, storage.ChannelBlock)

for i := 0; i < 10; i++ {
for i := uint64(0); i < 10; i++ {
hash := make([]byte, 32)
_, err := rand.Read(hash)
require.NoError(t, err)

blockMock.EXPECT().ByIdWithRelations(ctx, uint64(i)).Return(storage.Block{
Id: uint64(i),
blockMock.EXPECT().ByIdWithRelations(ctx, i).Return(storage.Block{
Id: i,
Height: types.Level(i),
Time: time.Now(),
Hash: hash,
Expand Down
Loading
Loading