@@ -7,30 +7,38 @@ import { cache } from "../services";
77const CACHE_TTL_SECONDS = 5 * 60 ; // 5 minutes
88
99export interface VolumeRow {
10+ chain : string ;
1011 buy_usd : number ;
1112 sell_usd : number ;
1213 total_usd : number ;
1314}
1415
15- export interface DailyVolume extends VolumeRow {
16+ export interface MonthlyVolume extends VolumeRow {
17+ month : string ;
18+ }
19+
20+ export interface ChainVolume {
21+ chain : string ;
22+ buy_usd : number ;
23+ sell_usd : number ;
24+ total_usd : number ;
25+ }
26+
27+ export interface DailyVolume {
1628 day : string ;
29+ chains : ChainVolume [ ] ;
1730}
1831
19- export interface MonthlyVolume extends VolumeRow {
32+ export interface MonthlyVolume {
2033 month : string ;
34+ chains : ChainVolume [ ] ;
2135}
2236
23- export interface WeeklyVolume extends VolumeRow {
37+ export interface WeeklyVolume {
2438 week : string ;
2539 startDate : string ;
2640 endDate : string ;
27- }
28-
29- export interface VolumeData {
30- monthly : MonthlyVolume [ ] ;
31- weekly : WeeklyVolume [ ] ;
32- daily : DailyVolume [ ] ;
33- selectedMonth : string ;
41+ chains : ChainVolume [ ] ;
3442}
3543
3644let supabaseClient : SupabaseClient | null = null ;
@@ -50,9 +58,7 @@ function getSupabaseClient() {
5058
5159const zeroVolume = ( key : string , keyName : "day" | "month" ) : any => ( {
5260 [ keyName ] : key ,
53- buy_usd : 0 ,
54- sell_usd : 0 ,
55- total_usd : 0
61+ chains : [ ]
5662} ) ;
5763
5864async function getMonthlyVolumes ( ) : Promise < MonthlyVolume [ ] > {
@@ -62,7 +68,7 @@ async function getMonthlyVolumes(): Promise<MonthlyVolume[]> {
6268
6369 try {
6470 const supabase = getSupabaseClient ( ) ;
65- const { data, error } = await supabase . rpc ( "get_monthly_volumes " , { year_param : null } ) ;
71+ const { data, error } = await supabase . rpc ( "get_monthly_volumes_by_chain " , { year_param : null } ) ;
6672 if ( error ) throw error ;
6773
6874 const rawData = ( data as MonthlyVolume [ ] ) || [ ] ;
@@ -91,60 +97,58 @@ async function getMonthlyVolumes(): Promise<MonthlyVolume[]> {
9197}
9298
9399async function getDailyVolumes ( startDate : string , endDate : string ) : Promise < DailyVolume [ ] > {
94- const cacheKey = `daily-${ startDate } -${ endDate } ` ;
95- const cached = cache . get < DailyVolume [ ] > ( cacheKey ) ;
96- if ( cached ) return cached ;
97-
98- try {
99- const supabase = getSupabaseClient ( ) ;
100- const { data, error } = await supabase . rpc ( "get_daily_volumes" , { end_date : endDate , start_date : startDate } ) ;
101- if ( error ) throw error ;
102-
103- const rawData = ( data as DailyVolume [ ] ) || [ ] ;
104- const dataMap = new Map ( rawData . map ( row => [ row . day , row ] ) ) ;
105-
106- const current = new Date ( startDate ) ;
107- const end = new Date ( endDate ) ;
108- const volumes : DailyVolume [ ] = [ ] ;
109-
110- while ( current <= end ) {
111- const dayStr = current . toISOString ( ) . slice ( 0 , 10 ) ;
112- volumes . push ( dataMap . get ( dayStr ) || zeroVolume ( dayStr , "day" ) ) ;
113- current . setDate ( current . getDate ( ) + 1 ) ;
114- }
115-
116- cache . set ( cacheKey , volumes , CACHE_TTL_SECONDS ) ;
117- return volumes ;
118- } catch ( error : any ) {
119- throw new Error ( "Could not calculate daily volumes: " + error . message ) ;
100+ const supabase = getSupabaseClient ( ) ;
101+ const { data, error } = await supabase . rpc ( "get_daily_volumes_by_chain" , {
102+ end_date : endDate ,
103+ start_date : startDate
104+ } ) ;
105+
106+ if ( error ) throw error ;
107+
108+ const rawData = ( data as DailyVolume [ ] ) || [ ] ;
109+ const dataMap = new Map ( rawData . map ( row => [ row . day , row ] ) ) ;
110+
111+ const current = new Date ( startDate ) ;
112+ const end = new Date ( endDate ) ;
113+ const volumes : DailyVolume [ ] = [ ] ;
114+
115+ while ( current <= end ) {
116+ const dayStr = current . toISOString ( ) . slice ( 0 , 10 ) ;
117+ // If date is missing, return empty chains array instead of zeroed fields
118+ volumes . push ( dataMap . get ( dayStr ) || { chains : [ ] , day : dayStr } ) ;
119+ current . setDate ( current . getDate ( ) + 1 ) ;
120120 }
121+
122+ return volumes ;
121123}
122124
123125function aggregateWeekly ( daily : DailyVolume [ ] ) : WeeklyVolume [ ] {
124126 const weeks : WeeklyVolume [ ] = [ ] ;
125127
126128 for ( let i = 0 ; i < daily . length ; i += 7 ) {
127129 const chunk = daily . slice ( i , i + 7 ) ;
128- const startDay = chunk [ 0 ] ;
129- const endDay = chunk [ chunk . length - 1 ] ;
130-
131- const startDate = new Date ( startDay . day ) ;
132- const endDate = new Date ( endDay . day ) ;
133-
134- const startMonth = startDate . toLocaleString ( "en-US" , { month : "short" , timeZone : "UTC" } ) ;
135- const endMonth = endDate . toLocaleString ( "en-US" , { month : "short" , timeZone : "UTC" } ) ;
136- const weekLabel = `${ startMonth } ${ startDate . getUTCDate ( ) } - ${ endMonth } ${ endDate . getUTCDate ( ) } ` ;
130+ const startDay = chunk [ 0 ] . day ;
131+ const endDay = chunk [ chunk . length - 1 ] . day ;
132+
133+ const chainTotals = new Map < string , any > ( ) ;
134+
135+ chunk . forEach ( day => {
136+ day . chains . forEach ( ( c : any ) => {
137+ const existing = chainTotals . get ( c . chain ) || { buy_usd : 0 , chain : c . chain , sell_usd : 0 , total_usd : 0 } ;
138+ existing . buy_usd += c . buy_usd ;
139+ existing . sell_usd += c . sell_usd ;
140+ existing . total_usd += c . total_usd ;
141+ chainTotals . set ( c . chain , existing ) ;
142+ } ) ;
143+ } ) ;
137144
138145 weeks . push ( {
139- buy_usd : chunk . reduce ( ( sum , d ) => sum + d . buy_usd , 0 ) ,
140- endDate : endDay . day ,
141- sell_usd : chunk . reduce ( ( sum , d ) => sum + d . sell_usd , 0 ) ,
142- startDate : startDay . day ,
143- total_usd : chunk . reduce ( ( sum , d ) => sum + d . total_usd , 0 ) ,
144- week : weekLabel
146+ chains : Array . from ( chainTotals . values ( ) ) ,
147+ endDate : endDay ,
148+ startDate : startDay ,
149+ week : `${ startDay } to ${ endDay } `
145150 } ) ;
146151 }
147-
148152 return weeks ;
149153}
150154
0 commit comments