Add transfer prices backfiller in analytics (#1153)

* Add transfer prices backfiller in analytics
Save notional prices in s3 bucket

* Code review updates
This commit is contained in:
ftocal 2024-02-27 15:17:59 -03:00 committed by GitHub
parent 91ce905768
commit a882355c05
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 713 additions and 547 deletions

View File

@ -1,10 +1,14 @@
package main
import (
"log"
"time"
"github.com/spf13/cobra"
"github.com/wormhole-foundation/wormhole-explorer/analytics/cmd/metrics"
"github.com/wormhole-foundation/wormhole-explorer/analytics/cmd/prices"
"github.com/wormhole-foundation/wormhole-explorer/analytics/cmd/service"
sdk "github.com/wormhole-foundation/wormhole/sdk/vaa"
)
func main() {
@ -148,29 +152,105 @@ func addVaaVolumeCommand(parent *cobra.Command) {
parent.AddCommand(vaaVolumeCmd)
}
func addPricesCommand(root *cobra.Command) {
func addPricesCommand(parent *cobra.Command) {
addHistoryPrices(parent)
addVaasPrices(parent)
}
func addHistoryPrices(parent *cobra.Command) {
var output, p2pNetwork, coingeckoUrl, coingeckoHeaderKey, coingeckoApiKey string
vaaCountCmd := &cobra.Command{
historyPricesCmd := &cobra.Command{
Use: "history",
Short: "Generate notional price history for symbol",
Run: func(_ *cobra.Command, _ []string) {
prices.RunPrices(output, p2pNetwork, coingeckoUrl, coingeckoHeaderKey, coingeckoApiKey)
prices.RunHistoryPrices(output, p2pNetwork, coingeckoUrl, coingeckoHeaderKey, coingeckoApiKey)
},
}
// output flag
vaaCountCmd.Flags().StringVar(&output, "output", "", "path to output file")
vaaCountCmd.MarkFlagRequired("output")
historyPricesCmd.Flags().StringVar(&output, "output", "", "path to output file")
historyPricesCmd.MarkFlagRequired("output")
//p2p-network flag
vaaCountCmd.Flags().StringVar(&p2pNetwork, "p2p-network", "", "P2P network")
vaaCountCmd.MarkFlagRequired("p2p-network")
historyPricesCmd.Flags().StringVar(&p2pNetwork, "p2p-network", "", "P2P network")
historyPricesCmd.MarkFlagRequired("p2p-network")
//coingecko flags
vaaCountCmd.Flags().StringVar(&coingeckoUrl, "coingecko-url", "", "Coingecko URL")
vaaCountCmd.MarkFlagRequired("coingecko-url")
historyPricesCmd.Flags().StringVar(&coingeckoUrl, "coingecko-url", "", "Coingecko URL")
historyPricesCmd.MarkFlagRequired("coingecko-url")
vaaCountCmd.Flags().StringVar(&coingeckoHeaderKey, "coingecko-header-key", "", "Coingecko header key")
vaaCountCmd.Flags().StringVar(&coingeckoApiKey, "coingecko-api-key", "", "Coingecko api key")
historyPricesCmd.Flags().StringVar(&coingeckoHeaderKey, "coingecko-header-key", "", "Coingecko header key")
historyPricesCmd.Flags().StringVar(&coingeckoApiKey, "coingecko-api-key", "", "Coingecko api key")
root.AddCommand(vaaCountCmd)
parent.AddCommand(historyPricesCmd)
}
func addVaasPrices(parent *cobra.Command) {
var cfg prices.VaasPrices
var start, end, emitterAddress, sequence string
var emitterChainID uint16
vaasPricesCmd := &cobra.Command{
Use: "vaas",
Short: "Add price to VAA",
Run: func(_ *cobra.Command, _ []string) {
if emitterChainID != 0 {
eci := sdk.ChainID(emitterChainID)
cfg.EmitterChainID = &eci
}
if emitterAddress != "" {
cfg.EmitterAddress = &emitterAddress
}
if sequence != "" {
cfg.Sequence = &sequence
}
if start != "" {
st, err := time.Parse(time.RFC3339, start)
if err != nil {
log.Fatal("Failed to parse start: ", err)
}
cfg.StartTime = &st
}
if end != "" {
et, err := time.Parse(time.RFC3339, end)
if err != nil {
log.Fatal("Failed to parse end: ", err)
}
cfg.StartTime = &et
}
prices.RunVaasPrices(cfg)
},
}
//mongo flags
vaasPricesCmd.Flags().StringVar(&cfg.MongoUri, "mongo-uri", "", "Mongo connection")
vaasPricesCmd.Flags().StringVar(&cfg.MongoDb, "mongo-database", "", "Mongo database")
vaasPricesCmd.Flags().Int64Var(&cfg.PageSize, "page-size", 1000, "number of documents retrieved at a time")
//p2p-network flag
vaasPricesCmd.Flags().StringVar(&cfg.P2PNetwork, "p2p-network", "", "P2P network")
vaasPricesCmd.MarkFlagRequired("p2p-network")
//notional url flags
vaasPricesCmd.Flags().StringVar(&cfg.NotionalUrl, "notional-url", "", "Notional URL")
vaasPricesCmd.MarkFlagRequired("notional-url")
//vaa-payload-parser-url flag
vaasPricesCmd.Flags().StringVar(&cfg.VaaPayloadParserUrl, "vaa-payload-parser-url", "", "VAA payload parser URL")
vaasPricesCmd.MarkFlagRequired("vaa-payload-parser-url")
// emitter-chain flag
vaasPricesCmd.Flags().Uint16Var(&emitterChainID, "emitter-chain", 0, "emitter chain id")
// emitter-address flag
vaasPricesCmd.Flags().StringVar(&emitterAddress, "emitter-address", "", "emitter address")
// sequence flag
vaasPricesCmd.Flags().StringVar(&sequence, "sequence", "", "sequence")
// start flag
vaasPricesCmd.Flags().StringVar(&start, "start", "", "start timestamp in RFC3339 format")
// end flag
vaasPricesCmd.Flags().StringVar(&end, "end", "", "end timestamp in RFC3339 format")
parent.AddCommand(vaasPricesCmd)
}

View File

@ -14,7 +14,7 @@ import (
// go througth the symbol list provided by wormhole
// and fetch the history from coingecko
// and save it to a file
func RunPrices(output, p2pNetwork, coingeckoUrl, coingeckoHeaderKey, coingeckoApiKey string) {
func RunHistoryPrices(output, p2pNetwork, coingeckoUrl, coingeckoHeaderKey, coingeckoApiKey string) {
// build logger
logger := logger.New("wormhole-explorer-analytics")

View File

@ -0,0 +1,140 @@
package prices
import (
"context"
"time"
"github.com/shopspring/decimal"
"github.com/wormhole-foundation/wormhole-explorer/analytics/cmd/token"
"github.com/wormhole-foundation/wormhole-explorer/analytics/metric"
"github.com/wormhole-foundation/wormhole-explorer/common/client/parser"
"github.com/wormhole-foundation/wormhole-explorer/common/dbutil"
"github.com/wormhole-foundation/wormhole-explorer/common/domain"
"github.com/wormhole-foundation/wormhole-explorer/common/logger"
apiPrices "github.com/wormhole-foundation/wormhole-explorer/common/prices"
"github.com/wormhole-foundation/wormhole-explorer/common/repository"
sdk "github.com/wormhole-foundation/wormhole/sdk/vaa"
"go.uber.org/zap"
)
type VaasPrices struct {
MongoUri string
MongoDb string
PageSize int64
P2PNetwork string
NotionalUrl string
VaaPayloadParserUrl string
StartTime *time.Time
EndTime *time.Time
EmitterChainID *sdk.ChainID
EmitterAddress *string
Sequence *string
}
func RunVaasPrices(cfg VaasPrices) {
ctx := context.Background()
// build logger
logger := logger.New("wormhole-explorer-analytics")
logger.Info("starting wormhole-explorer-analytics ...")
//setup DB connection
db, err := dbutil.Connect(ctx, logger, cfg.MongoUri, cfg.MongoDb, false)
if err != nil {
logger.Fatal("Failed to connect MongoDB", zap.Error(err))
}
// get transfer prices collection
transferPricesCollection := db.Database.Collection(repository.TransferPrices)
// create a parserVAAAPIClient
parserVAAAPIClient, err := parser.NewParserVAAAPIClient(5, cfg.VaaPayloadParserUrl, logger)
if err != nil {
logger.Fatal("failed to create parse vaa api client")
}
// create a new VAA repository
vaaRepository := repository.NewVaaRepository(db.Database, logger)
// create a token resolver
tokenResolver := token.NewTokenResolver(parserVAAAPIClient, logger)
// create a token provider
tokenProvider := domain.NewTokenProvider(cfg.P2PNetwork)
// create a price api
api := apiPrices.NewPricesApi(cfg.NotionalUrl, logger)
query := repository.VaaQuery{
StartTime: cfg.StartTime,
EndTime: cfg.EndTime,
EmitterChainID: cfg.EmitterChainID,
EmitterAddress: cfg.EmitterAddress,
Sequence: cfg.Sequence,
}
pagination := repository.Pagination{
Page: 0,
PageSize: cfg.PageSize,
SortAsc: true,
}
// start backfilling
for {
logger.Info("Processing page", zap.Any("pagination", pagination), zap.Any("query", query))
vaas, err := vaaRepository.FindPage(ctx, query, pagination)
if err != nil {
logger.Error("Failed to get vaas", zap.Error(err))
break
}
if len(vaas) == 0 {
logger.Info("Empty page", zap.Int64("page", pagination.Page))
break
}
for _, v := range vaas {
logger.Debug("Processing vaa", zap.String("id", v.ID))
vaa, err := sdk.Unmarshal(v.Vaa)
if err != nil {
logger.Error("Failed to unmarshal VAA", zap.Error(err))
continue
}
transferredToken, err := tokenResolver.GetTransferredTokenByVaa(ctx, vaa)
if err != nil {
if !token.IsUnknownTokenErr(err) {
logger.Error("Failed to obtain transferred token for this VAA",
zap.String("vaaId", vaa.MessageID()),
zap.Error(err))
}
continue
}
if err := metric.UpsertTransferPrices(
ctx,
logger,
vaa,
transferPricesCollection,
func(tokenID, coinGeckoID string, timestamp time.Time) (decimal.Decimal, error) {
price, err := api.GetPriceByTime(ctx, coinGeckoID, timestamp)
if err != nil {
return decimal.NewFromInt(0), err
}
return price, nil
},
transferredToken,
tokenProvider,
); err != nil {
logger.Error("Failed to upsert transfer prices", zap.String("id", v.ID), zap.Error(err))
}
}
pagination.Page++
}
logger.Info("finished wormhole-explorer-analytics")
}

View File

@ -4,7 +4,7 @@ go 1.19
require (
github.com/ansrivas/fiberprometheus/v2 v2.6.0
github.com/aws/aws-sdk-go-v2 v1.17.4
github.com/aws/aws-sdk-go-v2 v1.25.1
github.com/aws/aws-sdk-go-v2/config v1.1.1
github.com/aws/aws-sdk-go-v2/credentials v1.1.1
github.com/go-redis/redis/v8 v8.11.5
@ -28,15 +28,15 @@ require (
github.com/algorand/go-codec/codec v1.1.8 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.29 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sns v1.20.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sqs v1.20.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect
github.com/aws/smithy-go v1.13.5 // indirect
github.com/aws/smithy-go v1.20.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
@ -45,6 +45,7 @@ require (
github.com/deepmap/oapi-codegen v1.8.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/ethereum/go-ethereum v1.10.21 // indirect
github.com/go-resty/resty/v2 v2.11.0 // indirect
github.com/gofiber/adaptor/v2 v2.1.31 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
@ -78,11 +79,11 @@ require (
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
)

View File

@ -49,22 +49,26 @@ github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHG
github.com/ansrivas/fiberprometheus/v2 v2.6.0 h1:QUaaKxil/N5IM1R19k6jsmFEJMfa4O3qtnDkiF+zxUc=
github.com/ansrivas/fiberprometheus/v2 v2.6.0/go.mod h1:hivZjKkqX04PPbMZNi9iGB0AQ90iN6RmKERiX1TdgTA=
github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo=
github.com/aws/aws-sdk-go-v2 v1.17.4 h1:wyC6p9Yfq6V2y98wfDsj6OnNQa4w2BLGCLIxzNhwOGY=
github.com/aws/aws-sdk-go-v2 v1.17.4/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2 v1.25.1 h1:P7hU6A5qEdmajGwvae/zDkOq+ULLC9tQBTwqqiwFGpI=
github.com/aws/aws-sdk-go-v2 v1.25.1/go.mod h1:Evoc5AsmtveRt1komDwIsjHFyrP5tDuF1D1U+6z6pNo=
github.com/aws/aws-sdk-go-v2/config v1.1.1 h1:ZAoq32boMzcaTW9bcUacBswAmHTbvlvDJICgHFZuECo=
github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y=
github.com/aws/aws-sdk-go-v2/credentials v1.1.1 h1:NbvWIM1Mx6sNPTxowHgS2ewXCRp+NGTzUYb/96FZJbY=
github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 h1:EtEU7WRaWliitZh2nmuxEXrN0Cb8EgPUFGIoTMeqbzI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28 h1:r+XwaCLpIvCKjBIYy/HVZujQS9tsz5ohHG3ZIe0wKoE=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28/go.mod h1:3lwChorpIM/BhImY/hy+Z6jekmN92cXGPI1QJasVPYY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22 h1:7AwGYXDdqRQYsluvKFmWoqpcOQJ4bH634SkYf3FNj/A=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1 h1:evvi7FbTAoFxdP/mixmP7LIYzQWAmzBcwNB/es9XPNc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1/go.mod h1:rH61DT6FDdikhPghymripNUCsf+uVF4Cnk4c4DBKH64=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22/go.mod h1:EqK7gVrIGAHyZItrD1D8B0ilgwMD1GiWAmbU4u/JHNk=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1 h1:RAnaIrbxPtlXNVI/OIlh1sidTQ3e1qM6LRjs7N0bE0I=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1/go.mod h1:nbgAGkH5lk0RZRMh6A4K/oG6Xj11eC/1CyDow+DUAFI=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.29 h1:J4xhFd6zHhdF9jPP0FQJ6WknzBboGMBNjKOv4iTuw4A=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.29/go.mod h1:TwuqRBGzxjQJIwH16/fOZodwXt2Zxa9/cwJC5ke4j7s=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 h1:4AH9fFjUlVktQMznF+YN33aWNXaR4VgDXyP28qokJC0=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1 h1:cVP8mng1RjDyI3JN/AXFCn5FHNlsBaBH0/MBtG1bg0o=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1/go.mod h1:C8sQjoyAsdfjC7hpy4+S6B92hnFzx0d0UAyHicaOTIE=
github.com/aws/aws-sdk-go-v2/service/sns v1.20.2 h1:MU/v2qtfGjKexJ09BMqE8pXo9xYMhT13FXjKgFc0cFw=
github.com/aws/aws-sdk-go-v2/service/sns v1.20.2/go.mod h1:VN2n9SOMS1lNbh5YD7o+ho0/rgfifSrK//YYNiVVF5E=
github.com/aws/aws-sdk-go-v2/service/sqs v1.20.2 h1:CSNIo1jiw7KrkdgZjCOnotu6yuB3IybhKLuSQrTLNfo=
@ -74,8 +78,9 @@ github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbE
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 h1:TJoIfnIFubCX0ACVeJ0w46HEH5MwjwYN4iFhuYIhfIY=
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM=
github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw=
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@ -135,6 +140,8 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gofiber/adaptor/v2 v2.1.31 h1:E7LJre4uBc+RDsQfHCE+LKVkFcciSMYu4KhzbvoWgKU=
github.com/gofiber/adaptor/v2 v2.1.31/go.mod h1:vdSG9JhOhOLYjE4j14fx6sJvLJNFVf9o6rSyB5GkU4s=
@ -404,8 +411,8 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -439,6 +446,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -478,8 +486,10 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -553,13 +563,18 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -569,13 +584,17 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -620,6 +639,7 @@ golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -111,12 +111,12 @@ func (m *Metric) Push(ctx context.Context, params *Params) error {
err3 = m.volumeMeasurement(ctx, params, transferredToken.Clone())
}
err4 = upsertTransferPrices(
err4 = UpsertTransferPrices(
ctx,
m.logger,
params.Vaa,
m.transferPrices,
func(tokenID string, timestamp time.Time) (decimal.Decimal, error) {
func(tokenID, _ string, timestamp time.Time) (decimal.Decimal, error) {
priceData, err := m.notionalCache.Get(tokenID)
if err != nil {

View File

@ -39,12 +39,12 @@ type TransferPriceDoc struct {
UpdatedAt time.Time `bson:"updatedAt"`
}
func upsertTransferPrices(
func UpsertTransferPrices(
ctx context.Context,
logger *zap.Logger,
vaa *sdk.VAA,
transferPrices *mongo.Collection,
tokenPriceFunc func(tokenID string, timestamp time.Time) (decimal.Decimal, error),
tokenPriceFunc func(tokenID, coinGeckoID string, timestamp time.Time) (decimal.Decimal, error),
transferredToken *token.TransferredToken,
tokenProvider *domain.TokenProvider,
) error {
@ -68,13 +68,14 @@ func upsertTransferPrices(
}
// Try to obtain the token notional value from the cache
notionalUSD, err := tokenPriceFunc(tokenMeta.GetTokenID(), vaa.Timestamp)
notionalUSD, err := tokenPriceFunc(tokenMeta.GetTokenID(), tokenMeta.CoingeckoID, vaa.Timestamp)
if err != nil {
logger.Warn("failed to obtain notional for this token",
zap.String("vaaId", vaa.MessageID()),
zap.String("tokenAddress", transferredToken.TokenAddress.String()),
zap.Uint16("tokenChain", uint16(transferredToken.TokenChain)),
zap.Any("tokenMetadata", tokenMeta),
zap.String("timestamp", vaa.Timestamp.Format(time.RFC3339)),
zap.Error(err),
)
return nil

34
common/client/s3/s3.go Normal file
View File

@ -0,0 +1,34 @@
package s3
import (
"bytes"
"context"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
type S3Repository struct {
uploader *manager.Uploader
bucket string
}
func NewS3Repository(awsConfig aws.Config, bucket string) *S3Repository {
client := s3.NewFromConfig(awsConfig)
return &S3Repository{
uploader: manager.NewUploader(client),
bucket: bucket,
}
}
func (r *S3Repository) Save(ctx context.Context, key string, body []byte) error {
_, err := r.uploader.Upload(ctx,
&s3.PutObjectInput{
Bucket: &r.bucket,
Key: &key,
Body: bytes.NewReader(body),
})
return err
}

View File

@ -4,12 +4,15 @@ go 1.19
require (
github.com/algorand/go-algorand-sdk v1.23.0
github.com/aws/aws-sdk-go-v2 v1.17.4
github.com/aws/aws-sdk-go-v2 v1.25.1
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.4
github.com/aws/aws-sdk-go-v2/service/s3 v1.50.3
github.com/aws/aws-sdk-go-v2/service/sns v1.20.2
github.com/aws/aws-sdk-go-v2/service/sqs v1.20.2
github.com/cosmos/btcutil v1.0.5
github.com/gagliardetto/solana-go v1.8.4
github.com/go-redis/redis/v8 v8.11.5
github.com/go-resty/resty/v2 v2.11.0
github.com/gofiber/fiber/v2 v2.47.0
github.com/influxdata/influxdb-client-go/v2 v2.12.2
github.com/joho/godotenv v1.5.1
@ -30,9 +33,15 @@ require (
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
github.com/algorand/go-codec/codec v1.1.8 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22 // indirect
github.com/aws/smithy-go v1.13.5 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1 // indirect
github.com/aws/smithy-go v1.20.1 // indirect
github.com/blendle/zapdriver v1.3.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
@ -52,6 +61,7 @@ require (
github.com/hashicorp/go-retryablehttp v0.5.1 // indirect
github.com/holiman/uint256 v1.2.1 // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.16.3 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
@ -86,11 +96,11 @@ require (
go.opencensus.io v0.22.5 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/term v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@ -51,18 +51,45 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v1.17.4 h1:wyC6p9Yfq6V2y98wfDsj6OnNQa4w2BLGCLIxzNhwOGY=
github.com/aws/aws-sdk-go-v2 v1.17.4/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28 h1:r+XwaCLpIvCKjBIYy/HVZujQS9tsz5ohHG3ZIe0wKoE=
github.com/aws/aws-sdk-go-v2 v1.25.1 h1:P7hU6A5qEdmajGwvae/zDkOq+ULLC9tQBTwqqiwFGpI=
github.com/aws/aws-sdk-go-v2 v1.25.1/go.mod h1:Evoc5AsmtveRt1komDwIsjHFyrP5tDuF1D1U+6z6pNo=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo=
github.com/aws/aws-sdk-go-v2/config v1.27.2 h1:XnMKB9JRjfnxg9ZkUic4MiapnWJISWRo8HVM+7nx9qQ=
github.com/aws/aws-sdk-go-v2/credentials v1.17.2 h1:tCZXWtH0HiIEZ50NJ7/QEaXmuzEd36L+2JUiZkp2nsc=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.1 h1:lk1ZZFbdb24qpOwVC1AwYNrswUjAxeyey6kFBVANudQ=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.4 h1:yuhSpqtahkrC8kRCU5v4gEaTDy/ccTIPIkufIRF7YTk=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.4/go.mod h1:q3SxgP2WD9YRLCybtyse8EgO3vKKWVmxlTmBNeRXPyk=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28/go.mod h1:3lwChorpIM/BhImY/hy+Z6jekmN92cXGPI1QJasVPYY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22 h1:7AwGYXDdqRQYsluvKFmWoqpcOQJ4bH634SkYf3FNj/A=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1 h1:evvi7FbTAoFxdP/mixmP7LIYzQWAmzBcwNB/es9XPNc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1/go.mod h1:rH61DT6FDdikhPghymripNUCsf+uVF4Cnk4c4DBKH64=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22/go.mod h1:EqK7gVrIGAHyZItrD1D8B0ilgwMD1GiWAmbU4u/JHNk=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1 h1:RAnaIrbxPtlXNVI/OIlh1sidTQ3e1qM6LRjs7N0bE0I=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1/go.mod h1:nbgAGkH5lk0RZRMh6A4K/oG6Xj11eC/1CyDow+DUAFI=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1 h1:rtYJd3w6IWCTVS8vmMaiXjW198noh2PBm5CiXyJea9o=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1/go.mod h1:zvXu+CTlib30LUy4LTNFc6HTZ/K6zCae5YIHTdX9wIo=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1 h1:5Wxh862HkXL9CbQ83BIkWKLIgQapGeuh5zG2G9OZtQk=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1/go.mod h1:V7GLA01pNUxMCYSQsibdVrqUrNIYIT/9lCOyR8ExNvQ=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1 h1:cVP8mng1RjDyI3JN/AXFCn5FHNlsBaBH0/MBtG1bg0o=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1/go.mod h1:C8sQjoyAsdfjC7hpy4+S6B92hnFzx0d0UAyHicaOTIE=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1 h1:OYmmIcyw19f7x0qLBLQ3XsrCZSSyLhxd9GXng5evsN4=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1/go.mod h1:s5rqdn74Vdg10k61Pwf4ZHEApOSD6CKRe6qpeHDq32I=
github.com/aws/aws-sdk-go-v2/service/s3 v1.50.3 h1:Cv/HH7sLzEdJMYQi4MCNHxZeyubQNOOIdVc0VU0lo3Q=
github.com/aws/aws-sdk-go-v2/service/s3 v1.50.3/go.mod h1:lTW7O4iMAnO2o7H3XJTvqaWFZCH6zIPs+eP7RdG/yp0=
github.com/aws/aws-sdk-go-v2/service/sns v1.20.2 h1:MU/v2qtfGjKexJ09BMqE8pXo9xYMhT13FXjKgFc0cFw=
github.com/aws/aws-sdk-go-v2/service/sns v1.20.2/go.mod h1:VN2n9SOMS1lNbh5YD7o+ho0/rgfifSrK//YYNiVVF5E=
github.com/aws/aws-sdk-go-v2/service/sqs v1.20.2 h1:CSNIo1jiw7KrkdgZjCOnotu6yuB3IybhKLuSQrTLNfo=
github.com/aws/aws-sdk-go-v2/service/sqs v1.20.2/go.mod h1:1ttxGjUHZliCQMpPss1sU5+Ph/5NvdMFRzr96bv8gm0=
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
github.com/aws/aws-sdk-go-v2/service/sso v1.19.2 h1:pnj8llQoBAHD4UmbM8UM5GdfycFJKMhgPSeaOyRaZ34=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.22.2 h1:L4yhKxW6HbTSQ08OsvPJuaspaLE40qMgprgXUNFUiMg=
github.com/aws/aws-sdk-go-v2/service/sts v1.27.2 h1:Dr+7r/p20XpN+1U5tVNZfA2bLq0kQ9IjVBM0iAyMMLg=
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@ -140,6 +167,8 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gofiber/fiber/v2 v2.47.0 h1:EN5lHVCc+Pyqh5OEsk8fzRiifgwpbrP0rulQ4iNf3fs=
github.com/gofiber/fiber/v2 v2.47.0/go.mod h1:mbFMVN1lQuzziTkkakgtKKdjfsXSw9BKR5lmcNksUoU=
@ -235,7 +264,9 @@ github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsD
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
@ -477,8 +508,8 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -513,6 +544,7 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -547,8 +579,10 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -612,16 +646,20 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -631,13 +669,17 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -680,6 +722,7 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

53
common/prices/api.go Normal file
View File

@ -0,0 +1,53 @@
package prices
import (
"context"
"fmt"
"time"
"github.com/go-resty/resty/v2"
"github.com/shopspring/decimal"
"go.uber.org/zap"
)
type getPriceResponse struct {
CoingeckoID string `json:"coingeckoId"`
Symbol string `json:"symbol"`
Price string `json:"price"`
DateTime string `json:"dateTime"`
}
type PricesApi struct {
client *resty.Client
log *zap.Logger
}
func NewPricesApi(url string, log *zap.Logger) *PricesApi {
return &PricesApi{
client: resty.New().SetBaseURL(url),
log: log,
}
}
func (n *PricesApi) GetPriceByTime(ctx context.Context, coingeckoID string, dateTime time.Time) (decimal.Decimal, error) {
url := fmt.Sprintf("/api/coingecko/prices/%s/%s", coingeckoID, dateTime.Format(time.RFC3339))
resp, err := n.client.R().
SetContext(ctx).
SetResult(&getPriceResponse{}).
Get(url)
if err != nil {
return decimal.Zero, err
}
if resp.IsError() {
return decimal.Zero, fmt.Errorf("status code: %s. %s", resp.Status(), string(resp.Body()))
}
result := resp.Result().(*getPriceResponse)
if result == nil {
return decimal.Zero, fmt.Errorf("empty response")
}
return decimal.NewFromString(result.Price)
}

View File

@ -1,3 +1,7 @@
package repository
const VaaIdTxHash = "vaaIdTxHash"
const (
VaaIdTxHash = "vaaIdTxHash"
TransferPrices = "transferPrices"
Vaas = "vaas"
)

View File

@ -4,6 +4,7 @@ import (
"context"
"time"
sdk "github.com/wormhole-foundation/wormhole/sdk/vaa"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
@ -23,11 +24,27 @@ type VaaDoc struct {
Vaa []byte `bson:"vaas" json:"vaa"`
}
// VaaQuery is a query for VAA.
type VaaQuery struct {
StartTime *time.Time
EndTime *time.Time
EmitterChainID *sdk.ChainID
EmitterAddress *string
Sequence *string
}
// Pagination is a pagination for VAA.
type Pagination struct {
Page int64
PageSize int64
SortAsc bool
}
// NewVaaRepository create a new Vaa repository.
func NewVaaRepository(db *mongo.Database, logger *zap.Logger) *VaaRepository {
return &VaaRepository{db: db,
logger: logger.With(zap.String("module", "VaaRepository")),
vaas: db.Collection("vaas"),
vaas: db.Collection(Vaas),
}
}
@ -61,3 +78,45 @@ func (r *VaaRepository) FindPageByTimeRange(ctx context.Context, startTime time.
err = cur.All(ctx, &vaas)
return vaas, err
}
// FindPage finds VAA by query and pagination.
func (r *VaaRepository) FindPage(ctx context.Context, query VaaQuery, pagination Pagination) ([]*VaaDoc, error) {
filter := bson.M{}
if query.StartTime != nil || query.EndTime != nil {
rangeTimestamp := bson.M{}
if query.StartTime != nil {
rangeTimestamp["$gte"] = query.StartTime
}
if query.EndTime != nil {
rangeTimestamp["$lt"] = query.EndTime
}
filter["timestamp"] = rangeTimestamp
}
if query.EmitterChainID != nil {
filter["emitterChain"] = query.EmitterChainID
}
if query.EmitterAddress != nil {
filter["emitterAddr"] = query.EmitterAddress
}
if query.Sequence != nil {
filter["sequence"] = query.Sequence
}
sort := -1
if pagination.SortAsc {
sort = 1
}
skip := pagination.Page * pagination.PageSize
opts := &options.FindOptions{Skip: &skip, Limit: &pagination.PageSize, Sort: bson.M{"timestamp": sort}}
cur, err := r.vaas.Find(ctx, filter, opts)
if err != nil {
return nil, err
}
var vaas []*VaaDoc
err = cur.All(ctx, &vaas)
return vaas, err
}

View File

@ -0,0 +1,9 @@
---
kind: ConfigMap
apiVersion: v1
metadata:
name: jobs
namespace: {{ .NAMESPACE }}
data:
aws-region: {{ .AWS_REGION }}
aws-bucket: {{ .AWS_BUCKET }}

View File

@ -27,3 +27,6 @@ PROTOCOLS_STATS_CRONTAB_SCHEDULE='0 * * * *'
#protocols activity job:every hour
PROTOCOLS_ACTIVITY_CRONTAB_SCHEDULE='0 * * * *'
PROTOCOLS_JSON=
AWS_IAM_ROLE=
AWS_REGION=
AWS_BUCKET=

View File

@ -27,3 +27,6 @@ PROTOCOLS_STATS_CRONTAB_SCHEDULE='0 * * * *'
#protocols activity job:every hour
PROTOCOLS_ACTIVITY_CRONTAB_SCHEDULE='0 * * * *'
PROTOCOLS_JSON=
AWS_IAM_ROLE=
AWS_REGION=
AWS_BUCKET=

View File

@ -27,3 +27,6 @@ PROTOCOLS_STATS_CRONTAB_SCHEDULE=0 * * * *
#protocols activity job:every hour
PROTOCOLS_ACTIVITY_CRONTAB_SCHEDULE=0 * * * *
PROTOCOLS_JSON=
AWS_IAM_ROLE=
AWS_REGION=
AWS_BUCKET=

View File

@ -27,3 +27,6 @@ PROTOCOLS_STATS_CRONTAB_SCHEDULE='0 * * * *'
#protocols activity job:every hour
PROTOCOLS_ACTIVITY_CRONTAB_SCHEDULE='0 * * * *'
PROTOCOLS_JSON=
AWS_IAM_ROLE=
AWS_REGION=
AWS_BUCKET=

View File

@ -9,6 +9,7 @@ spec:
spec:
template:
spec:
serviceAccountName: jobs
containers:
- name: {{ .NAME }}
image: {{ .IMAGE_NAME }}
@ -35,5 +36,15 @@ spec:
valueFrom:
configMapKeyRef:
name: config
key: redis-prefix
key: redis-prefix
- name: AWS_REGION
valueFrom:
configMapKeyRef:
name: jobs
key: aws-region
- name: AWS_BUCKET
valueFrom:
configMapKeyRef:
name: jobs
key: aws-bucket
restartPolicy: OnFailure

7
deploy/jobs/sa.yaml Normal file
View File

@ -0,0 +1,7 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: jobs
namespace: {{ .NAMESPACE }}
annotations:
eks.amazonaws.com/role-arn: {{ .AWS_IAM_ROLE }}

View File

@ -1,82 +0,0 @@
ENVIRONMENT=production
NAMESPACE=wormscan
NAME=wormscan-tx-tracker-backfiller
IMAGE_NAME=
RESOURCES_LIMITS_MEMORY=128Mi
RESOURCES_LIMITS_CPU=500m
RESOURCES_REQUESTS_MEMORY=64Mi
RESOURCES_REQUESTS_CPU=100m
NUM_WORKERS=50
BULK_SIZE=1000
STRATEGY_NAME=time_range
STRATEGY_TIMESTAMP_AFTER=2023-01-01T00:00:00.000Z
STRATEGY_TIMESTAMP_BEFORE=2024-01-01T00:00:00.000Z
ACALA_BASE_URL=https://eth-rpc-acala.aca-api.network
ACALA_REQUESTS_PER_MINUTE=1
ALGORAND_BASE_URL=https://mainnet-idx.algonode.cloud
ALGORAND_REQUESTS_PER_MINUTE=1
APTOS_BASE_URL=https://fullnode.mainnet.aptoslabs.com/v1
APTOS_REQUESTS_PER_MINUTE=2
ARBITRUM_BASE_URL=https://rpc.ankr.com/arbitrum
ARBITRUM_REQUESTS_PER_MINUTE=1
AVALANCHE_BASE_URL=https://api.avax.network/ext/bc/C/rpc
AVALANCHE_REQUESTS_PER_MINUTE=2
BASE_BASE_URL=https://base-mainnet.public.blastapi.io
BASE_REQUESTS_PER_MINUTE=1
BSC_BASE_URL=https://bsc-dataseed2.defibit.io
BSC_REQUESTS_PER_MINUTE=2
CELO_BASE_URL=https://forno.celo.org
CELO_REQUESTS_PER_MINUTE=1
ETHEREUM_BASE_URL=https://rpc.ankr.com/eth
ETHEREUM_REQUESTS_PER_MINUTE=2
FANTOM_BASE_URL=https://rpc.ankr.com/fantom
FANTOM_REQUESTS_PER_MINUTE=2
# Currently, the main URL for injective RPC (https://k8s.mainnet.lcd.injective.network) is down.
# We're temporally using a different one.
INJECTIVE_BASE_URL=http://sentry2.injective.network:10337/
INJECTIVE_REQUESTS_PER_MINUTE=1
KARURA_BASE_URL=https://eth-rpc-karura.aca-api.network
KARURA_REQUESTS_PER_MINUTE=1
KLAYTN_BASE_URL=https://klaytn-mainnet-rpc.allthatnode.com:8551
KLAYTN_REQUESTS_PER_MINUTE=1
MOONBEAM_BASE_URL=https://rpc.api.moonbeam.network
MOONBEAM_REQUESTS_PER_MINUTE=1
OASIS_BASE_URL=https://emerald.oasis.dev
OASIS_REQUESTS_PER_MINUTE=1
OPTIMISM_BASE_URL=https://rpc.ankr.com/optimism
OPTIMISM_REQUESTS_PER_MINUTE=1
POLYGON_BASE_URL=https://rpc.ankr.com/polygon
POLYGON_REQUESTS_PER_MINUTE=2
SOLANA_BASE_URL=https://api.mainnet-beta.solana.com
SOLANA_REQUESTS_PER_MINUTE=4
SUI_BASE_URL=https://fullnode.mainnet.sui.io:443
SUI_REQUESTS_PER_MINUTE=1
TERRA_BASE_URL=https://columbus-fcd.terra.dev
TERRA_REQUESTS_PER_MINUTE=4
TERRA2_BASE_URL=https://phoenix-lcd.terra.dev
TERRA2_REQUESTS_PER_MINUTE=1
XPLA_BASE_URL=https://dimension-lcd.xpla.dev
XPLA_REQUESTS_PER_MINUTE=1

View File

@ -1,82 +0,0 @@
ENVIRONMENT=staging
NAMESPACE=wormscan
NAME=wormscan-tx-tracker-backfiller
IMAGE_NAME=
RESOURCES_LIMITS_MEMORY=128Mi
RESOURCES_LIMITS_CPU=500m
RESOURCES_REQUESTS_MEMORY=64Mi
RESOURCES_REQUESTS_CPU=100m
NUM_WORKERS=50
BULK_SIZE=1000
STRATEGY_NAME=time_range
STRATEGY_TIMESTAMP_AFTER=2023-01-01T00:00:00.000Z
STRATEGY_TIMESTAMP_BEFORE=2024-01-01T00:00:00.000Z
ACALA_BASE_URL=https://eth-rpc-acala.aca-api.network
ACALA_REQUESTS_PER_MINUTE=1
ALGORAND_BASE_URL=https://mainnet-idx.algonode.cloud
ALGORAND_REQUESTS_PER_MINUTE=1
APTOS_BASE_URL=https://fullnode.mainnet.aptoslabs.com/v1
APTOS_REQUESTS_PER_MINUTE=1
ARBITRUM_BASE_URL=https://rpc.ankr.com/arbitrum
ARBITRUM_REQUESTS_PER_MINUTE=1
AVALANCHE_BASE_URL=https://api.avax.network/ext/bc/C/rpc
AVALANCHE_REQUESTS_PER_MINUTE=1
BASE_BASE_URL=https://base-mainnet.public.blastapi.io
BASE_REQUESTS_PER_MINUTE=1
BSC_BASE_URL=https://bsc-dataseed2.defibit.io
BSC_REQUESTS_PER_MINUTE=1
CELO_BASE_URL=https://forno.celo.org
CELO_REQUESTS_PER_MINUTE=1
ETHEREUM_BASE_URL=https://rpc.ankr.com/eth
ETHEREUM_REQUESTS_PER_MINUTE=1
FANTOM_BASE_URL=https://rpc.ankr.com/fantom
FANTOM_REQUESTS_PER_MINUTE=1
# Currently, the main URL for injective RPC (https://k8s.mainnet.lcd.injective.network) is down.
# We're temporally using a different one.
INJECTIVE_BASE_URL=http://sentry2.injective.network:10337/
INJECTIVE_REQUESTS_PER_MINUTE=1
KARURA_BASE_URL=https://eth-rpc-karura.aca-api.network
KARURA_REQUESTS_PER_MINUTE=1
KLAYTN_BASE_URL=https://klaytn-mainnet-rpc.allthatnode.com:8551
KLAYTN_REQUESTS_PER_MINUTE=1
MOONBEAM_BASE_URL=https://rpc.api.moonbeam.network
MOONBEAM_REQUESTS_PER_MINUTE=1
OASIS_BASE_URL=https://emerald.oasis.dev
OASIS_REQUESTS_PER_MINUTE=1
OPTIMISM_BASE_URL=https://rpc.ankr.com/optimism
OPTIMISM_REQUESTS_PER_MINUTE=1
POLYGON_BASE_URL=https://rpc.ankr.com/polygon
POLYGON_REQUESTS_PER_MINUTE=1
SOLANA_BASE_URL=https://api.mainnet-beta.solana.com
SOLANA_REQUESTS_PER_MINUTE=2
SUI_BASE_URL=https://fullnode.mainnet.sui.io:443
SUI_REQUESTS_PER_MINUTE=1
TERRA_BASE_URL=https://columbus-fcd.terra.dev
TERRA_REQUESTS_PER_MINUTE=2
TERRA2_BASE_URL=https://phoenix-lcd.terra.dev
TERRA2_REQUESTS_PER_MINUTE=1
XPLA_BASE_URL=https://dimension-lcd.xpla.dev
XPLA_REQUESTS_PER_MINUTE=1

View File

@ -1,80 +0,0 @@
ENVIRONMENT=test
NAMESPACE=wormscan-testnet
NAME=wormscan-tx-tracker-backfiller
IMAGE_NAME=
RESOURCES_LIMITS_MEMORY=128Mi
RESOURCES_LIMITS_CPU=500m
RESOURCES_REQUESTS_MEMORY=64Mi
RESOURCES_REQUESTS_CPU=100m
NUM_WORKERS=50
BULK_SIZE=1000
STRATEGY_NAME=time_range
STRATEGY_TIMESTAMP_AFTER=2023-01-01T00:00:00.000Z
STRATEGY_TIMESTAMP_BEFORE=2024-01-01T00:00:00.000Z
ACALA_BASE_URL=https://acala-dev.aca-dev.network/eth/http
ACALA_REQUESTS_PER_MINUTE=2
ALGORAND_BASE_URL=https://testnet-idx.algonode.cloud
ALGORAND_REQUESTS_PER_MINUTE=2
APTOS_BASE_URL=https://fullnode.testnet.aptoslabs.com/v1
APTOS_REQUESTS_PER_MINUTE=2
ARBITRUM_BASE_URL=https://goerli-rollup.arbitrum.io/rpc
ARBITRUM_REQUESTS_PER_MINUTE=2
AVALANCHE_BASE_URL=https://rpc.ankr.com/avalanche_fuji
AVALANCHE_REQUESTS_PER_MINUTE=2
BASE_BASE_URL=https://base-goerli.public.blastapi.io
BASE_REQUESTS_PER_MINUTE=1
BSC_BASE_URL=https://data-seed-prebsc-1-s1.binance.org:8545
BSC_REQUESTS_PER_MINUTE=2
CELO_BASE_URL=https://alfajores-forno.celo-testnet.org
CELO_REQUESTS_PER_MINUTE=2
ETHEREUM_BASE_URL=https://rpc.ankr.com/eth_goerli
ETHEREUM_REQUESTS_PER_MINUTE=2
FANTOM_BASE_URL=https://rpc.testnet.fantom.network
FANTOM_REQUESTS_PER_MINUTE=2
INJECTIVE_BASE_URL=https://k8s.testnet.tm.injective.network:443
INJECTIVE_REQUESTS_PER_MINUTE=2
KARURA_BASE_URL=https://karura-dev.aca-dev.network/eth/http
KARURA_REQUESTS_PER_MINUTE=2
KLAYTN_BASE_URL=https://api.baobab.klaytn.net:8651
KLAYTN_REQUESTS_PER_MINUTE=2
MOONBEAM_BASE_URL=https://rpc.api.moonbase.moonbeam.network
MOONBEAM_REQUESTS_PER_MINUTE=2
OASIS_BASE_URL=https://testnet.emerald.oasis.dev
OASIS_REQUESTS_PER_MINUTE=2
OPTIMISM_BASE_URL=https://goerli.optimism.io
OPTIMISM_REQUESTS_PER_MINUTE=2
POLYGON_BASE_URL=https://rpc.ankr.com/polygon_mumbai
POLYGON_REQUESTS_PER_MINUTE=2
SOLANA_BASE_URL=https://api.devnet.solana.com
SOLANA_REQUESTS_PER_MINUTE=2
SUI_BASE_URL=https://fullnode.testnet.sui.io:443
SUI_REQUESTS_PER_MINUTE=2
TERRA_BASE_URL=https://bombay-lcd.terra.dev
TERRA_REQUESTS_PER_MINUTE=2
TERRA2_BASE_URL=https://pisco-lcd.terra.dev
TERRA2_REQUESTS_PER_MINUTE=2
XPLA_BASE_URL=https://cube-lcd.xpla.dev:443
XPLA_REQUESTS_PER_MINUTE=2

View File

@ -1,138 +0,0 @@
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .NAME }}
namespace: {{ .NAMESPACE }}
spec:
template:
metadata:
labels:
app: {{ .NAME }}
spec:
restartPolicy: Never
terminationGracePeriodSeconds: 40
containers:
- name: {{ .NAME }}
image: {{ .IMAGE_NAME }}
imagePullPolicy: Always
env:
- name: ENV
value: "PRODUCTION"
- name: LOG_LEVEL
value: "DEBUG"
- name: MONGODB_URI
valueFrom:
secretKeyRef:
name: mongodb
key: mongo-uri
- name: MONGODB_DATABASE
valueFrom:
configMapKeyRef:
name: config
key: mongo-database
- name: ACALA_BASE_URL
value: {{ .ACALA_BASE_URL }}
- name: ACALA_REQUESTS_PER_MINUTE
value: "{{ .ACALA_REQUESTS_PER_MINUTE }}"
- name: ALGORAND_BASE_URL
value: {{ .ALGORAND_BASE_URL }}
- name: ALGORAND_REQUESTS_PER_MINUTE
value: "{{ .ALGORAND_REQUESTS_PER_MINUTE }}"
- name: APTOS_BASE_URL
value: {{ .APTOS_BASE_URL }}
- name: APTOS_REQUESTS_PER_MINUTE
value: "{{ .APTOS_REQUESTS_PER_MINUTE }}"
- name: ARBITRUM_BASE_URL
value: {{ .ARBITRUM_BASE_URL }}
- name: ARBITRUM_REQUESTS_PER_MINUTE
value: "{{ .ARBITRUM_REQUESTS_PER_MINUTE }}"
- name: AVALANCHE_BASE_URL
value: {{ .AVALANCHE_BASE_URL }}
- name: AVALANCHE_REQUESTS_PER_MINUTE
value: "{{ .AVALANCHE_REQUESTS_PER_MINUTE }}"
- name: BASE_BASE_URL
value: {{ .BASE_BASE_URL }}
- name: BASE_REQUESTS_PER_MINUTE
value: "{{ .BASE_REQUESTS_PER_MINUTE }}"
- name: BSC_BASE_URL
value: {{ .BSC_BASE_URL }}
- name: BSC_REQUESTS_PER_MINUTE
value: "{{ .BSC_REQUESTS_PER_MINUTE }}"
- name: CELO_BASE_URL
value: {{ .CELO_BASE_URL }}
- name: CELO_REQUESTS_PER_MINUTE
value: "{{ .CELO_REQUESTS_PER_MINUTE }}"
- name: ETHEREUM_BASE_URL
value: {{ .ETHEREUM_BASE_URL }}
- name: ETHEREUM_REQUESTS_PER_MINUTE
value: "{{ .ETHEREUM_REQUESTS_PER_MINUTE }}"
- name: FANTOM_BASE_URL
value: {{ .FANTOM_BASE_URL }}
- name: FANTOM_REQUESTS_PER_MINUTE
value: "{{ .FANTOM_REQUESTS_PER_MINUTE }}"
- name: INJECTIVE_BASE_URL
value: {{ .INJECTIVE_BASE_URL }}
- name: INJECTIVE_REQUESTS_PER_MINUTE
value: "{{ .INJECTIVE_REQUESTS_PER_MINUTE }}"
- name: KARURA_BASE_URL
value: {{ .KARURA_BASE_URL }}
- name: KARURA_REQUESTS_PER_MINUTE
value: "{{ .KARURA_REQUESTS_PER_MINUTE }}"
- name: KLAYTN_BASE_URL
value: {{ .KLAYTN_BASE_URL }}
- name: KLAYTN_REQUESTS_PER_MINUTE
value: "{{ .KLAYTN_REQUESTS_PER_MINUTE }}"
- name: MOONBEAM_BASE_URL
value: {{ .MOONBEAM_BASE_URL }}
- name: MOONBEAM_REQUESTS_PER_MINUTE
value: "{{ .MOONBEAM_REQUESTS_PER_MINUTE }}"
- name: OASIS_BASE_URL
value: {{ .OASIS_BASE_URL }}
- name: OASIS_REQUESTS_PER_MINUTE
value: "{{ .OASIS_REQUESTS_PER_MINUTE }}"
- name: OPTIMISM_BASE_URL
value: {{ .OPTIMISM_BASE_URL }}
- name: OPTIMISM_REQUESTS_PER_MINUTE
value: "{{ .OPTIMISM_REQUESTS_PER_MINUTE }}"
- name: POLYGON_BASE_URL
value: {{ .POLYGON_BASE_URL }}
- name: POLYGON_REQUESTS_PER_MINUTE
value: "{{ .POLYGON_REQUESTS_PER_MINUTE }}"
- name: SOLANA_BASE_URL
value: {{ .SOLANA_BASE_URL }}
- name: SOLANA_REQUESTS_PER_MINUTE
value: "{{ .SOLANA_REQUESTS_PER_MINUTE }}"
- name: SUI_BASE_URL
value: {{ .SUI_BASE_URL }}
- name: SUI_REQUESTS_PER_MINUTE
value: "{{ .SUI_REQUESTS_PER_MINUTE }}"
- name: TERRA_BASE_URL
value: {{ .TERRA_BASE_URL }}
- name: TERRA_REQUESTS_PER_MINUTE
value: "{{ .TERRA_REQUESTS_PER_MINUTE }}"
- name: TERRA2_BASE_URL
value: {{ .TERRA2_BASE_URL }}
- name: TERRA2_REQUESTS_PER_MINUTE
value: "{{ .TERRA2_REQUESTS_PER_MINUTE }}"
- name: XPLA_BASE_URL
value: {{ .XPLA_BASE_URL }}
- name: XPLA_REQUESTS_PER_MINUTE
value: "{{ .XPLA_REQUESTS_PER_MINUTE }}"
- name: NUM_WORKERS
value: "100"
- name: BULK_SIZE
value: "1000"
- name: STRATEGY_NAME
value: "{{ .STRATEGY_NAME }}"
- name: STRATEGY_TIMESTAMP_AFTER
value: "{{ .STRATEGY_TIMESTAMP_AFTER }}"
- name: STRATEGY_TIMESTAMP_BEFORE
value: "{{ .STRATEGY_TIMESTAMP_BEFORE }}"
resources:
limits:
memory: {{ .RESOURCES_LIMITS_MEMORY }}
cpu: {{ .RESOURCES_LIMITS_CPU }}
requests:
memory: {{ .RESOURCES_REQUESTS_MEMORY }}
cpu: {{ .RESOURCES_REQUESTS_CPU }}

View File

@ -3,17 +3,20 @@ package main
import (
"context"
"encoding/json"
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
"github.com/wormhole-foundation/wormhole-explorer/common/configuration"
"github.com/wormhole-foundation/wormhole-explorer/jobs/jobs/protocols/activity"
"github.com/wormhole-foundation/wormhole-explorer/jobs/jobs/protocols/stats"
"log"
"net/http"
"os"
"strings"
"time"
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
"github.com/wormhole-foundation/wormhole-explorer/common/configuration"
"github.com/wormhole-foundation/wormhole-explorer/jobs/jobs/protocols/activity"
"github.com/wormhole-foundation/wormhole-explorer/jobs/jobs/protocols/stats"
awsconfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/go-redis/redis"
"github.com/wormhole-foundation/wormhole-explorer/common/client/s3"
txtrackerProcessVaa "github.com/wormhole-foundation/wormhole-explorer/common/client/txtracker"
common "github.com/wormhole-foundation/wormhole-explorer/common/coingecko"
"github.com/wormhole-foundation/wormhole-explorer/common/dbutil"
@ -38,7 +41,7 @@ func main() {
ctx := context.Background()
// get the config
cfg, errConf := config.New(ctx)
cfg, errConf := configuration.LoadFromEnv[config.Configuration](ctx)
if errConf != nil {
log.Fatal("error creating config", errConf)
}
@ -49,7 +52,7 @@ func main() {
var err error
switch cfg.JobID {
case jobs.JobIDNotional:
nCfg, errCfg := config.NewNotionalConfiguration(ctx)
nCfg, errCfg := configuration.LoadFromEnv[config.NotionalConfiguration](ctx)
if errCfg != nil {
log.Fatal("error creating config", errCfg)
}
@ -57,7 +60,7 @@ func main() {
err = notionalJob.Run()
case jobs.JobIDTransferReport:
aCfg, errCfg := config.NewTransferReportConfiguration(ctx)
aCfg, errCfg := configuration.LoadFromEnv[config.TransferReportConfiguration](ctx)
if errCfg != nil {
log.Fatal("error creating config", errCfg)
}
@ -65,7 +68,7 @@ func main() {
err = transferReport.Run(ctx)
case jobs.JobIDHistoricalPrices:
hCfg, errCfg := config.NewHistoricalPricesConfiguration(ctx)
hCfg, errCfg := configuration.LoadFromEnv[config.HistoricalPricesConfiguration](ctx)
if errCfg != nil {
log.Fatal("error creating config", errCfg)
}
@ -73,7 +76,7 @@ func main() {
err = historyPrices.Run(ctx)
case jobs.JobIDMigrationSourceTx:
mCfg, errCfg := config.NewMigrateSourceTxConfiguration(ctx)
mCfg, errCfg := configuration.LoadFromEnv[config.MigrateSourceTxConfiguration](ctx)
if errCfg != nil {
log.Fatal("error creating config", errCfg)
}
@ -108,8 +111,18 @@ func initNotionalJob(ctx context.Context, cfg *config.NotionalConfiguration, log
redisClient := redis.NewClient(&redis.Options{Addr: cfg.CacheURL})
// init token provider.
tokenProvider := domain.NewTokenProvider(cfg.P2pNetwork)
notify := notional.NoopNotifier()
if cfg.AwsRegion != "" && cfg.AwsBucket != "" {
awsConfig, err := awsconfig.LoadDefaultConfig(ctx, awsconfig.WithRegion(cfg.AwsRegion))
if err != nil {
logger.Fatal("Failed to load AWS config", zap.Error(err))
}
// init s3 client.
s3Client := s3.NewS3Repository(awsConfig, cfg.AwsBucket)
notify = notional.S3Notifier(s3Client)
}
// create notional job.
notionalJob := notional.NewNotionalJob(api, redisClient, cfg.CachePrefix, cfg.NotionalChannel, tokenProvider, logger)
notionalJob := notional.NewNotionalJob(api, redisClient, cfg.CachePrefix, cfg.NotionalChannel, tokenProvider, notify, logger)
return notionalJob
}

View File

@ -2,13 +2,6 @@
// It define a type [Configuration] that represent the aplication configuration
package config
import (
"context"
"github.com/joho/godotenv"
"github.com/sethvargo/go-envconfig"
)
// Configuration is the configuration for the job
type Configuration struct {
JobID string `env:"JOB_ID,required"`
@ -22,6 +15,8 @@ type NotionalConfiguration struct {
CachePrefix string `env:"CACHE_PREFIX,required"`
NotionalChannel string `env:"NOTIONAL_CHANNEL,required"`
P2pNetwork string `env:"P2P_NETWORK,required"`
AwsRegion string `env:"AWS_REGION"`
AwsBucket string `env:"AWS_BUCKET"`
}
type TransferReportConfiguration struct {
@ -76,61 +71,3 @@ type Protocol struct {
type ProtocolsActivityConfiguration struct {
ProtocolsStatsConfiguration
}
// New creates a default configuration with the values from .env file and environment variables.
func New(ctx context.Context) (*Configuration, error) {
_ = godotenv.Load(".env", "../.env")
var configuration Configuration
if err := envconfig.Process(ctx, &configuration); err != nil {
return nil, err
}
return &configuration, nil
}
// New creates a notional configuration with the values from .env file and environment variables.
func NewNotionalConfiguration(ctx context.Context) (*NotionalConfiguration, error) {
_ = godotenv.Load(".env", "../.env")
var configuration NotionalConfiguration
if err := envconfig.Process(ctx, &configuration); err != nil {
return nil, err
}
return &configuration, nil
}
// New creates a transfer report configuration with the values from .env file and environment variables.
func NewTransferReportConfiguration(ctx context.Context) (*TransferReportConfiguration, error) {
_ = godotenv.Load(".env", "../.env")
var configuration TransferReportConfiguration
if err := envconfig.Process(ctx, &configuration); err != nil {
return nil, err
}
return &configuration, nil
}
// New creates a history prices configuration with the values from .env file and environment variables.
func NewHistoricalPricesConfiguration(ctx context.Context) (*HistoricalPricesConfiguration, error) {
_ = godotenv.Load(".env", "../.env")
var configuration HistoricalPricesConfiguration
if err := envconfig.Process(ctx, &configuration); err != nil {
return nil, err
}
return &configuration, nil
}
// New creates a migration source tx configuration with the values from .env file and environment variables.
func NewMigrateSourceTxConfiguration(ctx context.Context) (*MigrateSourceTxConfiguration, error) {
_ = godotenv.Load(".env", "../.env")
var configuration MigrateSourceTxConfiguration
if err := envconfig.Process(ctx, &configuration); err != nil {
return nil, err
}
return &configuration, nil
}

View File

@ -3,8 +3,9 @@ module github.com/wormhole-foundation/wormhole-explorer/jobs
go 1.19
require (
github.com/aws/aws-sdk-go-v2/config v1.27.2
github.com/go-redis/redis v6.15.9+incompatible
github.com/go-resty/resty/v2 v2.10.0
github.com/go-resty/resty/v2 v2.11.0
github.com/google/uuid v1.3.0
github.com/influxdata/influxdb-client-go/v2 v2.12.2
github.com/joho/godotenv v1.5.1
@ -19,9 +20,31 @@ require (
go.uber.org/zap v1.25.0
)
require (
github.com/aws/aws-sdk-go-v2 v1.25.1 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.2 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.50.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.19.2 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.22.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.27.2 // indirect
github.com/aws/smithy-go v1.20.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
)
require (
github.com/algorand/go-algorand-sdk v1.23.0 // indirect
github.com/algorand/go-codec/codec v1.1.8 // indirect
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.4 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect

View File

@ -3,6 +3,44 @@ github.com/algorand/go-algorand-sdk v1.23.0/go.mod h1:7i2peZBcE48kfoxNZnLA+mklKh
github.com/algorand/go-codec v1.1.8/go.mod h1:XhzVs6VVyWMLu6cApb9/192gBjGRVGm5cX5j203Heg4=
github.com/algorand/go-codec/codec v1.1.8 h1:lsFuhcOH2LiEhpBH3BVUUkdevVmwCRyvb7FCAAPeY6U=
github.com/algorand/go-codec/codec v1.1.8/go.mod h1:tQ3zAJ6ijTps6V+wp8KsGDnPC2uhHVC7ANyrtkIY0bA=
github.com/aws/aws-sdk-go-v2 v1.25.1 h1:P7hU6A5qEdmajGwvae/zDkOq+ULLC9tQBTwqqiwFGpI=
github.com/aws/aws-sdk-go-v2 v1.25.1/go.mod h1:Evoc5AsmtveRt1komDwIsjHFyrP5tDuF1D1U+6z6pNo=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo=
github.com/aws/aws-sdk-go-v2/config v1.27.2 h1:XnMKB9JRjfnxg9ZkUic4MiapnWJISWRo8HVM+7nx9qQ=
github.com/aws/aws-sdk-go-v2/config v1.27.2/go.mod h1:z/XIktFoVIKNEqX/811vx4eHetrC3tAkgJKL1ZY/KM4=
github.com/aws/aws-sdk-go-v2/credentials v1.17.2 h1:tCZXWtH0HiIEZ50NJ7/QEaXmuzEd36L+2JUiZkp2nsc=
github.com/aws/aws-sdk-go-v2/credentials v1.17.2/go.mod h1:7Zo+D6q4auSIo3p4EItuTKTk7J+RqjASISZqLvmUgpc=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.1 h1:lk1ZZFbdb24qpOwVC1AwYNrswUjAxeyey6kFBVANudQ=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.1/go.mod h1:/xJ6x1NehNGCX4tvGzzj2bq5TBOT/Yxq+qbL9Jpx2Vk=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.4 h1:yuhSpqtahkrC8kRCU5v4gEaTDy/ccTIPIkufIRF7YTk=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.4/go.mod h1:q3SxgP2WD9YRLCybtyse8EgO3vKKWVmxlTmBNeRXPyk=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1 h1:evvi7FbTAoFxdP/mixmP7LIYzQWAmzBcwNB/es9XPNc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1/go.mod h1:rH61DT6FDdikhPghymripNUCsf+uVF4Cnk4c4DBKH64=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1 h1:RAnaIrbxPtlXNVI/OIlh1sidTQ3e1qM6LRjs7N0bE0I=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1/go.mod h1:nbgAGkH5lk0RZRMh6A4K/oG6Xj11eC/1CyDow+DUAFI=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1 h1:rtYJd3w6IWCTVS8vmMaiXjW198noh2PBm5CiXyJea9o=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1/go.mod h1:zvXu+CTlib30LUy4LTNFc6HTZ/K6zCae5YIHTdX9wIo=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1 h1:5Wxh862HkXL9CbQ83BIkWKLIgQapGeuh5zG2G9OZtQk=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1/go.mod h1:V7GLA01pNUxMCYSQsibdVrqUrNIYIT/9lCOyR8ExNvQ=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1 h1:cVP8mng1RjDyI3JN/AXFCn5FHNlsBaBH0/MBtG1bg0o=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1/go.mod h1:C8sQjoyAsdfjC7hpy4+S6B92hnFzx0d0UAyHicaOTIE=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1 h1:OYmmIcyw19f7x0qLBLQ3XsrCZSSyLhxd9GXng5evsN4=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1/go.mod h1:s5rqdn74Vdg10k61Pwf4ZHEApOSD6CKRe6qpeHDq32I=
github.com/aws/aws-sdk-go-v2/service/s3 v1.50.3 h1:Cv/HH7sLzEdJMYQi4MCNHxZeyubQNOOIdVc0VU0lo3Q=
github.com/aws/aws-sdk-go-v2/service/s3 v1.50.3/go.mod h1:lTW7O4iMAnO2o7H3XJTvqaWFZCH6zIPs+eP7RdG/yp0=
github.com/aws/aws-sdk-go-v2/service/sso v1.19.2 h1:pnj8llQoBAHD4UmbM8UM5GdfycFJKMhgPSeaOyRaZ34=
github.com/aws/aws-sdk-go-v2/service/sso v1.19.2/go.mod h1:x6/tCd1o/AOKQR+iYnjrzhJxD+w0xRN34asGPaSV7ew=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.22.2 h1:L4yhKxW6HbTSQ08OsvPJuaspaLE40qMgprgXUNFUiMg=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.22.2/go.mod h1:lZB123q0SVQ3dfIbEOcGzhQHrwVBcHVReNS9tm20oU4=
github.com/aws/aws-sdk-go-v2/service/sts v1.27.2 h1:Dr+7r/p20XpN+1U5tVNZfA2bLq0kQ9IjVBM0iAyMMLg=
github.com/aws/aws-sdk-go-v2/service/sts v1.27.2/go.mod h1:ozhhG9/NB5c9jcmhGq6tX9dpp21LYdmRWRQVppASim4=
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=
@ -36,8 +74,8 @@ github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGK
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-resty/resty/v2 v2.10.0 h1:Qla4W/+TMmv0fOeeRqzEpXPLfTUnR5HZ1+lGs+CkiCo=
github.com/go-resty/resty/v2 v2.10.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@ -54,6 +92,10 @@ github.com/influxdata/influxdb-client-go/v2 v2.12.2 h1:uYABKdrEKlYm+++qfKdbgaHKB
github.com/influxdata/influxdb-client-go/v2 v2.12.2/go.mod h1:YteV91FiQxRdccyJ2cHvj2f/5sq4y4Njqu1fQzsQCOU=
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM=
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
@ -223,7 +265,9 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -2,11 +2,15 @@
package notional
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/go-redis/redis"
"github.com/shopspring/decimal"
"github.com/wormhole-foundation/wormhole-explorer/common/client/cache/notional"
"github.com/wormhole-foundation/wormhole-explorer/common/client/s3"
"github.com/wormhole-foundation/wormhole-explorer/common/domain"
"github.com/wormhole-foundation/wormhole-explorer/jobs/internal/coingecko"
"go.uber.org/zap"
@ -19,17 +23,22 @@ type NotionalJob struct {
cachePrefix string
cacheChannel string
tokenProvider *domain.TokenProvider
notify notify
logger *zap.Logger
}
type notify func(context.Context, time.Time, map[string]coingecko.NotionalUSD) error
// NewNotionalJob creates a new notional job.
func NewNotionalJob(api *coingecko.CoingeckoAPI, cacheClient *redis.Client, cachePrefix string, cacheChannel string, tokenProvider *domain.TokenProvider, logger *zap.Logger) *NotionalJob {
func NewNotionalJob(api *coingecko.CoingeckoAPI, cacheClient *redis.Client, cachePrefix string, cacheChannel string,
tokenProvider *domain.TokenProvider, notify notify, logger *zap.Logger) *NotionalJob {
return &NotionalJob{
coingeckoAPI: api,
cacheClient: cacheClient,
cachePrefix: cachePrefix,
cacheChannel: formatChannel(cachePrefix, cacheChannel),
tokenProvider: tokenProvider,
notify: notify,
logger: logger,
}
}
@ -37,12 +46,16 @@ func NewNotionalJob(api *coingecko.CoingeckoAPI, cacheClient *redis.Client, cach
// Run runs the notional job.
func (j *NotionalJob) Run() error {
ctx := context.Background()
// get chains coingecko ids by p2p network.
chainIDs := j.tokenProvider.GetAllCoingeckoIDs()
if len(chainIDs) == 0 {
return fmt.Errorf("no chain ids found for p2p network %s", j.tokenProvider.GetP2pNewtork())
}
now := time.Now()
// get notional value of assets.
coingeckoNotionals, err := j.coingeckoAPI.GetNotionalUSD(chainIDs)
if err != nil {
@ -53,7 +66,7 @@ func (j *NotionalJob) Run() error {
j.logger.Info("found notionals", zap.Int("chainIDs", len(chainIDs)), zap.Int("notionals", len(coingeckoNotionals)))
// convert notionals with coingecko assets ids to notionals with wormhole chainIDs.
notionals := j.convertToSymbols(coingeckoNotionals)
notionals := j.convertToSymbols(coingeckoNotionals, now)
j.logger.Info("convert to symbol", zap.Int("notionals", len(coingeckoNotionals)), zap.Int("symbols", len(notionals)))
// save notional value of assets in cache.
@ -73,6 +86,11 @@ func (j *NotionalJob) Run() error {
return err
}
if err = j.notify(ctx, now, coingeckoNotionals); err != nil {
j.logger.Error("failed to notify notional value of assets", zap.Error(err))
return err
}
return nil
}
@ -93,10 +111,9 @@ func (j *NotionalJob) updateNotionalCache(notionals map[string]notional.PriceDat
// convertToSymbols converts the coingecko response into a symbol map
//
// The returned map has symbols as keys, and price data as the values.
func (j *NotionalJob) convertToSymbols(m map[string]coingecko.NotionalUSD) map[string]notional.PriceData {
func (j *NotionalJob) convertToSymbols(m map[string]coingecko.NotionalUSD, now time.Time) map[string]notional.PriceData {
w := make(map[string]notional.PriceData, len(m))
now := time.Now()
for _, v := range j.tokenProvider.GetAllTokens() {
notionalUSD, ok := m[v.CoingeckoID]
@ -129,3 +146,35 @@ func formatChannel(prefix string, channel string) string {
}
return channel
}
func S3Notifier(s3Repository *s3.S3Repository) notify {
return func(ctx context.Context, t time.Time, notionals map[string]coingecko.NotionalUSD) error {
r := t.UTC().Truncate(5 * time.Minute)
key := fmt.Sprintf("jobs/notional/%4d/%02d/%02d/%02d%02d.json", r.Year(), r.Month(), r.Day(), r.Hour(), r.Minute())
prices := make([]price, 0)
for k, v := range notionals {
if v.Price != nil && k != "" {
prices = append(prices, price{
CoingeckoID: k,
PriceUSD: *v.Price,
})
}
}
body, err := json.Marshal(prices)
if err != nil {
return err
}
return s3Repository.Save(ctx, key, body)
}
}
type price struct {
CoingeckoID string `json:"coingecko_id"`
PriceUSD decimal.Decimal `json:"price_usd"`
}
func NoopNotifier() notify {
return func(ctx context.Context, t time.Time, notionals map[string]coingecko.NotionalUSD) error {
return nil
}
}

View File

@ -57,6 +57,10 @@ func (c *Controller) FindByCoingeckoID(ctx *fiber.Ctx) error {
price, err := c.priceService.GetPriceByCoingeckoID(ctx.Context(), coingeckoID, *dateTime)
if errors.Is(err, ErrTokenNotFound) {
return fiber.NewError(fiber.StatusNotFound, "token not found")
}
return c.handleResponse(err, ctx, price)
}

View File

@ -6,6 +6,7 @@ import (
"time"
"github.com/shopspring/decimal"
"github.com/wormhole-foundation/wormhole-explorer/common/repository"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
@ -50,7 +51,7 @@ func (p *PriceRepository) Upsert(ctx context.Context, coingeckoID string, price
update := bson.M{
"$set": model,
"$setOnInsert": indexedAt(time.Now()),
"$setOnInsert": repository.IndexedAt(time.Now()),
"$inc": bson.D{{Key: "revision", Value: 1}},
}
@ -75,15 +76,5 @@ func (p *PriceRepository) Find(ctx context.Context, coingeckoID string, dateTime
}
func (p *PriceRepository) createID(coingeckoID string, dateTime time.Time) string {
return fmt.Sprintf("%s-%s", coingeckoID, dateTime.Format(time.RFC3339))
}
func indexedAt(t time.Time) IndexingTimestamps {
return IndexingTimestamps{
IndexedAt: t,
}
}
type IndexingTimestamps struct {
IndexedAt time.Time `bson:"indexedAt"`
return fmt.Sprintf("%s-%s", coingeckoID, dateTime.UTC().Format(time.RFC3339))
}

View File

@ -100,6 +100,9 @@ func (s *PriceService) GetPriceBySymbol(ctx context.Context, token *domain.Token
dayDatetime := datetime.Truncate(24 * time.Hour)
cachePrice, err := s.notionalCache.Get(token.GetTokenID())
if err != nil {
if err == wormscanNotionalCache.ErrNotFound {
return nil, ErrTokenNotFound
}
return nil, err
}

View File

@ -59,10 +59,10 @@ func addBackfillerByTimeRange(parent *cobra.Command) {
},
}
// before flag
timeRange.Flags().StringVar(&before, "before", "", "path to input vaa file")
timeRange.Flags().StringVar(&before, "before", "", "before timestamp in RFC3339 format")
timeRange.MarkFlagRequired("before")
// after flag
timeRange.Flags().StringVar(&after, "after", "", "path to output file")
timeRange.Flags().StringVar(&after, "after", "", "after timestamp in RFC3339 format")
timeRange.MarkFlagRequired("after")
parent.AddCommand(timeRange)
}
@ -89,14 +89,14 @@ func addBackfillerByVaas(parent *cobra.Command) {
},
}
// emitter-chain flag
vaas.Flags().Uint16Var(&emitterChainID, "emitter-chain", 0, "path to input vaa file")
vaas.Flags().Uint16Var(&emitterChainID, "emitter-chain", 0, "emitter chain id")
vaas.MarkFlagRequired("emitter-chain")
// emitter-address flag
vaas.Flags().StringVar(&emitterAddress, "emitter-address", "", "path to output file")
vaas.Flags().StringVar(&emitterAddress, "emitter-address", "", "emitter address")
// sequence flag
vaas.Flags().StringVar(&sequence, "sequence", "", "path to output file")
vaas.Flags().StringVar(&sequence, "sequence", "", "sequence")
parent.AddCommand(vaas)
}