Add api endpoint to get total count and volume

This commit is contained in:
Agustin Pazos 2023-05-11 19:18:31 -03:00
parent 01b34a84e8
commit d8723c056b
9 changed files with 57 additions and 74 deletions

View File

@ -9,9 +9,12 @@ import (
)
type Scorecards struct {
// Number of VAAs emitted since the creation of the network (does not include Pyth messages)
// Total number of VAAs emitted since the creation of the network (does not include Pyth messages).
TotalTxCount string
// Volume transferred through the token bridge since the creation of the network, in USD.
TotalTxVolume string
// Number of VAAs emitted in the last 24 hours (does not include Pyth messages).
TxCount24h string

View File

@ -13,6 +13,8 @@ import (
"github.com/pkg/errors"
errs "github.com/wormhole-foundation/wormhole-explorer/api/internal/errors"
"github.com/wormhole-foundation/wormhole-explorer/common/domain"
"github.com/wormhole-foundation/wormhole-explorer/common/storage/portalanalytic"
"github.com/wormhole-foundation/wormhole-explorer/fly/storage"
sdk "github.com/wormhole-foundation/wormhole/sdk/vaa"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
@ -92,6 +94,7 @@ type Repository struct {
bucketInfiniteRetention string
bucket30DaysRetention string
bucket24HoursRetention string
portalAnalyticRepo *portalanalytic.Repository
db *mongo.Database
collections struct {
globalTransactions *mongo.Collection
@ -104,6 +107,7 @@ func NewRepository(
org string,
bucket24HoursRetention, bucket30DaysRetention, bucketInfiniteRetention string,
db *mongo.Database,
portalAnalyticRepo *portalanalytic.Repository,
logger *zap.Logger,
) *Repository {
@ -113,6 +117,7 @@ func NewRepository(
bucket24HoursRetention: bucket24HoursRetention,
bucket30DaysRetention: bucket30DaysRetention,
bucketInfiniteRetention: bucketInfiniteRetention,
portalAnalyticRepo: portalAnalyticRepo,
db: db,
collections: struct{ globalTransactions *mongo.Collection }{globalTransactions: db.Collection("globalTransactions")},
logger: logger,
@ -231,19 +236,19 @@ func (r *Repository) buildFindVolumeQuery(q *ChainActivityQuery) string {
}
func (r *Repository) GetScorecards(ctx context.Context) (*Scorecards, error) {
// get historic total count and volume.
totalTxCount, totalTxVolume, err := r.getTotalCountAndVolume(ctx)
if err != nil {
return nil, err
}
//TODO the underlying query in this code is not using pre-summarized data.
// We should fix that before re-enabling the metric.
//totalTxCount, err := r.getTotalTxCount(ctx)
//if err != nil {
// return nil, fmt.Errorf("failed to query all-time tx count")
//}
// get 24h transactions
txCount24h, err := r.getTxCount24h(ctx)
if err != nil {
return nil, fmt.Errorf("failed to query 24h transactions: %w", err)
}
// get 24h volume
volume24h, err := r.getVolume24h(ctx)
if err != nil {
return nil, fmt.Errorf("failed to query 24h volume: %w", err)
@ -251,40 +256,35 @@ func (r *Repository) GetScorecards(ctx context.Context) (*Scorecards, error) {
// build the result and return
scorecards := Scorecards{
//TotalTxCount: totalTxCount,
TxCount24h: txCount24h,
Volume24h: volume24h,
TotalTxCount: fmt.Sprint(totalTxCount),
TotalTxVolume: fmt.Sprint(totalTxVolume),
TxCount24h: txCount24h,
Volume24h: volume24h,
}
return &scorecards, nil
}
func (r *Repository) getTotalTxCount(ctx context.Context) (string, error) {
// query 24h transactions
query := fmt.Sprintf(queryTemplateTotalTxCount, r.bucketInfiniteRetention)
result, err := r.queryAPI.Query(ctx, query)
// getTotalCountAndVolume get historic total count and volume.
func (r *Repository) getTotalCountAndVolume(ctx context.Context) (storage.Uint64, storage.Uint64, error) {
var totalTxCount, totalTxVolume storage.Uint64
var ids = []string{"tx_volume_historic", "tx_volume", "tx_count_historic", "tx_count"}
portalAnalytics, err := r.portalAnalyticRepo.GetPortalAnalyticByIds(ctx, ids)
if err != nil {
r.logger.Error("failed to query total transaction count", zap.Error(err))
return "", err
}
if result.Err() != nil {
r.logger.Error("total transaction count query result has errors", zap.Error(err))
return "", result.Err()
}
if !result.Next() {
return "", errors.New("expected at least one record in total transaction count query result")
return 0, 0, err
}
for _, portalAnalytic := range portalAnalytics {
if portalAnalytic.ID == "tx_count_historic" || portalAnalytic.ID == "tx_count" {
totalTxCount = totalTxCount + portalAnalytic.Value
continue
}
if portalAnalytic.ID == "tx_volume_historic" || portalAnalytic.ID == "tx_volume" {
totalTxVolume = totalTxVolume + portalAnalytic.Value
continue
}
// deserialize the row returned
row := struct {
Value uint64 `mapstructure:"_value"`
}{}
if err := mapstructure.Decode(result.Record().Values(), &row); err != nil {
return "", fmt.Errorf("failed to decode total transaction count query response: %w", err)
}
return fmt.Sprint(row.Value), nil
return totalTxCount, totalTxVolume, nil
}
func (r *Repository) getTxCount24h(ctx context.Context) (string, error) {

View File

@ -38,6 +38,7 @@ import (
wormscanCache "github.com/wormhole-foundation/wormhole-explorer/common/client/cache"
wormscanNotionalCache "github.com/wormhole-foundation/wormhole-explorer/common/client/cache/notional"
xlogger "github.com/wormhole-foundation/wormhole-explorer/common/logger"
"github.com/wormhole-foundation/wormhole-explorer/common/storage/portalanalytic"
"go.uber.org/zap"
)
@ -112,6 +113,7 @@ func main() {
governorRepo := governor.NewRepository(db, rootLogger)
infrastructureRepo := infrastructure.NewRepository(db, rootLogger)
heartbeatsRepo := heartbeats.NewRepository(db, rootLogger)
portalAnalytcRepo := portalanalytic.NewPortalAnalytic(db, rootLogger)
transactionsRepo := transactions.NewRepository(
influxCli,
cfg.Influx.Organization,
@ -119,6 +121,7 @@ func main() {
cfg.Influx.Bucket30Days,
cfg.Influx.BucketInfinite,
db,
portalAnalytcRepo,
rootLogger,
)

View File

@ -77,9 +77,10 @@ func (c *Controller) GetScorecards(ctx *fiber.Ctx) error {
// Convert indicators to the response model
response := ScorecardsResponse{
TotalTxCount: scorecards.TotalTxCount,
TxCount24h: scorecards.TxCount24h,
Volume24h: scorecards.Volume24h,
TotalTxCount: scorecards.TotalTxCount,
TotalTxVolume: scorecards.TotalTxVolume,
TxCount24h: scorecards.TxCount24h,
Volume24h: scorecards.Volume24h,
}
return ctx.JSON(response)

View File

@ -30,10 +30,11 @@ type ScorecardsResponse struct {
// Number of VAAs emitted in the last 24 hours (includes Pyth messages).
//Messages24h string `json:"24h_messages"`
// Number of VAAs emitted since the creation of the network (does not include Pyth messages)
TotalTxCount string `json:"total_tx_count,omitempty"`
// Total number of VAAs emitted since the creation of the network (does not include Pyth messages).
TotalTxCount string `json:"total_tx_count"`
//TotalVolume string `json:"total_volume"`
// Volume transferred through the token bridge since the creation of the network, in USD.
TotalTxVolume string `json:"total_volume"`
//TVL string `json:"tvl"`

View File

@ -1,6 +1,6 @@
package portalanalytic
import "github.com/wormhole-foundation/wormhole-explorer/common/storage"
import "github.com/wormhole-foundation/wormhole-explorer/fly/storage"
// PortalAnalyticDoc is a portal analytic document.
type PortalAnalyticdDoc struct {

View File

@ -1,6 +1,8 @@
package portalanalytic
import (
"context"
"go.mongodb.org/mongo-driver/mongo"
"go.uber.org/zap"
)
@ -23,6 +25,6 @@ func NewPortalAnalytic(db *mongo.Database, log *zap.Logger) *Repository {
}
// GetPortalAnalytic get portal analytic.
func (r *Repository) GetPortalAnalyticByIds(ids []string) ([]*PortalAnalyticdDoc, error) {
func (r *Repository) GetPortalAnalyticByIds(ctx context.Context, ids []string) ([]*PortalAnalyticdDoc, error) {
return []*PortalAnalyticdDoc{}, nil
}

View File

@ -1,33 +0,0 @@
package storage
import (
"errors"
"strconv"
"go.mongodb.org/mongo-driver/bson/bsontype"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
)
type Uint64 uint64
func (u Uint64) MarshalBSONValue() (bsontype.Type, []byte, error) {
ui64Str := strconv.FormatUint(uint64(u), 10)
d128, err := primitive.ParseDecimal128(ui64Str)
return bsontype.Decimal128, bsoncore.AppendDecimal128(nil, d128), err
}
func (u *Uint64) UnmarshalBSONValue(t bsontype.Type, b []byte) error {
d128, _, ok := bsoncore.ReadDecimal128(b)
if !ok {
return errors.New("Uint64 UnmarshalBSONValue error")
}
ui64, err := strconv.ParseUint(d128.String(), 10, 64)
if err != nil {
return err
}
*u = Uint64(ui64)
return nil
}

View File

@ -65,6 +65,12 @@ func Run(db *mongo.Database) error {
return err
}
// Create vaaIdTxHash collection.
err = db.CreateCollection(context.TODO(), "portalAnalytic")
if err != nil && isNotAlreadyExistsError(err) {
return err
}
// create index in vaas collection by vaa key (emitterchain, emitterAddr, sequence)
indexVaaByKey := mongo.IndexModel{
Keys: bson.D{