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 }