diff --git a/web/components/bet-panel.tsx b/web/components/bet-panel.tsx
index afb5bfd2..bcb18b47 100644
--- a/web/components/bet-panel.tsx
+++ b/web/components/bet-panel.tsx
@@ -64,7 +64,7 @@ export function BetPanel(props: { contract: Contract; className?: string }) {
return (
diff --git a/web/components/contract-overview.tsx b/web/components/contract-overview.tsx
index 41fea05b..659e62f9 100644
--- a/web/components/contract-overview.tsx
+++ b/web/components/contract-overview.tsx
@@ -1,51 +1,22 @@
import React from 'react'
-import { Line } from 'react-chartjs-2'
-import {
- CategoryScale,
- Chart,
- LinearScale,
- PointElement,
- LineElement,
- Title,
- Tooltip,
- Legend,
-} from 'chart.js'
import { Contract } from '../lib/firebase/contracts'
import { Col } from './layout/col'
import { Row } from './layout/row'
import { Spacer } from './layout/spacer'
import { formatWithCommas } from '../lib/util/format'
+import { ContractProbGraph } from './contract-prob-graph'
-// Auto import doesn't work for some reason...
-// So we manually register ChartJS components instead:
-Chart.register(
- CategoryScale,
- LinearScale,
- PointElement,
- LineElement,
- Title,
- Tooltip,
- Legend
-)
-const chartData = {
- labels: Array.from({ length: 0 }, (_, i) => i + 1),
- datasets: [
- {
- label: 'Implied probability',
- data: [],
- borderColor: 'rgb(75, 192, 192)',
- },
- ],
-}
-
-export const ContractOverview = (props: { contract: Contract }) => {
- const { contract } = props
+export const ContractOverview = (props: {
+ contract: Contract
+ className?: string
+}) => {
+ const { contract, className } = props
const { pot, seedAmounts } = contract
const volume = pot.YES + pot.NO - seedAmounts.YES - seedAmounts.NO
return (
-
+
{contract.question}
@@ -53,12 +24,14 @@ export const ContractOverview = (props: { contract: Contract }) => {
•
Dec 9
•
- {formatWithCommas(volume)} volume
+
+ {formatWithCommas(volume)} volume
+
-
+
diff --git a/web/components/contract-prob-graph.tsx b/web/components/contract-prob-graph.tsx
new file mode 100644
index 00000000..ad05ec6d
--- /dev/null
+++ b/web/components/contract-prob-graph.tsx
@@ -0,0 +1,52 @@
+import { Line } from 'react-chartjs-2'
+import {
+ CategoryScale,
+ Chart,
+ LinearScale,
+ PointElement,
+ LineElement,
+ Title,
+ Tooltip,
+ Legend,
+} from 'chart.js'
+
+import { useBets } from '../hooks/use-bets'
+import { Contract } from '../lib/firebase/contracts'
+
+// Auto import doesn't work for some reason...
+// So we manually register ChartJS components instead:
+Chart.register(
+ CategoryScale,
+ LinearScale,
+ PointElement,
+ LineElement,
+ Title,
+ Tooltip,
+ Legend
+)
+
+export function ContractProbGraph(props: { contract: Contract }) {
+ const { contract } = props
+ const { id, seedAmounts } = contract
+
+ let bets = useBets(id)
+ if (bets === 'loading') bets = []
+
+ const seedProb =
+ seedAmounts.YES ** 2 / (seedAmounts.YES ** 2 + seedAmounts.NO ** 2)
+
+ const probs = [seedProb, ...bets.map((bet) => bet.probAfter)]
+
+ const chartData = {
+ labels: Array.from({ length: probs.length }, (_, i) => i + 1),
+ datasets: [
+ {
+ label: 'Implied probability',
+ data: probs,
+ borderColor: 'rgb(75, 192, 192)',
+ },
+ ],
+ }
+
+ return
+}
diff --git a/web/hooks/use-bets.ts b/web/hooks/use-bets.ts
new file mode 100644
index 00000000..0a35ba53
--- /dev/null
+++ b/web/hooks/use-bets.ts
@@ -0,0 +1,12 @@
+import { useEffect, useState } from 'react'
+import { Bet, listenForBets } from '../lib/firebase/bets'
+
+export const useBets = (contractId: string) => {
+ const [bets, setBets] = useState('loading')
+
+ useEffect(() => {
+ if (contractId) return listenForBets(contractId, setBets)
+ }, [contractId])
+
+ return bets
+}
diff --git a/web/lib/firebase/bets.ts b/web/lib/firebase/bets.ts
index dbfd6f2b..79036c44 100644
--- a/web/lib/firebase/bets.ts
+++ b/web/lib/firebase/bets.ts
@@ -1,22 +1,32 @@
-import { doc, setDoc } from 'firebase/firestore'
+import { collection, onSnapshot } from 'firebase/firestore'
import { db } from './init'
export type Bet = {
id: string
userId: string
contractId: string
-
- amount: number // Amount of USD bid
+ amount: number // Amount of bet
outcome: 'YES' | 'NO' // Chosen outcome
-
- // Calculate and replace these on server?
- createdTime: number
dpmWeight: number // Dynamic Parimutuel weight
+ probBefore: number
+ probAverage: number
+ probAfter: number
+ createdTime: number
}
-// Push bet to Firestore
-// TODO: Should bets be subcollections under its contract?
-export async function saveBet(bet: Bet) {
- const docRef = doc(db, 'contracts', bet.contractId, 'bets', bet.id)
- await setDoc(docRef, bet)
+function getBetsCollection(contractId: string) {
+ return collection(db, 'contracts', contractId, 'bets')
+}
+
+export function listenForBets(
+ contractId: string,
+ setBets: (bets: Bet[]) => void
+) {
+ return onSnapshot(getBetsCollection(contractId), (snap) => {
+ const bets = snap.docs.map((doc) => doc.data() as Bet)
+
+ bets.sort((bet1, bet2) => bet1.createdTime - bet2.createdTime)
+
+ setBets(bets)
+ })
}
diff --git a/web/pages/contract/[contractId].tsx b/web/pages/contract/[contractId].tsx
index bcde85fa..365a5a77 100644
--- a/web/pages/contract/[contractId].tsx
+++ b/web/pages/contract/[contractId].tsx
@@ -24,15 +24,13 @@ export default function ContractPage() {
)
}