Skip to content

Commit

Permalink
Feature: add supply and sort to assets list (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
aopoltorzhicky authored Dec 10, 2024
1 parent c60cc8b commit 5cf8990
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 30 deletions.
28 changes: 28 additions & 0 deletions cmd/api/docs/docs.go

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

28 changes: 28 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.

21 changes: 21 additions & 0 deletions cmd/api/docs/swagger.yaml

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

17 changes: 12 additions & 5 deletions cmd/api/handler/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,19 @@ func NewAssetHandler(
}

type assetListRequest struct {
Limit uint64 `query:"limit" validate:"omitempty,min=1,max=100"`
Offset uint64 `query:"offset" validate:"omitempty,min=0"`
Limit uint64 `query:"limit" validate:"omitempty,min=1,max=100"`
Offset uint64 `query:"offset" validate:"omitempty,min=0"`
Sort string `query:"sort" validate:"omitempty,oneof=asc desc"`
SortField string `query:"sort_by" validate:"omitempty,oneof=fee fee_count transferred transfer_count supply"`
}

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

// List godoc
Expand All @@ -43,8 +48,10 @@ func (p *assetListRequest) SetDefault() {
// @Description Get assets info
// @Tags assets
// @ID get-asset
// @Param limit query integer false "Count of requested entities" mininum(1) maximum(100)
// @Param offset query integer false "Offset" mininum(1)
// @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" Enums(asc, desc)
// @Param sort_by query string false "Field using for sorting. Default: fee" Enums(fee, fee_count, transferred, transfer_count, supply)
// @Produce json
// @Success 200 {object} responses.Asset
// @Success 204
Expand All @@ -58,7 +65,7 @@ func (handler *AssetHandler) List(c echo.Context) error {
}
req.SetDefault()

assets, err := handler.asset.List(c.Request().Context(), int(req.Limit), int(req.Offset))
assets, err := handler.asset.List(c.Request().Context(), int(req.Limit), int(req.Offset), req.SortField, pgSort(req.Sort))
if err != nil {
return handleError(c, err, handler.blocks)
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/api/handler/asset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/celenium-io/astria-indexer/cmd/api/handler/responses"
"github.com/celenium-io/astria-indexer/internal/storage"
"github.com/celenium-io/astria-indexer/internal/storage/mock"
sdk "github.com/dipdup-net/indexer-sdk/pkg/storage"
"github.com/labstack/echo/v4"
"github.com/shopspring/decimal"
"github.com/stretchr/testify/suite"
Expand Down Expand Up @@ -56,7 +57,7 @@ func (s *AssetTestSuite) TestList() {
c.SetPath("/asset")

s.asset.EXPECT().
List(gomock.Any(), 10, 0).
List(gomock.Any(), 10, 0, "", sdk.SortOrderDesc).
Return([]storage.Asset{
{
Asset: "asset",
Expand Down
2 changes: 2 additions & 0 deletions cmd/api/handler/responses/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Asset struct {
Transferred string `example:"1000" format:"string" json:"transferred" swaggertype:"string"`
TransferCount int `example:"100" format:"number" json:"transfer_count" swaggertype:"integer"`
Asset string `example:"nria" format:"string" json:"asset" swaggertype:"string"`
Supply string `example:"1000" format:"string" json:"supply" swaggertype:"string"`
}

func NewAsset(asset storage.Asset) Asset {
Expand All @@ -20,5 +21,6 @@ func NewAsset(asset storage.Asset) Asset {
FeeCount: asset.FeeCount,
Transferred: asset.Transferred.String(),
TransferCount: asset.TransferCount,
Supply: asset.Supply.String(),
}
}
4 changes: 3 additions & 1 deletion internal/storage/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ package storage
import (
"context"

sdk "github.com/dipdup-net/indexer-sdk/pkg/storage"
"github.com/shopspring/decimal"
"github.com/uptrace/bun"
)

type IAsset interface {
List(ctx context.Context, limit int, offset int) ([]Asset, error)
List(ctx context.Context, limit int, offset int, sortBy string, order sdk.SortOrder) ([]Asset, error)
}

//go:generate mockgen -source=$GOFILE -destination=mock/$GOFILE -package=mock -typed
Expand All @@ -23,4 +24,5 @@ type Asset struct {
FeeCount int `bun:"fee_count"`
Transferred decimal.Decimal `bun:"transferred"`
TransferCount int `bun:"transfer_count"`
Supply decimal.Decimal `bun:"supply"`
}
13 changes: 7 additions & 6 deletions internal/storage/mock/asset.go

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

4 changes: 2 additions & 2 deletions internal/storage/postgres/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (s *StorageTestSuite) TestAddressListWithBalancesWithAsset() {
addresses, err := s.storage.Address.ListWithBalance(ctx, storage.AddressListFilter{
Sort: sdk.SortOrderAsc,
Limit: 1,
Asset: "test",
Asset: "asset-1",
})
s.Require().NoError(err)
s.Require().Len(addresses, 1)
Expand All @@ -73,7 +73,7 @@ func (s *StorageTestSuite) TestAddressListWithBalancesWithAsset() {

balance := address.Balance[0]
s.Require().EqualValues("10", balance.Total.String())
s.Require().EqualValues("test", balance.Currency)
s.Require().EqualValues("asset-1", balance.Currency)

s.Require().EqualValues("astria1lm45urgugesyhaymn68xww0m6g49zreqa32w7p", address.Hash)
}
34 changes: 29 additions & 5 deletions internal/storage/postgres/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/celenium-io/astria-indexer/internal/storage"
"github.com/dipdup-net/go-lib/database"
sdk "github.com/dipdup-net/indexer-sdk/pkg/storage"
)

type Asset struct {
Expand All @@ -21,7 +22,15 @@ func NewAsset(db *database.Bun) *Asset {
}
}

func (a *Asset) List(ctx context.Context, limit int, offset int) (assets []storage.Asset, err error) {
var validSortFieldsForAssetList = map[string]struct{}{
"fee": {},
"transferred": {},
"transfer_count": {},
"fee_count": {},
"supply": {},
}

func (a *Asset) List(ctx context.Context, limit int, offset int, sortBy string, order sdk.SortOrder) (assets []storage.Asset, err error) {
transferredQuery := a.db.DB().NewSelect().
Model((*storage.Transfer)(nil)).
ColumnExpr("asset, count(*) as c, sum(amount) as amount").
Expand All @@ -32,19 +41,34 @@ func (a *Asset) List(ctx context.Context, limit int, offset int) (assets []stora
ColumnExpr("asset, count(*) as c, sum(amount) as amount").
Group("asset")

supplyQuery := a.db.DB().NewSelect().
Model((*storage.Balance)(nil)).
ColumnExpr("currency, sum(total) as amount").
Group("currency")

query := a.db.DB().NewSelect().
With("fees", feesQuery).
With("transferred", transferredQuery).
Table("fees").
ColumnExpr("(case when fees.asset is NULL then transferred.asset else fees.asset end) as asset").
With("supply", supplyQuery).
Table("supply").
ColumnExpr("(case when fees.asset is not NULL then fees.asset when supply.currency is not NULL then supply.currency else transferred.asset end) as asset").
ColumnExpr("(case when fees.amount is NULL then 0 else fees.amount end) as fee").
ColumnExpr("(case when transferred.amount is NULL then 0 else transferred.amount end) as transferred").
ColumnExpr("fees.c as fee_count, transferred.c as transfer_count").
Join("full outer join transferred on transferred.asset = fees.asset")
ColumnExpr("(case when supply.amount is NULL then 0 else supply.amount end) as supply").
ColumnExpr("(case when fees.c is NULL then 0 else fees.c end) as fee_count").
ColumnExpr("(case when transferred.c is NULL then 0 else transferred.c end) as transfer_count").
Join("left join transferred on supply.currency = transferred.asset").
Join("left join fees on supply.currency = fees.asset")

query = limitScope(query, limit)
query = offsetScope(query, offset)

if _, ok := validSortFieldsForAssetList[sortBy]; ok {
query = sortScope(query, sortBy, order)
} else {
query = sortScope(query, "supply", order)
}

err = query.Scan(ctx, &assets)
return
}
Loading

0 comments on commit 5cf8990

Please sign in to comment.