import { useEffect, useMemo, useState } from 'react' import dayjs from 'dayjs' import useMangoStore from '../../stores/useMangoStore' import { Table, TableDateDisplay, Td, Th, TrBody, TrHead, } from '../TableElements' import isEmpty from 'lodash/isEmpty' import { useTranslation } from 'next-i18next' import Pagination from '../Pagination' import usePagination from '../../hooks/usePagination' import { roundToDecimal } from '../../utils' import Chart from '../Chart' import Switch from '../Switch' import useLocalStorageState from '../../hooks/useLocalStorageState' import { handleDustTicks } from './AccountInterest' const utc = require('dayjs/plugin/utc') dayjs.extend(utc) import { exportDataToCSV } from '../../utils/export' import Button from '../Button' import { SaveIcon } from '@heroicons/react/solid' import TabButtons from 'components/TabButtons' const QUOTE_DECIMALS = 6 const AccountFunding = () => { const { t } = useTranslation('common') const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current) const [fundingStats, setFundingStats] = useState([]) const [hourlyFunding, setHourlyFunding] = useState([]) const [selectedAsset, setSelectedAsset] = useState('') const [loadHourlyStats, setLoadHourlyStats] = useState(false) const [loadTotalStats, setLoadTotalStats] = useState(false) const { paginatedData, setData, totalPages, nextPage, previousPage, page, firstPage, lastPage, } = usePagination(hourlyFunding[selectedAsset] || []) const [hideFundingDust, setHideFundingDust] = useLocalStorageState( 'hideFundingDust', false ) const [chartData, setChartData] = useState([]) const mangoAccountPk = useMemo(() => { if (mangoAccount) { return mangoAccount.publicKey.toString() } }, [mangoAccount]) const exportFundingDataToCSV = () => { const assets = Object.keys(hourlyFunding) let dataToExport: any[] = [] for (const asset of assets) { dataToExport = [ ...dataToExport, ...hourlyFunding[asset].map((funding) => { const timestamp = new Date(funding.time) return { timestamp: `${timestamp.toLocaleDateString()} ${timestamp.toLocaleTimeString()}`, asset: asset, amount: funding.total_funding, } }), ] } const title = `${ mangoAccount?.name || mangoAccount?.publicKey }-Funding-${new Date().toLocaleDateString()}` const columns = ['Timestamp', 'Asset', 'Amount'] exportDataToCSV(dataToExport, title, columns, t) } useEffect(() => { if (!isEmpty(hourlyFunding)) { setData(hourlyFunding[selectedAsset] || []) } }, [selectedAsset, hourlyFunding]) useEffect(() => { const hideDust: any[] = [] const fetchFundingStats = async () => { setLoadTotalStats(true) const response = await fetch( `https://mango-transaction-log.herokuapp.com/v3/stats/total-funding?mango-account=${mangoAccountPk}` ) const parsedResponse = await response.json() if (hideFundingDust) { Object.entries(parsedResponse).forEach((r: any) => { const funding = r[1].total_funding if (Math.abs(funding) > 1) { hideDust.push(r) } }) setLoadTotalStats(false) setFundingStats(hideDust) } else { setLoadTotalStats(false) setFundingStats(Object.entries(parsedResponse)) } } const fetchHourlyFundingStats = async () => { setLoadHourlyStats(true) const response = await fetch( `https://mango-transaction-log.herokuapp.com/v3/stats/hourly-funding?mango-account=${mangoAccountPk}` ) const parsedResponse = await response.json() let assets if (hideFundingDust) { const assetsToShow = hideDust.map((a) => a[0]) assets = Object.keys(parsedResponse).filter((a) => assetsToShow.includes(a) ) setSelectedAsset(assetsToShow[0]) } else { assets = Object.keys(parsedResponse) } const stats = {} for (const asset of assets) { const x: any = Object.entries(parsedResponse[asset]) stats[asset] = x .map(([key, value]) => { const funding = roundToDecimal( value.total_funding, QUOTE_DECIMALS + 1 ) if (funding !== 0) { return { ...value, time: key } } else { return null } }) .filter((x) => x) .reverse() } setLoadHourlyStats(false) setHourlyFunding(stats) } const getStats = async () => { fetchFundingStats() fetchHourlyFundingStats() } getStats() }, [mangoAccountPk, hideFundingDust]) useEffect(() => { if (hourlyFunding[selectedAsset]) { const start = new Date( // @ts-ignore dayjs().utc().hour(0).minute(0).subtract(29, 'day') ).getTime() const filtered = hourlyFunding[selectedAsset].filter( (d) => new Date(d.time).getTime() > start ) const dailyFunding: any[] = [] for (let i = 0; i < 30; i++) { dailyFunding.push({ funding: 0, time: new Date( // @ts-ignore dayjs().utc().hour(0).minute(0).subtract(i, 'day') ).getTime(), }) } filtered.forEach((d) => { const found = dailyFunding.find( (x) => dayjs(x.time).format('DD-MMM') === dayjs(d.time).format('DD-MMM') ) if (found) { const newFunding = d.total_funding found.funding = found.funding + newFunding } }) setChartData(dailyFunding.reverse()) } }, [hourlyFunding, selectedAsset]) useEffect(() => { if (!selectedAsset && Object.keys(hourlyFunding).length > 0) { setSelectedAsset(Object.keys(hourlyFunding)[0]) } }, [hourlyFunding]) return ( <>

{t('total-funding')}

setHideFundingDust(!hideFundingDust)} > {t('hide-dust')}
{mangoAccount ? (
{loadTotalStats ? (
) : ( {fundingStats.length === 0 ? ( ) : ( fundingStats.map(([symbol, stats]) => { return ( ) }) )}
{t('token')} {t('total-funding')} (USDC)
{t('no-funding')}
{symbol}-PERP
0 ? 'text-th-green' : stats.total_funding < 0 ? 'text-th-red' : 'text-th-fgd-3' }`} > {stats.total_funding ? `${stats.total_funding?.toLocaleString( undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2, } )}` : '-'}
)} <> {!isEmpty(hourlyFunding) && !loadHourlyStats ? ( <>

{t('history')}

({ label: token, key: token, }))} onClick={setSelectedAsset} showSymbolIcon />
{selectedAsset && chartData.length > 0 ? (
{chartData.find((d) => d.funding !== 0) ? (
x && `${x?.toLocaleString(undefined, { maximumFractionDigits: 6, })} USDC` } tickFormat={handleDustTicks} titleValue={chartData.reduce( (a, c) => a + c.funding, 0 )} type="bar" useMulticoloredBars yAxisWidth={70} zeroLine />
) : null}
) : null}
{paginatedData.length ? ( {paginatedData.map((stat) => { // @ts-ignore const utc = dayjs.utc(stat.time).format() return ( ) })}
{t('time')} {t('funding')} (USDC)
{stat.total_funding.toFixed( QUOTE_DECIMALS + 1 )}
) : (
{t('no-funding')}
)}
) : loadHourlyStats ? (
) : null}
) : (
{t('connect-wallet')}
)} ) } export default AccountFunding