diff --git a/web/hooks/use-contracts.ts b/web/hooks/use-contracts.ts index bec304a9..c71f5cb8 100644 --- a/web/hooks/use-contracts.ts +++ b/web/hooks/use-contracts.ts @@ -1,10 +1,9 @@ import _ from 'lodash' import { useEffect, useState } from 'react' -import { Bet, listenForRecentBets } from '../lib/firebase/bets' import { - computeHotContracts, Contract, listenForContracts, + listenForHotContracts, } from '../lib/firebase/contracts' export const useContracts = () => { @@ -18,14 +17,9 @@ export const useContracts = () => { } export const useHotContracts = () => { - const [recentBets, setRecentBets] = useState('loading') + const [hotContracts, setHotContracts] = useState() - useEffect(() => { - const oneDay = 1000 * 60 * 60 * 24 - return listenForRecentBets(oneDay, setRecentBets) - }, []) + useEffect(() => listenForHotContracts(setHotContracts), []) - if (recentBets === 'loading') return 'loading' - - return computeHotContracts(recentBets) + return hotContracts } diff --git a/web/lib/firebase/bets.ts b/web/lib/firebase/bets.ts index 818c09bc..9fa67e56 100644 --- a/web/lib/firebase/bets.ts +++ b/web/lib/firebase/bets.ts @@ -4,7 +4,6 @@ import { query, onSnapshot, where, - getDocs, } from 'firebase/firestore' import _ from 'lodash' import { db } from './init' @@ -64,34 +63,3 @@ export function listenForUserBets( setBets(bets) }) } - -export function listenForRecentBets( - timePeriodMs: number, - setBets: (bets: Bet[]) => void -) { - const recentQuery = query( - collectionGroup(db, 'bets'), - where('createdTime', '>', Date.now() - timePeriodMs) - ) - return onSnapshot(recentQuery, (snap) => { - const bets = snap.docs.map((doc) => doc.data() as Bet) - - bets.sort((bet1, bet2) => bet1.createdTime - bet2.createdTime) - - setBets(bets) - }) -} - -export async function getRecentBets(timePeriodMs: number) { - const recentQuery = query( - collectionGroup(db, 'bets'), - where('createdTime', '>', Date.now() - timePeriodMs) - ) - - const snapshot = await getDocs(recentQuery) - const bets = snapshot.docs.map((doc) => doc.data() as Bet) - - bets.sort((bet1, bet2) => bet1.createdTime - bet2.createdTime) - - return bets -} diff --git a/web/lib/firebase/contracts.ts b/web/lib/firebase/contracts.ts index 1a51b9dc..90a0c784 100644 --- a/web/lib/firebase/contracts.ts +++ b/web/lib/firebase/contracts.ts @@ -12,10 +12,10 @@ import { orderBy, getDoc, updateDoc, + limit, } from 'firebase/firestore' import dayjs from 'dayjs' -import { Bet, getRecentBets } from './bets' -import _ from 'lodash' +import { getValues, listenForValues } from './utils' export type Contract = { id: string @@ -145,16 +145,19 @@ export function listenForContract( }) } -export function computeHotContracts(recentBets: Bet[]) { - const contractBets = _.groupBy(recentBets, (bet) => bet.contractId) - const hotContractIds = _.sortBy(Object.keys(contractBets), (contractId) => - _.sumBy(contractBets[contractId], (bet) => -1 * bet.amount) - ) - return hotContractIds +const hotContractsQuery = query( + contractCollection, + where('isResolved', '==', false), + orderBy('volume24Hours', 'desc'), + limit(4) +) + +export function listenForHotContracts( + setHotContracts: (contracts: Contract[]) => void +) { + return listenForValues(hotContractsQuery, setHotContracts) } -export async function getHotContracts() { - const oneDay = 1000 * 60 * 60 * 24 - const recentBets = await getRecentBets(oneDay) - return computeHotContracts(recentBets) +export function getHotContracts() { + return getValues(hotContractsQuery) } diff --git a/web/lib/firebase/utils.ts b/web/lib/firebase/utils.ts new file mode 100644 index 00000000..6af380c7 --- /dev/null +++ b/web/lib/firebase/utils.ts @@ -0,0 +1,39 @@ +import { db } from './init' +import { + doc, + getDoc, + getDocs, + onSnapshot, + Query, + DocumentReference, +} from 'firebase/firestore' + +export const getValue = async (collectionName: string, docName: string) => { + const snap = await getDoc(doc(db, collectionName, docName)) + return snap.exists() ? (snap.data() as T) : null +} + +export const getValues = async (query: Query) => { + const snap = await getDocs(query) + return snap.docs.map((doc) => doc.data() as T) +} + +export function listenForValue( + docRef: DocumentReference, + setValue: (value: T | null) => void +) { + return onSnapshot(docRef, (snapshot) => { + const value = snapshot.exists() ? (snapshot.data() as T) : null + setValue(value) + }) +} + +export function listenForValues( + query: Query, + setValues: (values: T[]) => void +) { + return onSnapshot(query, (snapshot) => { + const values = snapshot.docs.map((doc) => doc.data() as T) + setValues(values) + }) +} diff --git a/web/pages/index.tsx b/web/pages/index.tsx index c16bb68b..80f9a7d3 100644 --- a/web/pages/index.tsx +++ b/web/pages/index.tsx @@ -1,5 +1,5 @@ import React from 'react' - +import _ from 'lodash' import { useUser } from '../hooks/use-user' import Markets from './markets' import LandingPage from './landing-page' @@ -8,10 +8,9 @@ import { getHotContracts, listAllContracts, } from '../lib/firebase/contracts' -import _ from 'lodash' export async function getStaticProps() { - const [contracts, hotContractIds] = await Promise.all([ + const [contracts, hotContracts] = await Promise.all([ listAllContracts().catch((_) => []), getHotContracts().catch(() => []), ]) @@ -19,26 +18,22 @@ export async function getStaticProps() { return { props: { contracts, - hotContractIds, + hotContracts, }, revalidate: 60, // regenerate after a minute } } -const Home = (props: { contracts: Contract[]; hotContractIds: string[] }) => { +const Home = (props: { contracts: Contract[]; hotContracts: Contract[] }) => { const user = useUser() if (user === undefined) return <> - const { contracts, hotContractIds } = props - const hotContracts = hotContractIds - .map((id) => contracts.find((contract) => contract.id === id) as Contract) - .filter((contract) => !contract.isResolved) - .slice(0, 4) + const { contracts, hotContracts } = props return user ? ( - + ) : ( ) diff --git a/web/pages/markets.tsx b/web/pages/markets.tsx index 6aa30cd0..e03e3b73 100644 --- a/web/pages/markets.tsx +++ b/web/pages/markets.tsx @@ -12,7 +12,7 @@ import { } from '../lib/firebase/contracts' export async function getStaticProps() { - const [contracts, hotContractIds] = await Promise.all([ + const [contracts, hotContracts] = await Promise.all([ listAllContracts().catch((_) => []), getHotContracts().catch(() => []), ]) @@ -20,7 +20,7 @@ export async function getStaticProps() { return { props: { contracts, - hotContractIds, + hotContracts, }, revalidate: 60, // regenerate after a minute @@ -29,29 +29,20 @@ export async function getStaticProps() { export default function Markets(props: { contracts: Contract[] - hotContractIds: string[] + hotContracts: Contract[] }) { const contracts = useContracts() + const hotContracts = useHotContracts() const { query, setQuery, sort, setSort } = useQueryAndSortParams() - const hotContractIds = useHotContracts() - const readyHotContractIds = - hotContractIds === 'loading' ? props.hotContractIds : hotContractIds + const readyHotContracts = hotContracts ?? props.hotContracts const readyContracts = contracts === 'loading' ? props.contracts : contracts - const hotContracts = readyHotContractIds - .map( - (hotId) => - _.find(readyContracts, (contract) => contract.id === hotId) as Contract - ) - .filter((contract) => !contract.isResolved) - .slice(0, 4) - return (
- <ContractsGrid contracts={hotContracts} /> + <ContractsGrid contracts={readyHotContracts} /> </div> <Spacer h={10} />