import { Bet } from 'common/bet' import { resolvedPayout } from 'common/calculate' import { Contract } from 'common/contract' import { formatMoney } from 'common/util/format' import { groupBy, mapValues, sumBy, sortBy, keyBy } from 'lodash' import { memo } from 'react' import { useComments } from 'web/hooks/use-comments' import { FeedBet } from '../feed/feed-bets' import { FeedComment } from '../feed/feed-comments' import { Spacer } from '../layout/spacer' import { Leaderboard } from '../leaderboard' import { Title } from '../title' import { BETTORS } from 'common/user' export const ContractLeaderboard = memo(function ContractLeaderboard(props: { contract: Contract bets: Bet[] }) { const { contract, bets } = props // Create a map of userIds to total profits (including sales) const openBets = bets.filter((bet) => !bet.isSold && !bet.sale) const betsByUser = groupBy(openBets, 'userId') const userProfits = mapValues(betsByUser, (bets) => { return { name: bets[0].userName, username: bets[0].userUsername, avatarUrl: bets[0].userAvatarUrl, total: sumBy(bets, (bet) => resolvedPayout(contract, bet) - bet.amount), } }) // Find the 5 users with the most profits const top5 = Object.values(userProfits) .sort((p1, p2) => p2.total - p1.total) .filter((p) => p.total > 0) .slice(0, 5) return top5 && top5.length > 0 ? ( formatMoney(entry.total), }, ]} className="mt-12 max-w-sm" /> ) : null }) export function ContractTopTrades(props: { contract: Contract; bets: Bet[] }) { const { contract, bets } = props // todo: this stuff should be calced in DB at resolve time const comments = useComments(contract.id) const betsById = keyBy(bets, 'id') // If 'id2' is the sale of 'id1', both are logged with (id2 - id1) of profit // Otherwise, we record the profit at resolution time const profitById: Record = {} for (const bet of bets) { if (bet.sale) { const originalBet = betsById[bet.sale.betId] const profit = bet.sale.amount - originalBet.amount profitById[bet.id] = profit profitById[originalBet.id] = profit } else { profitById[bet.id] = resolvedPayout(contract, bet) - bet.amount } } // Now find the betId with the highest profit const topBetId = sortBy(bets, (b) => -profitById[b.id])[0]?.id const topBettor = betsById[topBetId]?.userName // And also the comment with the highest profit const topComment = sortBy(comments, (c) => c.betId && -profitById[c.betId])[0] return (
{topComment && profitById[topComment.id] > 0 && ( <> <div className="relative flex items-start space-x-3 rounded-md bg-gray-50 px-2 py-4"> <FeedComment contract={contract} comment={topComment} /> </div> <Spacer h={16} /> </> )} {/* If they're the same, only show the comment; otherwise show both */} {topBettor && topBetId !== topComment?.betId && profitById[topBetId] > 0 && ( <> <Title text="💸 Best bet" className="!mt-0" /> <div className="relative flex items-start space-x-3 rounded-md bg-gray-50 px-2 py-4"> <FeedBet contract={contract} bet={betsById[topBetId]} /> </div> <div className="mt-2 ml-2 text-sm text-gray-500"> {topBettor} made {formatMoney(profitById[topBetId] || 0)}! </div> </> )} </div> ) }