Skip to content

Commit

Permalink
api: /chain/transactions endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
altergui committed Jul 24, 2024
1 parent 8684a11 commit a46a92c
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 141 deletions.
8 changes: 1 addition & 7 deletions api/api_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type AccountParams struct {
type TransactionParams struct {
PaginationParams
Height uint64 `json:"height,omitempty"`
Type string `json:"type,omitempty"`
}

// FeesParams allows the client to filter fees
Expand Down Expand Up @@ -269,13 +270,6 @@ type FeesList struct {
Pagination *Pagination `json:"pagination"`
}

// TODO: this struct should be deprecated, why blockNumber instead of blockHeight??
type BlockTransactionsInfo struct {
BlockNumber uint64 `json:"blockNumber"`
TransactionsCount uint32 `json:"transactionCount"`
Transactions []TransactionMetadata `json:"transactions"`
}

type GenericTransactionWithInfo struct {
TxContent json.RawMessage `json:"tx"`
TxInfo indexertypes.Transaction `json:"txInfo"`
Expand Down
100 changes: 46 additions & 54 deletions api/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import (
"go.vocdoni.io/dvote/vochain"
"go.vocdoni.io/dvote/vochain/genesis"
"go.vocdoni.io/dvote/vochain/indexer"
"go.vocdoni.io/proto/build/go/models"
"google.golang.org/protobuf/proto"
)

const (
Expand Down Expand Up @@ -139,6 +137,14 @@ func (a *API) enableChainHandlers() error {
); err != nil {
return err
}
if err := a.Endpoint.RegisterMethod(
"/chain/transactions",
"GET",
apirest.MethodAccessTypePublic,
a.chainTxListHandler,
); err != nil {
return err
}
if err := a.Endpoint.RegisterMethod(
"/chain/transactions/page/{page}",
"GET",
Expand Down Expand Up @@ -696,6 +702,32 @@ func (a *API) chainTxRefByIndexHandler(_ *apirest.APIdata, ctx *httprouter.HTTPC
return ctx.Send(data, apirest.HTTPstatusOK)
}

// chainTxListHandler
//
// @Summary List transactions
// @Description To get full transaction information use [/chain/transaction/{blockHeight}/{txIndex}](transaction-by-block-index).\nWhere transactionIndex is the index of the transaction on the containing block.
// @Tags Chain
// @Accept json
// @Produce json
// @Param page query number false "Page"
// @Param limit query number false "Items per page"
// @Param height query number false "Block height"
// @Success 200 {object} TransactionsList "List of transactions references"
// @Router /chain/transactions [get]
func (a *API) chainTxListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
params, err := parseTransactionParams(
ctx.QueryParam(ParamPage),
ctx.QueryParam(ParamLimit),
ctx.QueryParam(ParamHeight),
ctx.QueryParam(ParamType),
)
if err != nil {
return err
}

return a.sendTransactionList(ctx, params)
}

// chainTxListByPageHandler
//
// @Summary List transactions
Expand All @@ -713,6 +745,7 @@ func (a *API) chainTxListByPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTPC
ctx.URLParam(ParamPage),
"",
"",
"",
)
if err != nil {
return err
Expand All @@ -725,71 +758,27 @@ func (a *API) chainTxListByPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTPC
//
// @Summary Transactions in a block
// @Description Given a block returns the list of transactions for that block
// @Deprecated
// @Description (deprecated, in favor of /chain/transactions?page=xxx&height=xxx)
// @Tags Chain
// @Accept json
// @Produce json
// @Param height path number true "Block height"
// @Param page path number true "Page"
// @Success 200 {object} []TransactionMetadata
// @Success 200 {object} TransactionsList
// @Router /chain/blocks/{height}/transactions/page/{page} [get]
func (a *API) chainTxListByHeightAndPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
params, err := parseTransactionParams(
ctx.URLParam(ParamPage),
"",
ctx.URLParam(ParamHeight),
"",
)
if err != nil {
return err
}

// TODO: replace all of this with the indexer method,
// from the other PR, TransactionListByHeight
block := a.vocapp.GetBlockByHeight(int64(params.Height))
if block == nil {
return ErrBlockNotFound
}
blockTxs := &BlockTransactionsInfo{
BlockNumber: params.Height,
TransactionsCount: uint32(len(block.Txs)),
Transactions: make([]TransactionMetadata, 0),
}

count := 0
for i := params.Page * params.Limit; i < len(block.Txs); i++ {
if count >= params.Limit {
break
}
signedTx := new(models.SignedTx)
tx := new(models.Tx)
var err error
if err := proto.Unmarshal(block.Txs[i], signedTx); err != nil {
return ErrUnmarshalingServerProto.WithErr(err)
}
if err := proto.Unmarshal(signedTx.Tx, tx); err != nil {
return ErrUnmarshalingServerProto.WithErr(err)
}
txType := string(
tx.ProtoReflect().WhichOneof(
tx.ProtoReflect().Descriptor().Oneofs().Get(0)).Name())

// TODO: can we avoid indexer Get calls in a loop?
txRef, err := a.indexer.GetTxHashReference(block.Txs[i].Hash())
if err != nil {
return ErrTransactionNotFound
}
blockTxs.Transactions = append(blockTxs.Transactions, TransactionMetadata{
Type: txType,
Index: int32(i),
Number: uint32(txRef.Index),
Hash: block.Txs[i].Hash(),
})
count++
}
data, err := json.Marshal(blockTxs)
if err != nil {
return err
}
return ctx.Send(data, apirest.HTTPstatusOK)
return a.sendTransactionList(ctx, params)
}

// sendTransactionList produces a filtered, paginated TransactionList,
Expand All @@ -798,8 +787,10 @@ func (a *API) chainTxListByHeightAndPageHandler(_ *apirest.APIdata, ctx *httprou
// Errors returned are always of type APIerror.
func (a *API) sendTransactionList(ctx *httprouter.HTTPContext, params *TransactionParams) error {
txs, total, err := a.indexer.SearchTransactions(
int32(params.Limit),
int32(params.Page*params.Limit),
params.Limit,
params.Page*params.Limit,
params.Height,
params.Type,
)
if err != nil {
return ErrIndexerQueryFailed.WithErr(err)
Expand Down Expand Up @@ -1148,7 +1139,7 @@ func parseFeesParams(paramPage, paramLimit, paramReference, paramType, paramAcco
}

// parseTransactionParams returns an TransactionParams filled with the passed params
func parseTransactionParams(paramPage, paramLimit, paramHeight string) (*TransactionParams, error) {
func parseTransactionParams(paramPage, paramLimit, paramHeight, paramType string) (*TransactionParams, error) {
pagination, err := parsePaginationParams(paramPage, paramLimit)
if err != nil {
return nil, err
Expand All @@ -1162,5 +1153,6 @@ func parseTransactionParams(paramPage, paramLimit, paramHeight string) (*Transac
return &TransactionParams{
PaginationParams: pagination,
Height: uint64(height),
Type: paramType,
}, nil
}
20 changes: 10 additions & 10 deletions vochain/indexer/db/db.go

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

110 changes: 67 additions & 43 deletions vochain/indexer/db/transactions.sql.go

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

Loading

0 comments on commit a46a92c

Please sign in to comment.