import { useEffect, useMemo, useState } from 'react' import dayjs from 'dayjs' import useMangoStore from '../../stores/useMangoStore' import { Table, Td, Th, TrBody, TrHead } from '../TableElements' import { isEmpty } from 'lodash' import { useTranslation } from 'next-i18next' import Select from '../Select' 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/outline' 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('BTC') 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 [showHours, setShowHours] = useState(false) const mangoAccountPk = useMemo(() => { return mangoAccount.publicKey.toString() }, [mangoAccount]) const exportFundingDataToCSV = () => { const assets = Object.keys(hourlyFunding) let dataToExport = [] 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 = [] 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 () => { await 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 = [] 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 } else { dailyFunding.push({ time: d.time, funding: d.total_funding, }) } }) if (dailyFunding.length <= 1) { const chartFunding = [] hourlyFunding[selectedAsset].forEach((a) => { chartFunding.push({ funding: a.total_funding, time: a.time, }) }) setShowHours(true) setChartData(chartFunding.reverse()) } else { setShowHours(false) 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], index) => { 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?.toFixed(6)}` : '-'}
)} <> {!isEmpty(hourlyFunding) && !loadHourlyStats ? ( <>
{t('history')}
{Object.keys(hourlyFunding).map((token: string) => (
setSelectedAsset(token)} key={token} > {token}-PERP
))}
{selectedAsset && chartData.length > 0 ? (
x && `${x?.toLocaleString(undefined, { maximumFractionDigits: 6, })} USDC` } tickFormat={handleDustTicks} type="bar" yAxisWidth={70} />
) : null}
{paginatedData.length ? ( {paginatedData.map((stat, index) => { // @ts-ignore const utc = dayjs.utc(stat.time).format() return ( ) })}
{t('time')} {t('funding')} (USDC)
{dayjs(utc).format('DD/MM/YY, h:mma')} {stat.total_funding.toFixed( QUOTE_DECIMALS + 1 )}
) : (
{t('no-funding')}
)}
) : loadHourlyStats ? (
) : null}
) : (
{t('connect-wallet')}
)} ) } export default AccountFunding