wormhole-explorer/analytics/cmd/metrics/volume.go

89 lines
2.7 KiB
Go

package metrics
import (
"errors"
"fmt"
"time"
"github.com/influxdata/influxdb-client-go/v2/api/write"
"github.com/shopspring/decimal"
"github.com/wormhole-foundation/wormhole-explorer/analytics/internal/metrics"
"github.com/wormhole-foundation/wormhole-explorer/analytics/metric"
"github.com/wormhole-foundation/wormhole-explorer/analytics/prices"
"github.com/wormhole-foundation/wormhole-explorer/common/domain"
sdk "github.com/wormhole-foundation/wormhole/sdk/vaa"
)
type VaaConverter struct {
MissingTokens map[sdk.Address]sdk.ChainID
MissingTokensCounter map[sdk.Address]int
PriceCache *prices.CoinPricesCache
Metrics metrics.Metrics
}
func NewVaaConverter(priceCache *prices.CoinPricesCache) *VaaConverter {
return &VaaConverter{
MissingTokens: make(map[sdk.Address]sdk.ChainID),
MissingTokensCounter: make(map[sdk.Address]int),
PriceCache: priceCache,
Metrics: metrics.NewNoopMetrics(),
}
}
func (c *VaaConverter) Convert(vaaBytes []byte) (string, error) {
// Parse the VAA and payload
vaa, err := sdk.Unmarshal(vaaBytes)
if err != nil {
return "", fmt.Errorf("error unmarshaling vaa: %v", err)
}
payload, err := sdk.DecodeTransferPayloadHdr(vaa.Payload)
if err != nil {
return "", fmt.Errorf("error decoding payload: %v", err)
}
// Look up token metadata
tokenMetadata, ok := domain.GetTokenByAddress(payload.OriginChain, payload.OriginAddress.String())
if !ok {
// if not found, add to missing tokens
c.MissingTokens[payload.OriginAddress] = payload.OriginChain
c.MissingTokensCounter[payload.OriginAddress] = c.MissingTokensCounter[payload.OriginAddress] + 1
return "", fmt.Errorf("unknown token: %s %s", payload.OriginChain.String(), payload.OriginAddress.String())
}
// Generate a data point for the VAA volume metric
var point *write.Point
{
p := metric.MakePointForVaaVolumeParams{
Vaa: vaa,
TokenPriceFunc: func(_ string, timestamp time.Time) (decimal.Decimal, error) {
// fetch the historic price from cache
price, err := c.PriceCache.GetPriceByTime(tokenMetadata.CoingeckoID, timestamp)
if err != nil {
return decimal.NewFromInt(0), err
}
return price, nil
},
Metrics: c.Metrics,
}
var err error
point, err = metric.MakePointForVaaVolume(&p)
if err != nil {
return "", fmt.Errorf("failed to create data point for VAA volume metric: %v", err)
}
if point == nil {
// Some VAAs don't generate any data points for this metric (e.g.: PythNet, non-token-bridge VAAs)
return "", errors.New("can't generate point for VAA volume metric")
}
}
// Convert the data point to line protocol
result := convertPointToLineProtocol(point)
return result, nil
}