Skip to content

Commit

Permalink
fp endpoitn with stats
Browse files Browse the repository at this point in the history
  • Loading branch information
gusin13 committed Nov 30, 2024
1 parent 8429c7f commit d5cc704
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 32 deletions.
1 change: 1 addition & 0 deletions internal/v2/db/client/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type V2DBClient interface {
dbclient.DBClient
GetOverallStats(ctx context.Context) (*v2dbmodel.V2OverallStatsDocument, error)
GetStakerStats(ctx context.Context, stakerPKHex string) (*v2dbmodel.V2StakerStatsDocument, error)
GetFinalityProviderStats(ctx context.Context) ([]*v2dbmodel.V2FinalityProviderStatsDocument, error)
GetOrCreateStatsLock(
ctx context.Context, stakingTxHashHex string, state string,
) (*v2dbmodel.V2StatsLockDocument, error)
Expand Down
17 changes: 17 additions & 0 deletions internal/v2/db/client/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,3 +408,20 @@ func (v2dbclient *V2Database) updateFinalityProviderStats(
_, txErr := session.WithTransaction(ctx, transactionWork)
return txErr
}

func (v2dbclient *V2Database) GetFinalityProviderStats(
ctx context.Context,
) ([]*v2dbmodel.V2FinalityProviderStatsDocument, error) {
client := v2dbclient.Client.Database(v2dbclient.DbName).Collection(dbmodel.V2FinalityProviderStatsCollection)
cursor, err := client.Find(ctx, bson.M{})
if err != nil {
return nil, err
}
defer cursor.Close(ctx)

var results []*v2dbmodel.V2FinalityProviderStatsDocument
if err := cursor.All(ctx, &results); err != nil {
return nil, err
}
return results, nil
}
25 changes: 6 additions & 19 deletions internal/v2/db/model/stats.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package v2dbmodel

import dbmodel "github.com/babylonlabs-io/staking-api-service/internal/shared/db/model"

// StatsLockDocument represents the document in the stats lock collection
// It's used as a lock to prevent concurrent stats calculation for the same staking tx hash
// As well as to prevent the same staking tx hash + txType to be processed multiple times
Expand Down Expand Up @@ -41,21 +39,10 @@ type V2StakerStatsDocument struct {
TotalDelegations int64 `bson:"total_delegations"`
}

// StakerStatsByStakerPagination is used to paginate the top stakers by active tvl
// ActiveTvl is used as the sorting key, whereas StakerPkHex is used as the secondary sorting key
type V2StakerStatsByStakerPagination struct {
StakerPkHex string `json:"staker_pk_hex"`
ActiveTvl int64 `json:"active_tvl"`
}

func BuildV2StakerStatsByStakerPaginationToken(d *V2StakerStatsDocument) (string, error) {
page := V2StakerStatsByStakerPagination{
StakerPkHex: d.StakerPkHex,
ActiveTvl: d.ActiveTvl,
}
token, err := dbmodel.GetPaginationToken(page)
if err != nil {
return "", err
}
return token, nil
type V2FinalityProviderStatsDocument struct {
FinalityProviderPkHex string `bson:"_id"`
ActiveTvl int64 `bson:"active_tvl"`
TotalTvl int64 `bson:"total_tvl"`
ActiveDelegations int64 `bson:"active_delegations"`
TotalDelegations int64 `bson:"total_delegations"`
}
60 changes: 47 additions & 13 deletions internal/v2/service/finality_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
indexerdbmodel "github.com/babylonlabs-io/staking-api-service/internal/indexer/db/model"
"github.com/babylonlabs-io/staking-api-service/internal/shared/db"
"github.com/babylonlabs-io/staking-api-service/internal/shared/types"
v2dbmodel "github.com/babylonlabs-io/staking-api-service/internal/v2/db/model"
"github.com/rs/zerolog/log"
)

Expand All @@ -23,39 +24,72 @@ type FinalityProvidersStatsPublic struct {
FinalityProviders []FinalityProviderStatsPublic `json:"finality_providers"`
}

func mapToFinalityProviderStatsPublic(provider indexerdbmodel.IndexerFinalityProviderDetails) *FinalityProviderStatsPublic {
func mapToFinalityProviderStatsPublic(
provider indexerdbmodel.IndexerFinalityProviderDetails,
fpStats *v2dbmodel.V2FinalityProviderStatsDocument,
) *FinalityProviderStatsPublic {
return &FinalityProviderStatsPublic{
BtcPk: provider.BtcPk,
State: types.FinalityProviderQueryingState(provider.State),
Description: types.FinalityProviderDescription(provider.Description),
Commission: provider.Commission,
ActiveTvl: 0,
ActiveDelegations: 0,
ActiveTvl: fpStats.ActiveTvl,
ActiveDelegations: fpStats.ActiveDelegations,
}
}

// GetFinalityProviders gets a list of finality providers with stats
// GetFinalityProvidersWithStats retrieves all finality providers and their associated statistics
func (s *V2Service) GetFinalityProvidersWithStats(
ctx context.Context,
) ([]*FinalityProviderStatsPublic, *types.Error) {
fps, err := s.DbClients.IndexerDBClient.GetFinalityProviders(ctx)
finalityProviders, err := s.DbClients.IndexerDBClient.GetFinalityProviders(ctx)
if err != nil {
if db.IsNotFoundError(err) {
log.Ctx(ctx).Warn().Err(err).Msg("Finality providers not found")
log.Ctx(ctx).Warn().Err(err).Msg("No finality providers found")
return nil, types.NewErrorWithMsg(
http.StatusNotFound, types.NotFound, "finality providers not found, please retry",
http.StatusNotFound,
types.NotFound,
"finality providers not found, please retry",
)
}
return nil, types.NewErrorWithMsg(
http.StatusInternalServerError, types.InternalServiceError, "failed to get finality providers",
http.StatusInternalServerError,
types.InternalServiceError,
"failed to get finality providers",
)
}

// TODO: Call the FP stats service to get the stats for compose the response
providersPublic := make([]*FinalityProviderStatsPublic, 0, len(fps))
providerStats, err := s.DbClients.V2DBClient.GetFinalityProviderStats(ctx)
if err != nil {
return nil, types.NewErrorWithMsg(
http.StatusInternalServerError,
types.InternalServiceError,
"failed to get finality provider stats",
)
}

for _, provider := range fps {
providersPublic = append(providersPublic, mapToFinalityProviderStatsPublic(*provider))
statsLookup := make(map[string]*v2dbmodel.V2FinalityProviderStatsDocument)
for _, stats := range providerStats {
statsLookup[stats.FinalityProviderPkHex] = stats
}

finalityProvidersWithStats := make([]*FinalityProviderStatsPublic, 0, len(finalityProviders))

for _, provider := range finalityProviders {
providerStats, hasStats := statsLookup[provider.BtcPk]
if !hasStats {
providerStats = &v2dbmodel.V2FinalityProviderStatsDocument{
ActiveTvl: 0,
ActiveDelegations: 0,
}
log.Ctx(ctx).Debug().
Str("finality_provider_pk_hex", provider.BtcPk).
Msg("Initializing finality provider with default stats")
}
finalityProvidersWithStats = append(
finalityProvidersWithStats,
mapToFinalityProviderStatsPublic(*provider, providerStats),
)
}
return providersPublic, nil
return finalityProvidersWithStats, nil
}
30 changes: 30 additions & 0 deletions tests/mocks/mock_v2_db_client.go

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

0 comments on commit d5cc704

Please sign in to comment.