Add total tx count and total tx volume by portal bridge for scorecards (#314)

Co-authored-by: walker-16 <agpazos85@gmail.com>
This commit is contained in:
ftocal 2023-05-15 15:15:12 -03:00 committed by GitHub
parent c25ebcb6fc
commit c2b94f6448
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 176 additions and 38 deletions

View File

@ -0,0 +1,17 @@
import "date"
option task = {
name: "total tx count by portal bridge",
every: 24h,
}
stop = date.truncate(t: now(), unit: 24h)
from(bucket: "wormscan")
|> range(start: 1970-01-01T00:00:00Z, stop: stop)
|> filter(fn: (r) => r["_measurement"] == "vaa_volume")
|> filter(fn: (r) => r["_field"] == "volume")
|> group()
|> count()
|> map(fn: (r) => ({ _time: r._stop, _value: r._value, _measurement: "total_tx_count", _field: "value" }))
|> to(bucket: "wormscan-30days")

View File

@ -0,0 +1,17 @@
import "date"
option task = {
name: "total tx volume by portal bridge",
every: 24h,
}
stop = date.truncate(t: now(), unit: 24h)
from(bucket: "wormscan")
|> range(start: 1970-01-01T00:00:00Z, stop: stop)
|> filter(fn: (r) => r["_measurement"] == "vaa_volume")
|> filter(fn: (r) => r["_field"] == "volume")
|> group()
|> sum()
|> map(fn: (r) => ({ _time: r._stop, _value: r._value, _measurement: "total_tx_volume", _field: "value" }))
|> to(bucket: "wormscan-30days")

View File

@ -12,6 +12,9 @@ type Scorecards struct {
// Number of VAAs emitted since the creation of the network (does not include Pyth messages)
TotalTxCount string
//Volume transferred 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
@ -118,8 +121,8 @@ type TransactionCountResult struct {
}
type ChainActivityResult struct {
ChainSourceID string `mapstructure:"chain_source_id"`
ChainDestinationID string `mapstructure:"chain_destination_id"`
ChainSourceID string `mapstructure:"emitter_chain"`
ChainDestinationID string `mapstructure:"destination_chain"`
Volume uint64 `mapstructure:"volume"`
}

View File

@ -64,3 +64,45 @@ func createRangeQuery(t time.Time, timeSpan string) (string, string) {
return startLastVaa.Format(format), startAggregatesVaa.Format(format)
}
const queryTemplateTotalTrxCount = `
current = from(bucket: "%s")
|> range(start: %s)
|> filter(fn: (r) => r["_measurement"] == "vaa_volume")
|> filter(fn: (r) => r["_field"] == "volume")
|> group()
|> count()
last = from(bucket: "%s")
|> range(start: -1mo)
|> filter(fn: (r) => r["_measurement"] == "total_tx_count")
|> last()
union(tables: [current, last])
|> group()
|> sum()
`
func buildTotalTrxCountQuery(bucketForever, bucket30Days string, t time.Time) string {
start := t.Truncate(time.Hour * 24).Format(time.RFC3339Nano)
return fmt.Sprintf(queryTemplateTotalTrxCount, bucketForever, start, bucket30Days)
}
const queryTemplateTotalTrxVolume = `
current = from(bucket: "%s")
|> range(start: %s)
|> filter(fn: (r) => r["_measurement"] == "vaa_volume")
|> filter(fn: (r) => r["_field"] == "volume")
|> group()
|> sum()
last = from(bucket: "%s")
|> range(start: -1mo)
|> filter(fn: (r) => r["_measurement"] == "total_tx_volume")
|> last()
union(tables: [current, last])
|> group()
|> sum()
`
func buildTotalTrxVolumeQuery(bucketForever, bucket30Days string, t time.Time) string {
start := t.Truncate(time.Hour * 24).Format(time.RFC3339Nano)
return fmt.Sprintf(queryTemplateTotalTrxVolume, bucketForever, start, bucket30Days)
}

View File

@ -1,7 +1,6 @@
package transactions
import (
"fmt"
"testing"
"time"
@ -62,8 +61,6 @@ union(tables: [aggregatesVaaCount, lastVaaCount])
//2023-05-04T18:39:10.985Z
tm := time.Date(2023, 5, 4, 18, 39, 10, 985, time.UTC)
actual := buildLastTrxQuery("wormscan-1month", tm, &TransactionCountQuery{TimeSpan: "1d", SampleRate: "1h"})
fmt.Println(actual)
fmt.Println(actual)
assert.Equal(t, expected, actual)
}
@ -86,7 +83,51 @@ union(tables: [aggregatesVaaCount, lastVaaCount])
//2023-05-04T18:39:10.985Z
tm := time.Date(2023, 5, 4, 18, 39, 10, 985, time.UTC)
actual := buildLastTrxQuery("wormscan-1month", tm, &TransactionCountQuery{TimeSpan: "1w", SampleRate: "1d"})
fmt.Println(actual)
fmt.Println(actual)
assert.Equal(t, expected, actual)
}
func TestQueries_buildTotalTrxCountQuery(t *testing.T) {
expected := `
current = from(bucket: "bucket-forever")
|> range(start: 2023-05-12T00:00:00Z)
|> filter(fn: (r) => r["_measurement"] == "vaa_volume")
|> filter(fn: (r) => r["_field"] == "volume")
|> group()
|> count()
last = from(bucket: "bucket-30days")
|> range(start: -1mo)
|> filter(fn: (r) => r["_measurement"] == "total_tx_count")
|> last()
union(tables: [current, last])
|> group()
|> sum()
`
//2023-05-04T18:39:10.985Z
tm := time.Date(2023, 5, 12, 16, 53, 10, 985, time.UTC)
actual := buildTotalTrxCountQuery("bucket-forever", "bucket-30days", tm)
assert.Equal(t, expected, actual)
}
func TestQueries_buildTotalTrxVolumeQuery(t *testing.T) {
expected := `
current = from(bucket: "bucket-forever")
|> range(start: 2023-05-10T00:00:00Z)
|> filter(fn: (r) => r["_measurement"] == "vaa_volume")
|> filter(fn: (r) => r["_field"] == "volume")
|> group()
|> sum()
last = from(bucket: "bucket-30days")
|> range(start: -1mo)
|> filter(fn: (r) => r["_measurement"] == "total_tx_volume")
|> last()
union(tables: [current, last])
|> group()
|> sum()
`
//2023-05-04T18:39:10.985Z
tm := time.Date(2023, 5, 10, 16, 53, 10, 985, time.UTC)
actual := buildTotalTrxVolumeQuery("bucket-forever", "bucket-30days", tm)
assert.Equal(t, expected, actual)
}

View File

@ -37,13 +37,6 @@ from(bucket: "%s")
|> %s(column: "volume")
`
const queryTemplateTotalTxCount = `
from(bucket: "%s")
|> range(start: 2018-01-01T00:00:00Z)
|> filter(fn: (r) => r._field == "total_vaa_count")
|> last()
`
const queryTemplateTxCount24h = `
from(bucket: "%s")
|> range(start: -24h)
@ -169,7 +162,7 @@ func (r *Repository) GetTopAssets(ctx context.Context, timeSpan *TopStatisticsTi
EmitterChain string `mapstructure:"emitter_chain"`
TokenChain string `mapstructure:"token_chain"`
TokenAddress string `mapstructure:"token_address"`
Volume int64 `mapstructure:"_value"`
Volume uint64 `mapstructure:"_value"`
}
var rows []Row
for result.Next() {
@ -265,7 +258,7 @@ func (r *Repository) GetTopChainPairs(ctx context.Context, timeSpan *TopStatisti
}
// convertToDecimal converts an integer amount to a decimal string, with 8 decimals of precision.
func convertToDecimal(amount int64) string {
func convertToDecimal(amount uint64) string {
// If the amount is less than 1, just use a format mask.
if amount < 1_0000_0000 {
@ -318,12 +311,15 @@ func (r *Repository) buildFindVolumeQuery(q *ChainActivityQuery) string {
func (r *Repository) GetScorecards(ctx context.Context) (*Scorecards, error) {
//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")
//}
totalTxCount, err := r.getTotalTxCount(ctx)
if err != nil {
return nil, fmt.Errorf("failed to query total tx count by portal bridge")
}
totalTxVolume, err := r.getTotalTxVolume(ctx)
if err != nil {
return nil, fmt.Errorf("failed to query tx volume by portal bridge")
}
txCount24h, err := r.getTxCount24h(ctx)
if err != nil {
@ -337,9 +333,10 @@ func (r *Repository) GetScorecards(ctx context.Context) (*Scorecards, error) {
// build the result and return
scorecards := Scorecards{
//TotalTxCount: totalTxCount,
TxCount24h: txCount24h,
Volume24h: volume24h,
TotalTxCount: totalTxCount,
TotalTxVolume: totalTxVolume,
TxCount24h: txCount24h,
Volume24h: volume24h,
}
return &scorecards, nil
@ -347,30 +344,50 @@ func (r *Repository) GetScorecards(ctx context.Context) (*Scorecards, error) {
func (r *Repository) getTotalTxCount(ctx context.Context) (string, error) {
// query 24h transactions
query := fmt.Sprintf(queryTemplateTotalTxCount, r.bucketInfiniteRetention)
query := buildTotalTrxCountQuery(r.bucketInfiniteRetention, r.bucket30DaysRetention, time.Now())
result, err := r.queryAPI.Query(ctx, query)
if err != nil {
r.logger.Error("failed to query total transaction count", zap.Error(err))
r.logger.Error("failed to query total tx count by portal bridge", zap.Error(err))
return "", err
}
if result.Err() != nil {
r.logger.Error("total transaction count query result has errors", zap.Error(err))
r.logger.Error("failed to query total tx count by portal bridge 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 "", errors.New("expected at least one record in query total tx count by portal bridge result")
}
// 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.Errorf("failed to decode total tx count by portal bridge query response: %w", err)
}
return fmt.Sprintf("%d", row.Value), nil
}
return fmt.Sprint(row.Value), nil
func (r *Repository) getTotalTxVolume(ctx context.Context) (string, error) {
query := buildTotalTrxVolumeQuery(r.bucketInfiniteRetention, r.bucket30DaysRetention, time.Now())
result, err := r.queryAPI.Query(ctx, query)
if err != nil {
r.logger.Error("failed to query total tx volume by portal bridge", zap.Error(err))
return "", err
}
if result.Err() != nil {
r.logger.Error("failed to query tx volume by portal bridge result has errors", zap.Error(err))
return "", result.Err()
}
if !result.Next() {
return "", errors.New("expected at least one record in query tx volume by portal bridge result")
}
row := struct {
Value uint64 `mapstructure:"_value"`
}{}
if err := mapstructure.Decode(result.Record().Values(), &row); err != nil {
return "", fmt.Errorf("failed to decode tx volume by portal bridge query response: %w", err)
}
return convertToDecimal(row.Value), nil
}
func (r *Repository) getTxCount24h(ctx context.Context) (string, error) {
@ -420,7 +437,7 @@ func (r *Repository) getVolume24h(ctx context.Context) (string, error) {
// deserialize the row returned
row := struct {
Value int64 `mapstructure:"_value"`
Value uint64 `mapstructure:"_value"`
}{}
if err := mapstructure.Decode(result.Record().Values(), &row); err != nil {
return "", fmt.Errorf("failed to decode 24h volume count query response: %w", err)

View File

@ -5,7 +5,7 @@ import "testing"
func Test_convertToDecimal(t *testing.T) {
tcs := []struct {
input int64
input uint64
output string
}{
{

View File

@ -78,6 +78,7 @@ func (c *Controller) GetScorecards(ctx *fiber.Ctx) error {
// Convert indicators to the response model
response := ScorecardsResponse{
TotalTxCount: scorecards.TotalTxCount,
TotalVolume: scorecards.TotalTxVolume,
TxCount24h: scorecards.TxCount24h,
Volume24h: scorecards.Volume24h,
}

View File

@ -31,9 +31,9 @@ type ScorecardsResponse struct {
//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"`
TotalTxCount string `json:"total_tx_count"`
//TotalVolume string `json:"total_volume"`
TotalVolume string `json:"total_volume"`
//TVL string `json:"tvl"`