Skip to content

Commit

Permalink
api: new endpoint /chain/blocks
Browse files Browse the repository at this point in the history
accepts QueryParams:
     * GET /chain/blocks
       * page
       * limit
       * chainId
       * hash
       * proposerAddress

* api: add structs BlockList, BlockParams
* api: add consts ParamChainId, ParamHash, ParamProposerAddress
* indexer: add indexertypes.Block
  • Loading branch information
altergui committed Aug 23, 2024
1 parent 6f4642c commit 5bde6d9
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 0 deletions.
3 changes: 3 additions & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ const (
ParamWithResults = "withResults"
ParamFinalResults = "finalResults"
ParamManuallyEnded = "manuallyEnded"
ParamChainId = "chainId"
ParamHash = "hash"
ParamProposerAddress = "proposerAddress"
ParamHeight = "height"
ParamReference = "reference"
ParamType = "type"
Expand Down
14 changes: 14 additions & 0 deletions api/api_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ type TransactionParams struct {
Type string `json:"type,omitempty"`
}

// BlockParams allows the client to filter blocks
type BlockParams struct {
PaginationParams
ChainID string `json:"chainId,omitempty"`
Hash string `json:"hash,omitempty"`
ProposerAddress string `json:"proposerAddress,omitempty"`
}

// FeesParams allows the client to filter fees
type FeesParams struct {
PaginationParams
Expand Down Expand Up @@ -439,3 +447,9 @@ type Block struct {
comettypes.Block `json:",inline"`
Hash types.HexBytes `json:"hash" `
}

// BlockList is used to return a paginated list to the client
type BlockList struct {
Blocks []*indexertypes.Block `json:"blocks"`
Pagination *Pagination `json:"pagination"`
}
80 changes: 80 additions & 0 deletions api/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,14 @@ func (a *API) enableChainHandlers() error {
); err != nil {
return err
}
if err := a.Endpoint.RegisterMethod(
"/chain/blocks",
"GET",
apirest.MethodAccessTypePublic,
a.chainBlockListHandler,
); err != nil {
return err
}
if err := a.Endpoint.RegisterMethod(
"/chain/organizations/filter/page/{page}",
"POST",
Expand Down Expand Up @@ -972,6 +980,63 @@ func (a *API) chainBlockByHashHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCo
return ctx.Send(convertKeysToCamel(data), apirest.HTTPstatusOK)
}

// chainBlockListHandler
//
// @Summary List all blocks
// @Description Returns the list of blocks, ordered by descending height.
// @Tags Chain
// @Accept json
// @Produce json
// @Param page query number false "Page"
// @Param limit query number false "Items per page"
// @Param chainId query string false "Filter by exact chainId"
// @Param hash query string false "Filter by partial hash"
// @Param proposerAddress query string false "Filter by exact proposerAddress"
// @Success 200 {object} BlockList
// @Router /chain/blocks [get]
func (a *API) chainBlockListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
params, err := parseBlockParams(
ctx.QueryParam(ParamPage),
ctx.QueryParam(ParamLimit),
ctx.QueryParam(ParamChainId),
ctx.QueryParam(ParamHash),
ctx.QueryParam(ParamProposerAddress),
)
if err != nil {
return err
}

return a.sendBlockList(ctx, params)
}

// sendBlockList produces a filtered, paginated BlockList,
// and sends it marshalled over ctx.Send
//
// Errors returned are always of type APIerror.
func (a *API) sendBlockList(ctx *httprouter.HTTPContext, params *BlockParams) error {
blocks, total, err := a.indexer.BlockList(
params.Limit,
params.Page*params.Limit,
params.ChainID,
params.Hash,
params.ProposerAddress,
)
if err != nil {
return ErrIndexerQueryFailed.WithErr(err)
}

pagination, err := calculatePagination(params.Page, params.Limit, total)
if err != nil {
return err
}

list := &BlockList{
Blocks: blocks,
Pagination: pagination,
}
return marshalAndSend(ctx, list)
}

// chainTransactionCountHandler
//
// @Summary Transactions count
Expand Down Expand Up @@ -1320,3 +1385,18 @@ func parseTransactionParams(paramPage, paramLimit, paramHeight, paramType string
Type: paramType,
}, nil
}

// parseBlockParams returns an BlockParams filled with the passed params
func parseBlockParams(paramPage, paramLimit, paramChainId, paramHash, paramProposerAddress string) (*BlockParams, error) {
pagination, err := parsePaginationParams(paramPage, paramLimit)
if err != nil {
return nil, err
}

return &BlockParams{
PaginationParams: pagination,
ChainID: paramChainId,
Hash: util.TrimHex(paramHash),
ProposerAddress: util.TrimHex(paramProposerAddress),
}, nil
}
20 changes: 20 additions & 0 deletions vochain/indexer/indexertypes/block.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package indexertypes

import (
"time"

"go.vocdoni.io/dvote/types"
)

// Block represents a block handled by the Vochain.
// The indexer Block data type is different from the vochain state data type
// since it is optimized for querying purposes and not for keeping a shared consensus state.
type Block struct {
ChainID string `json:"chainId"`
Height int64 `json:"height"`
Time time.Time `json:"time"`
Hash types.HexBytes `json:"hash"`
ProposerAddress types.HexBytes `json:"proposer"`
LastBlockHash types.HexBytes `json:"lastBlockHash"`
TxCount int64 `json:"txCount"`
}

0 comments on commit 5bde6d9

Please sign in to comment.