Files
explorer-monorepo/backend/analytics/bridge_analytics.go

128 lines
2.9 KiB
Go

package analytics
import (
"context"
"fmt"
"time"
"github.com/jackc/pgx/v5/pgxpool"
)
// BridgeAnalytics provides bridge analytics
type BridgeAnalytics struct {
db *pgxpool.Pool
}
// NewBridgeAnalytics creates a new bridge analytics instance
func NewBridgeAnalytics(db *pgxpool.Pool) *BridgeAnalytics {
return &BridgeAnalytics{db: db}
}
// BridgeStats represents bridge statistics
type BridgeStats struct {
Transfers24h int
Volume24h string
Chains map[int]ChainStats
TopTokens []TokenStats
}
// ChainStats represents chain statistics
type ChainStats struct {
Outbound int
Inbound int
VolumeOut string
VolumeIn string
}
// TokenStats represents token statistics
type TokenStats struct {
Token string
Symbol string
Transfers int
Volume string
}
// GetBridgeStats gets bridge statistics
func (ba *BridgeAnalytics) GetBridgeStats(ctx context.Context, chainFrom, chainTo *int, startDate, endDate *time.Time) (*BridgeStats, error) {
query := `
SELECT
COUNT(*) as transfers_24h,
SUM(amount) as volume_24h
FROM analytics_bridge_history
WHERE timestamp >= NOW() - INTERVAL '24 hours'
`
args := []interface{}{}
argIndex := 1
if chainFrom != nil {
query += fmt.Sprintf(" AND chain_from = $%d", argIndex)
args = append(args, *chainFrom)
argIndex++
}
if chainTo != nil {
query += fmt.Sprintf(" AND chain_to = $%d", argIndex)
args = append(args, *chainTo)
argIndex++
}
if startDate != nil {
query += fmt.Sprintf(" AND timestamp >= $%d", argIndex)
args = append(args, *startDate)
argIndex++
}
if endDate != nil {
query += fmt.Sprintf(" AND timestamp <= $%d", argIndex)
args = append(args, *endDate)
argIndex++
}
var transfers24h int
var volume24h string
err := ba.db.QueryRow(ctx, query, args...).Scan(&transfers24h, &volume24h)
if err != nil {
return nil, fmt.Errorf("failed to get bridge stats: %w", err)
}
stats := &BridgeStats{
Transfers24h: transfers24h,
Volume24h: volume24h,
Chains: make(map[int]ChainStats),
TopTokens: []TokenStats{},
}
// Get chain stats
chainQuery := `
SELECT
chain_from,
COUNT(*) FILTER (WHERE chain_from = $1) as outbound,
COUNT(*) FILTER (WHERE chain_to = $1) as inbound,
SUM(amount) FILTER (WHERE chain_from = $1) as volume_out,
SUM(amount) FILTER (WHERE chain_to = $1) as volume_in
FROM analytics_bridge_history
WHERE (chain_from = $1 OR chain_to = $1) AND timestamp >= NOW() - INTERVAL '24 hours'
GROUP BY chain_from
`
// Simplified - in production, iterate over all chains
rows, _ := ba.db.Query(ctx, chainQuery, 138)
for rows.Next() {
var chainID, outbound, inbound int
var volumeOut, volumeIn string
if err := rows.Scan(&chainID, &outbound, &inbound, &volumeOut, &volumeIn); err == nil {
stats.Chains[chainID] = ChainStats{
Outbound: outbound,
Inbound: inbound,
VolumeOut: volumeOut,
VolumeIn: volumeIn,
}
}
}
rows.Close()
return stats, nil
}