Skip to content

Commit

Permalink
Merge pull request #31 from flare-foundation/list-transactions-api
Browse files Browse the repository at this point in the history
Add new API route to list transactions for epoch
  • Loading branch information
mboben authored Nov 17, 2023
2 parents ac187bf + 6ea2153 commit 0d2aba6
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 42 deletions.
37 changes: 37 additions & 0 deletions services/api/pchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,40 @@ func newApiPChainOutputs(inputs []database.PChainTxOutput) []ApiPChainTxOutput {
}
return result
}

type ApiPChainTxListItem struct {
Type database.PChainTxType `json:"type"`
TxID *string `json:"txID"`
BlockHeight uint64 `json:"blockHeight"`
ChainID string `json:"chainID"`
NodeID string `json:"nodeID"`
StartTime *time.Time `json:"startTime"`
EndTime *time.Time `json:"endTime"`
Weight uint64 `json:"weight"`
InputAddress string `json:"inputAddress"`
InputIndex uint32 `json:"inputIndex"`
}

func newApiPChainTxListItem(tx *database.PChainTxData) ApiPChainTxListItem {
return ApiPChainTxListItem{
Type: tx.Type,
TxID: tx.TxID,
BlockHeight: tx.BlockHeight,
ChainID: tx.ChainID,
NodeID: tx.NodeID,
StartTime: tx.StartTime,
EndTime: tx.EndTime,
Weight: tx.Weight,
InputAddress: tx.InputAddress,
InputIndex: tx.InputIndex,
}
}

func NewApiPChainTxList(txs []database.PChainTxData) []ApiPChainTxListItem {
result := make([]ApiPChainTxListItem, len(txs))
for i, tx := range txs {
result[i] = newApiPChainTxListItem(&tx)
}

return result
}
11 changes: 7 additions & 4 deletions services/main/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,21 @@ func main() {
log.Fatal(err) // logger possibly not initialized here so use builtin log
}

epochs, err := utils.NewEpochInfo(ctx)
if err != nil {
log.Fatal(err)
}

muxRouter := mux.NewRouter()
router := utils.NewSwaggerRouter(muxRouter, "Flare P-Chain Indexer", "0.1.0")
routes.AddTransferRoutes(router, ctx)
routes.AddStakerRoutes(router, ctx)
routes.AddTransactionRoutes(router, ctx)
routes.AddTransactionRoutes(router, ctx, epochs)
routes.AddMirroringRoutes(router, ctx, epochs)

// Disabled -- state connector routes are currently not used
// routes.AddQueryRoutes(router, ctx)

if err := routes.AddMirroringRoutes(router, ctx); err != nil {
logger.Fatal("Failed to add mirroring routes: %v", err)
}
router.Finalize()

cors := cors.New(cors.Options{
Expand Down
37 changes: 4 additions & 33 deletions services/routes/mirroring.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ package routes

import (
"errors"
globalConfig "flare-indexer/config"
"flare-indexer/database"
"flare-indexer/services/config"
"flare-indexer/services/context"
"flare-indexer/services/utils"
"flare-indexer/utils/contracts/mirroring"
"flare-indexer/utils/contracts/voting"
"flare-indexer/utils/staking"
"fmt"
"net/http"
Expand Down Expand Up @@ -50,32 +47,11 @@ type mirroringRouteHandlers struct {
epochs staking.EpochInfo
}

func newMirroringRouteHandlers(ctx context.ServicesContext) (*mirroringRouteHandlers, error) {
cfg := ctx.Config()

start, period, err := getEpochStartAndPeriod(cfg)
if err != nil {
return nil, err
}

func newMirroringRouteHandlers(ctx context.ServicesContext, epochs staking.EpochInfo) *mirroringRouteHandlers {
return &mirroringRouteHandlers{
db: NewMirrorDBGorm(ctx.DB()),
epochs: staking.NewEpochInfo(&globalConfig.EpochConfig{}, start, period),
}, nil
}

func getEpochStartAndPeriod(cfg *config.Config) (time.Time, time.Duration, error) {
eth, err := cfg.Chain.DialETH()
if err != nil {
return time.Time{}, 0, err
epochs: epochs,
}

votingContract, err := voting.NewVoting(cfg.ContractAddresses.Voting, eth)
if err != nil {
return time.Time{}, 0, err
}

return staking.GetEpochConfig(votingContract)
}

func (rh *mirroringRouteHandlers) listMirroringTransactions() utils.RouteHandler {
Expand All @@ -101,16 +77,11 @@ func (rh *mirroringRouteHandlers) listMirroringTransactions() utils.RouteHandler
GetMirroringResponse{})
}

func AddMirroringRoutes(router utils.Router, ctx context.ServicesContext) error {
rh, err := newMirroringRouteHandlers(ctx)
if err != nil {
return err
}
func AddMirroringRoutes(router utils.Router, ctx context.ServicesContext, epochs staking.EpochInfo) {
rh := newMirroringRouteHandlers(ctx, epochs)

mirroringSubrouter := router.WithPrefix("/mirroring", "Mirroring")
mirroringSubrouter.AddRoute("/tx_data/{tx_id:[0-9a-zA-Z]+}", rh.listMirroringTransactions())

return nil
}

func (rh *mirroringRouteHandlers) createMirroringData(tx *database.PChainTx) ([]MirroringResponse, error) {
Expand Down
43 changes: 38 additions & 5 deletions services/routes/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ import (
"flare-indexer/services/api"
"flare-indexer/services/context"
"flare-indexer/services/utils"
"flare-indexer/utils/staking"
"net/http"
"strconv"

"gorm.io/gorm"
)

type transactionRouteHandlers struct {
db *gorm.DB
db *gorm.DB
epochs staking.EpochInfo
}

func newTransactionRouteHandlers(ctx context.ServicesContext) *transactionRouteHandlers {
func newTransactionRouteHandlers(ctx context.ServicesContext, epochs staking.EpochInfo) *transactionRouteHandlers {
return &transactionRouteHandlers{
db: ctx.DB(),
db: ctx.DB(),
epochs: epochs,
}
}

Expand All @@ -41,8 +45,37 @@ func (rh *transactionRouteHandlers) getTransaction() utils.RouteHandler {
&api.ApiPChainTx{})
}

func AddTransactionRoutes(router utils.Router, ctx context.ServicesContext) {
vr := newTransactionRouteHandlers(ctx)
func (rh *transactionRouteHandlers) listTransactions() utils.RouteHandler {
handler := func(params map[string]string) ([]api.ApiPChainTxListItem, *utils.ErrorHandler) {
epoch, err := strconv.ParseInt(params["epoch"], 10, 64)
if err != nil {
return nil, utils.HttpErrorHandler(http.StatusBadRequest, "Invalid epoch")
}

startTimestamp, endTimestamp := rh.epochs.GetTimeRange(epoch)
txs, err := database.GetPChainTxsForEpoch(&database.GetPChainTxsForEpochInput{
DB: rh.db,
StartTimestamp: startTimestamp,
EndTimestamp: endTimestamp,
})
if err != nil {
return nil, utils.InternalServerErrorHandler(err)
}

return api.NewApiPChainTxList(txs), nil
}

return utils.NewParamRouteHandler(handler, http.MethodGet,
map[string]string{"epoch:[0-9]+": "Epoch"},
[]api.ApiPChainTxListItem{},
)
}

func AddTransactionRoutes(
router utils.Router, ctx context.ServicesContext, epochs staking.EpochInfo,
) {
vr := newTransactionRouteHandlers(ctx, epochs)
subrouter := router.WithPrefix("/transactions", "Transactions")
subrouter.AddRoute("/get/{tx_id:[0-9a-zA-Z]+}", vr.getTransaction())
subrouter.AddRoute("/list/{epoch:[0-9]+}", vr.listTransactions())
}
35 changes: 35 additions & 0 deletions services/utils/epochs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package utils

import (
globalconfig "flare-indexer/config"
"flare-indexer/services/config"
"flare-indexer/services/context"
"flare-indexer/utils/contracts/voting"
"flare-indexer/utils/staking"
"time"
)

func NewEpochInfo(ctx context.ServicesContext) (staking.EpochInfo, error) {
cfg := ctx.Config()

start, period, err := getEpochStartAndPeriod(cfg)
if err != nil {
return staking.EpochInfo{}, err
}

return staking.NewEpochInfo(&globalconfig.EpochConfig{}, start, period), nil
}

func getEpochStartAndPeriod(cfg *config.Config) (time.Time, time.Duration, error) {
eth, err := cfg.Chain.DialETH()
if err != nil {
return time.Time{}, 0, err
}

votingContract, err := voting.NewVoting(cfg.ContractAddresses.Voting, eth)
if err != nil {
return time.Time{}, 0, err
}

return staking.GetEpochConfig(votingContract)
}

0 comments on commit 0d2aba6

Please sign in to comment.