171 lines
5.9 KiB
TypeScript
171 lines
5.9 KiB
TypeScript
import Switch from '@components/forms/Switch'
|
|
import DetailedAreaOrBarChart from '@components/shared/DetailedAreaOrBarChart'
|
|
import mangoStore from '@store/mangoStore'
|
|
import usePerpStatsChartData from 'hooks/usePerpStatsChartData'
|
|
import { useMemo, useState } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import { MangoTokenStatsItem } from 'types'
|
|
import { formatYAxis } from 'utils/formatting'
|
|
import { groupPerpByHourlyInterval } from './Volume'
|
|
|
|
interface GroupedTokenDataItem extends MangoTokenStatsItem {
|
|
intervalStartMillis: number
|
|
}
|
|
|
|
const groupTokenByHourlyInterval = (
|
|
data: MangoTokenStatsItem[],
|
|
intervalDurationHours: number,
|
|
) => {
|
|
const intervalMillis = intervalDurationHours * 60 * 60 * 1000
|
|
const groupedData = []
|
|
let currentGroup: GroupedTokenDataItem | null = null
|
|
for (let i = 0; i < data.length; i++) {
|
|
const obj = data[i]
|
|
const date = new Date(obj.date)
|
|
const intervalStartMillis =
|
|
Math.floor(date.getTime() / intervalMillis) * intervalMillis
|
|
if (
|
|
!currentGroup ||
|
|
currentGroup.intervalStartMillis !== intervalStartMillis
|
|
) {
|
|
currentGroup = {
|
|
...obj,
|
|
intervalStartMillis: intervalStartMillis,
|
|
}
|
|
groupedData.push(currentGroup)
|
|
} else {
|
|
currentGroup.feesCollected += obj.feesCollected
|
|
}
|
|
}
|
|
return groupedData
|
|
}
|
|
|
|
const Fees = () => {
|
|
const { t } = useTranslation(['common', 'token', 'trade'])
|
|
const mangoStats = mangoStore((s) => s.tokenStats.mangoStats)
|
|
const loadingStats = mangoStore((s) => s.tokenStats.loading)
|
|
const loadingPerpStats = mangoStore((s) => s.perpStats.loading)
|
|
const [feesDaysToShow, setFeesDaysToShow] = useState('30')
|
|
const [showCumulativeFees, setShowCumulativeFees] = useState(true)
|
|
const [feesPerpDaysToShow, setFeesPerpDaysToShow] = useState('30')
|
|
const [showCumulativePerpFees, setShowCumulativePerpFees] = useState(true)
|
|
const { feeValues: perpFeeChartData } = usePerpStatsChartData()
|
|
|
|
const tokenFeesChartData = useMemo(() => {
|
|
if (!mangoStats.length) return []
|
|
if (showCumulativeFees) {
|
|
return mangoStats
|
|
} else {
|
|
const transformedData = []
|
|
for (let i = 1; i < mangoStats.length; i++) {
|
|
const currentInterval = { ...mangoStats[i] }
|
|
const previousInterval = mangoStats[i - 1]
|
|
|
|
// Calculate the absolute fees for the current interval
|
|
currentInterval.feesCollected =
|
|
currentInterval.feesCollected - previousInterval.feesCollected
|
|
|
|
transformedData.push(currentInterval)
|
|
}
|
|
transformedData.unshift(mangoStats[0])
|
|
|
|
if (feesDaysToShow === '30') {
|
|
return groupTokenByHourlyInterval(transformedData, 24)
|
|
} else if (feesDaysToShow === '7') {
|
|
return groupTokenByHourlyInterval(transformedData, 4)
|
|
} else return transformedData
|
|
}
|
|
}, [mangoStats, feesDaysToShow, showCumulativeFees])
|
|
|
|
const perpFeeValues = useMemo(() => {
|
|
if (!perpFeeChartData || !perpFeeChartData.length) return []
|
|
|
|
let feeChartData = perpFeeChartData
|
|
if (!showCumulativePerpFees) {
|
|
const transformedData = []
|
|
for (let i = 1; i < perpFeeChartData.length; i++) {
|
|
const currentInterval = { ...perpFeeChartData[i] }
|
|
const previousInterval = perpFeeChartData[i - 1]
|
|
|
|
// Calculate the absolute fees for the current interval
|
|
currentInterval.value = currentInterval.value - previousInterval.value
|
|
|
|
transformedData.push(currentInterval)
|
|
}
|
|
transformedData.unshift(perpFeeChartData[0])
|
|
|
|
if (feesDaysToShow === '30') {
|
|
feeChartData = groupPerpByHourlyInterval(transformedData, 24)
|
|
} else if (feesDaysToShow === '7') {
|
|
feeChartData = groupPerpByHourlyInterval(transformedData, 4)
|
|
} else feeChartData = transformedData
|
|
}
|
|
|
|
return feeChartData
|
|
}, [feesDaysToShow, perpFeeChartData, showCumulativePerpFees])
|
|
|
|
return (
|
|
<>
|
|
<div className="col-span-2 flex flex-col justify-between border-b border-th-bkg-3 md:col-span-1">
|
|
<div className="px-4 pt-4 md:px-6 lg:pt-6">
|
|
<DetailedAreaOrBarChart
|
|
changeAsPercent
|
|
data={tokenFeesChartData}
|
|
daysToShow={feesDaysToShow}
|
|
setDaysToShow={setFeesDaysToShow}
|
|
heightClass="h-64"
|
|
loaderHeightClass="h-[350px]"
|
|
loading={loadingStats}
|
|
prefix="$"
|
|
tickFormat={(x) => `$${formatYAxis(x)}`}
|
|
title={t('token:token-fees-collected')}
|
|
tooltipContent={t('token:tooltip-token-fees-collected')}
|
|
xKey="date"
|
|
yKey={'feesCollected'}
|
|
chartType={showCumulativeFees ? 'area' : 'bar'}
|
|
/>
|
|
</div>
|
|
<div className="flex justify-end px-4 pb-4 md:px-6">
|
|
<Switch
|
|
checked={showCumulativeFees}
|
|
onChange={() => setShowCumulativeFees(!showCumulativeFees)}
|
|
small
|
|
>
|
|
{t('stats:show-cumulative')}
|
|
</Switch>
|
|
</div>
|
|
</div>
|
|
<div className="col-span-2 flex flex-col justify-between border-b border-th-bkg-3 md:col-span-1">
|
|
<div className="px-4 pt-4 md:px-6 lg:pt-6">
|
|
<DetailedAreaOrBarChart
|
|
changeAsPercent
|
|
data={perpFeeValues}
|
|
daysToShow={feesPerpDaysToShow}
|
|
setDaysToShow={setFeesPerpDaysToShow}
|
|
heightClass="h-64"
|
|
loading={loadingPerpStats}
|
|
loaderHeightClass="h-[350px]"
|
|
prefix="$"
|
|
tickFormat={(x) => `$${formatYAxis(x)}`}
|
|
title="Perp Fees"
|
|
xKey="date"
|
|
yKey="value"
|
|
chartType={showCumulativePerpFees ? 'area' : 'bar'}
|
|
/>
|
|
</div>
|
|
<div className="flex justify-end px-4 pb-4 md:px-6">
|
|
<Switch
|
|
checked={showCumulativePerpFees}
|
|
onChange={() => setShowCumulativePerpFees(!showCumulativePerpFees)}
|
|
small
|
|
>
|
|
{t('stats:show-cumulative')}
|
|
</Switch>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default Fees
|