import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react' import dayjs from 'dayjs' import { MedalIcon } from './icons' import { useTranslation } from 'next-i18next' import { abbreviateAddress, usdFormatter } from '../utils' import { ChevronRightIcon } from '@heroicons/react/solid' import ProfileImage from './ProfileImage' import { useRouter } from 'next/router' import { PublicKey } from '@solana/web3.js' import { notify } from 'utils/notifications' const utc = require('dayjs/plugin/utc') dayjs.extend(utc) const formatLeaderboardData = async (leaderboard) => { const walletPks = leaderboard.map((u) => u.wallet_pk) const profileDetailsResponse = await fetch( `https://mango-transaction-log.herokuapp.com/v3/user-data/multiple-profile-details?wallet-pks=${walletPks.toString()}` ) const parsedProfileDetailsResponse = await profileDetailsResponse.json() const leaderboardData = [] as any[] for (const item of leaderboard) { const profileDetails = parsedProfileDetailsResponse[item.wallet_pk] leaderboardData.push({ ...item, profile: profileDetails ? profileDetails : null, }) } return leaderboardData } const LeaderboardTable = ({ range = '29' }) => { const { t } = useTranslation('common') const [pnlLeaderboardData, setPnlLeaderboardData] = useState([]) const [perpPnlLeaderboardData, setPerpPnlLeaderboardData] = useState( [] ) const [spotPnlLeaderboardData, setSpotPnlLeaderboardData] = useState( [] ) const [leaderboardType, setLeaderboardType] = useState('total-pnl') const [loading, setLoading] = useState(false) const fetchPnlLeaderboard = async () => { setLoading(true) try { const response = await fetch( `https://mango-transaction-log.herokuapp.com/v3/stats/pnl-leaderboard?start-date=${dayjs() .utc() .hour(0) .minute(0) .subtract(parseInt(range), 'day') .add(1, 'hour') .format('YYYY-MM-DDThh:00:00')}` ) const parsedResponse = await response.json() const leaderboardData = await formatLeaderboardData(parsedResponse) setPnlLeaderboardData(leaderboardData) setLoading(false) } catch { notify({ type: 'error', title: t('fetch-leaderboard-fail') }) setLoading(false) } } const fetchPerpPnlLeaderboard = useCallback(async () => { setLoading(true) try { const response = await fetch( `https://mango-transaction-log.herokuapp.com/v3/stats/perp-pnl-leaderboard?start-date=${dayjs() .utc() .hour(0) .minute(0) .subtract(parseInt(range), 'day') .add(1, 'hour') .format('YYYY-MM-DDThh:00:00')}` ) const parsedResponse = await response.json() const leaderboardData = await formatLeaderboardData(parsedResponse) setPerpPnlLeaderboardData(leaderboardData) setLoading(false) } catch { notify({ type: 'error', title: t('fetch-leaderboard-fail') }) setLoading(false) } }, [range, t]) const fetchSpotPnlLeaderboard = useCallback(async () => { setLoading(true) const response = await fetch( `https://mango-transaction-log.herokuapp.com/v3/stats/spot-pnl-leaderboard?start-date=${dayjs() .hour(0) .minute(0) .utc() .subtract(parseInt(range), 'day') .format('YYYY-MM-DDThh:00:00')}` ) const parsedResponse = await response.json() const leaderboardData = await formatLeaderboardData(parsedResponse) setSpotPnlLeaderboardData(leaderboardData) setLoading(false) }, [range]) useEffect(() => { if (leaderboardType === 'total-pnl') { fetchPnlLeaderboard() } else if (leaderboardType === 'futures-only') { fetchPerpPnlLeaderboard() } else { fetchSpotPnlLeaderboard() } }, [range, leaderboardType]) useEffect(() => { fetchPerpPnlLeaderboard() fetchSpotPnlLeaderboard() }, []) const leaderboardData = useMemo( () => leaderboardType === 'total-pnl' ? pnlLeaderboardData : leaderboardType === 'futures-only' ? perpPnlLeaderboardData : spotPnlLeaderboardData, [ leaderboardType, pnlLeaderboardData, perpPnlLeaderboardData, spotPnlLeaderboardData, ] ) return (
{!loading ? (
{leaderboardData.map((acc, i) => ( ))}
) : (
)}
) } export default LeaderboardTable const AccountCard = ({ rank, acc, rawPnl, profile, pnl }) => { const router = useRouter() const medalColors = rank === 1 ? { darkest: '#E4AF11', dark: '#F2C94C', light: '#FFCF40', lightest: '#FDE877', } : rank === 2 ? { darkest: '#B8B8B8', dark: '#C0C0C0', light: '#C7C7C7', lightest: '#D8D6D6', } : { darkest: '#CD7F32', dark: '#E5994E', light: '#DBA36B', lightest: '#EFBF8D', } return (
{profile ? ( ) : null}

{rank}

{rank < 4 ? ( ) : null}

{abbreviateAddress(new PublicKey(acc))}

0 ? 'text-th-green' : 'text-th-red' }`} > {pnl}
) } const LeaderboardTypeButton = ({ leaderboardType, setLeaderboardType, range, icon, label, }: { leaderboardType: string setLeaderboardType: (x) => void range: string icon?: ReactNode label: string }) => { const { t } = useTranslation('common') return ( ) }