Skip to content

Commit

Permalink
Daily transaction chart
Browse files Browse the repository at this point in the history
  • Loading branch information
lubej committed Mar 15, 2023
1 parent 278789e commit c400d5b
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 4 deletions.
32 changes: 28 additions & 4 deletions src/app/pages/DashboardPage/TransactionsChartCard.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { useTranslation } from 'react-i18next'
import { Layer, useGetLayerStatsTxVolume } from '../../../oasis-indexer/api'
import { ChartDuration, chartUseQueryStaleTimeMs, durationToQueryParams } from '../../utils/chart-utils'
import {
ChartDuration,
chartUseQueryStaleTimeMs,
durationToQueryParams,
sumBucketsByStartDuration,
} from '../../utils/chart-utils'
import { LineChart } from '../../components/charts/LineChart'
import { useTheme } from '@mui/material/styles'
import useMediaQuery from '@mui/material/useMediaQuery'
import { FC, memo } from 'react'
import { SnapshotCard } from './SnapshotCard'
import { PercentageGain } from '../../components/PercentageGain'
import startOfHour from 'date-fns/startOfHour'

interface TransactionsChartCardProps {
chartDuration: ChartDuration
Expand All @@ -17,19 +23,36 @@ const TransactionsChartCardCmp: FC<TransactionsChartCardProps> = ({ chartDuratio
const theme = useTheme()
const isMobile = useMediaQuery(theme.breakpoints.down('sm'))
const statsParams = durationToQueryParams[chartDuration]
const { data } = useGetLayerStatsTxVolume(Layer.emerald, statsParams, {
const { data, isFetched } = useGetLayerStatsTxVolume(Layer.emerald, statsParams, {
query: { staleTime: chartUseQueryStaleTimeMs },
})

const lineChartData = data?.data.buckets.map(bucket => {
const isDailyChart = isFetched && chartDuration === ChartDuration.TODAY

const buckets = data?.data.buckets.map(bucket => {
return {
bucket_start: bucket.bucket_start,
volume_per_second: bucket.tx_volume / statsParams.bucket_size_seconds,
}
})

const totalTransactions = data?.data.buckets.reduce((acc, curr) => acc + curr.tx_volume, 0) ?? 0

const lineChartData = isDailyChart
? sumBucketsByStartDuration(buckets, 'volume_per_second', 'bucket_start', startOfHour)
: buckets

const formatParams = isDailyChart
? {
timestamp: {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
} satisfies Intl.DateTimeFormatOptions,
}
: undefined

return (
<SnapshotCard
title={t('common.transactions')}
Expand Down Expand Up @@ -62,6 +85,7 @@ const TransactionsChartCardCmp: FC<TransactionsChartCardProps> = ({ chartDuratio
label: (value: string) =>
t('common.formattedDateTime', {
timestamp: new Date(value),
formatParams,
}),
}}
/>
Expand Down
40 changes: 40 additions & 0 deletions src/app/utils/chart-utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import startOfHour from 'date-fns/startOfHour'
import startOfDay from 'date-fns/startOfDay'
import isSameMonth from 'date-fns/isSameMonth'
import startOfMonth from 'date-fns/startOfMonth'
import { GetLayerStatsTxVolumeParams, type TxVolume, type ActiveAccounts } from '../../oasis-indexer/api'

export enum ChartDuration {
Expand Down Expand Up @@ -80,3 +83,40 @@ export const filterHourlyActiveAccounts = (
): ActiveAccounts[] | undefined => {
return windows?.filter((value, index) => index % 12 === 0)
}

type NumberOnly<T> = {
[key in keyof T as T[key] extends number | undefined ? key : never]: T[key]
}

type StringOnly<T> = {
[key in keyof T as T[key] extends string | undefined ? key : never]: T[key]
}

export const sumBucketsByStartDuration = <
T extends NumberOnly<any> & StringOnly<any>,
N extends keyof NumberOnly<T>,
S extends keyof StringOnly<T>,
>(
buckets: T[] | undefined,
sumKey: N,
dateKey: S,
startDurationFn: typeof startOfHour | typeof startOfDay | typeof startOfMonth,
) => {
if (!buckets) {
return []
}

const durationMap = buckets.reduce((accMap, item) => {
const key = startDurationFn(new Date(item[dateKey])).toISOString()

return {
...accMap,
[key]: (accMap[key] || 0) + item[sumKey],
}
}, {} as { [key: string]: number })

return Object.keys(durationMap).map(key => ({
[dateKey]: key,
[sumKey]: durationMap[key],
})) as T[]
}

0 comments on commit c400d5b

Please sign in to comment.