diff --git a/common/calculate-cpmm.ts b/common/calculate-cpmm.ts index 9e544a4e..ed4e0120 100644 --- a/common/calculate-cpmm.ts +++ b/common/calculate-cpmm.ts @@ -88,6 +88,14 @@ export function calculateCpmmSale( return { saleValue, newPool } } +export function getCpmmProbabilityAfterSale( + contract: FullContract, + bet: Bet +) { + const { newPool } = calculateCpmmSale(contract, bet) + return getCpmmProbability(newPool) +} + export function calculateFixedPayout( contract: FullContract, bet: Bet, diff --git a/common/calculate.ts b/common/calculate.ts index b10906b2..e16c0ac4 100644 --- a/common/calculate.ts +++ b/common/calculate.ts @@ -3,6 +3,7 @@ import { calculateCpmmShares, getCpmmProbability, getCpmmProbabilityAfterBet, + getCpmmProbabilityAfterSale, } from './calculate-cpmm' import { calculateDpmPayoutAfterCorrectBet, @@ -10,6 +11,7 @@ import { getDpmOutcomeProbability, getDpmProbability, getDpmProbabilityAfterBet, + getDpmProbabilityAfterSale, } from './calculate-dpm' import { Binary, Contract, CPMM, DPM, FullContract } from './contract' import { FEES } from './fees' @@ -20,6 +22,14 @@ export function getProbability(contract: FullContract) { : getDpmProbability(contract.totalShares) } +export function getInitialProbability( + contract: FullContract +) { + return contract.mechanism === 'cpmm-1' + ? getCpmmProbability(contract.liquidity[contract.creatorId]) + : getDpmProbability(contract.phantomShares ?? contract.totalShares) +} + export function getOutcomeProbability(contract: Contract, outcome: string) { return contract.mechanism === 'cpmm-1' ? getCpmmProbability(contract.pool) @@ -56,6 +66,19 @@ export function calculatePayoutAfterCorrectBet(contract: Contract, bet: Bet) { : calculateDpmPayoutAfterCorrectBet(contract, bet) } +export function getProbabilityAfterSale( + contract: Contract, + outcome: string, + shares: number +) { + return contract.mechanism === 'cpmm-1' + ? getCpmmProbabilityAfterSale( + contract as FullContract, + { shares, outcome } as Bet + ) + : getDpmProbabilityAfterSale(contract.totalShares, outcome, shares) +} + export const deductFees = (betAmount: number, winnings: number) => { return winnings > betAmount ? betAmount + (1 - FEES) * (winnings - betAmount) diff --git a/web/components/bet-row.tsx b/web/components/bet-row.tsx index 60967e25..f766e51d 100644 --- a/web/components/bet-row.tsx +++ b/web/components/bet-row.tsx @@ -1,14 +1,15 @@ import clsx from 'clsx' import { Fragment, useState } from 'react' import { Dialog, Transition } from '@headlessui/react' -import { Contract } from '../lib/firebase/contracts' + import { BetPanel } from './bet-panel' import { Row } from './layout/row' import { YesNoSelector } from './yes-no-selector' +import { Binary, CPMM, DPM, FullContract } from '../../common/contract' // Inline version of a bet panel. Opens BetPanel in a new modal. export default function BetRow(props: { - contract: Contract + contract: FullContract className?: string labelClassName?: string }) { diff --git a/web/components/bets-list.tsx b/web/components/bets-list.tsx index 1a975052..71a1118f 100644 --- a/web/components/bets-list.tsx +++ b/web/components/bets-list.tsx @@ -25,9 +25,6 @@ import { UserLink } from './user-page' import { calculateDpmPayout, calculateDpmSaleAmount, - getDpmOutcomeProbability, - getDpmProbability, - getDpmProbabilityAfterSale, resolvedDpmPayout, } from '../../common/calculate-dpm' import { sellBet } from '../lib/firebase/api-call' @@ -36,6 +33,11 @@ import { OutcomeLabel, YesLabel, NoLabel } from './outcome-label' import { filterDefined } from '../../common/util/array' import { LoadingIndicator } from './loading-indicator' import { SiteLink } from './site-link' +import { + getOutcomeProbability, + getProbability, + getProbabilityAfterSale, +} from '../../common/calculate' type BetSort = 'newest' | 'profit' | 'settled' | 'value' @@ -385,7 +387,7 @@ export function MyBetsSummary(props: { <> Payout at{' '} - {formatPercent(getDpmProbability(contract.totalShares))} + {formatPercent(getProbability(contract))} ) : ( @@ -519,16 +521,12 @@ function SellButton(props: { contract: Contract; bet: Bet }) { const [isSubmitting, setIsSubmitting] = useState(false) - const initialProb = getDpmOutcomeProbability( - contract.totalShares, + const initialProb = getOutcomeProbability( + contract, outcome === 'NO' ? 'YES' : outcome ) - const outcomeProb = getDpmProbabilityAfterSale( - contract.totalShares, - outcome, - shares - ) + const outcomeProb = getProbabilityAfterSale(contract, outcome, shares) const saleAmount = calculateDpmSaleAmount(contract, bet) diff --git a/web/components/contract-prob-graph.tsx b/web/components/contract-prob-graph.tsx index e7a0545d..727927b5 100644 --- a/web/components/contract-prob-graph.tsx +++ b/web/components/contract-prob-graph.tsx @@ -2,20 +2,21 @@ import { DatumValue } from '@nivo/core' import { ResponsiveLine } from '@nivo/line' import dayjs from 'dayjs' import { Bet } from '../../common/bet' -import { getDpmProbability } from '../../common/calculate-dpm' +import { getInitialProbability } from '../../common/calculate' +import { Binary, CPMM, DPM, FullContract } from '../../common/contract' import { useBetsWithoutAntes } from '../hooks/use-bets' import { useWindowSize } from '../hooks/use-window-size' -import { Contract } from '../lib/firebase/contracts' -export function ContractProbGraph(props: { contract: Contract; bets: Bet[] }) { +export function ContractProbGraph(props: { + contract: FullContract + bets: Bet[] +}) { const { contract } = props - const { phantomShares, resolutionTime, closeTime } = contract + const { resolutionTime, closeTime } = contract const bets = useBetsWithoutAntes(contract, props.bets) - const startProb = getDpmProbability( - phantomShares as { [outcome: string]: number } - ) + const startProb = getInitialProbability(contract) const times = bets ? [contract.createdTime, ...bets.map((bet) => bet.createdTime)].map( diff --git a/web/components/contracts-list.tsx b/web/components/contracts-list.tsx index d64df8d8..194196da 100644 --- a/web/components/contracts-list.tsx +++ b/web/components/contracts-list.tsx @@ -13,6 +13,7 @@ import { Col } from './layout/col' import { SiteLink } from './site-link' import { ContractCard } from './contract-card' import { Sort, useQueryAndSortParams } from '../hooks/use-sort-and-query-params' +import { Answer } from '../../common/answer' export function ContractsGrid(props: { contracts: Contract[] @@ -217,7 +218,11 @@ export function SearchableGrid(props: { check(c.creatorName) || check(c.creatorUsername) || check(c.lowercaseTags.map((tag) => `#${tag}`).join(' ')) || - check((c.answers ?? []).map((answer) => answer.text).join(' ')) + check( + ((c as any).answers ?? []) + .map((answer: Answer) => answer.text) + .join(' ') + ) ) if (sort === 'newest' || sort === 'all') { diff --git a/web/components/resolution-panel.tsx b/web/components/resolution-panel.tsx index d1600b9b..b9d8e2dd 100644 --- a/web/components/resolution-panel.tsx +++ b/web/components/resolution-panel.tsx @@ -1,7 +1,6 @@ import clsx from 'clsx' import React, { useEffect, useState } from 'react' -import { Contract } from '../lib/firebase/contracts' import { Col } from './layout/col' import { Title } from './title' import { User } from '../lib/firebase/users' @@ -10,12 +9,13 @@ import { Spacer } from './layout/spacer' import { ResolveConfirmationButton } from './confirmation-button' import { resolveMarket } from '../lib/firebase/api-call' import { ProbabilitySelector } from './probability-selector' -import { getDpmProbability } from '../../common/calculate-dpm' import { CREATOR_FEE } from '../../common/fees' +import { getProbability } from '../../common/calculate' +import { Binary, CPMM, DPM, FullContract } from '../../common/contract' export function ResolutionPanel(props: { creator: User - contract: Contract + contract: FullContract className?: string }) { useEffect(() => { @@ -29,9 +29,7 @@ export function ResolutionPanel(props: { 'YES' | 'NO' | 'MKT' | 'CANCEL' | undefined >() - const [prob, setProb] = useState( - getDpmProbability(contract.totalShares) * 100 - ) + const [prob, setProb] = useState(getProbability(contract) * 100) const [isSubmitting, setIsSubmitting] = useState(false) const [error, setError] = useState(undefined) diff --git a/web/pages/api/v0/_types.ts b/web/pages/api/v0/_types.ts index beb520ec..2eadf8dc 100644 --- a/web/pages/api/v0/_types.ts +++ b/web/pages/api/v0/_types.ts @@ -1,7 +1,7 @@ import { Bet } from '../../../../common/bet' import { getDpmProbability } from '../../../../common/calculate-dpm' import { Comment } from '../../../../common/comment' -import { Contract } from '../../../../common/contract' +import { DPM, FullContract } from '../../../../common/contract' export type LiteMarket = { // Unique identifer for this market @@ -56,7 +56,7 @@ export function toLiteMarket({ isResolved, resolution, resolutionTime, -}: Contract): LiteMarket { +}: FullContract): LiteMarket { return { id, creatorUsername, diff --git a/web/pages/make-predictions.tsx b/web/pages/make-predictions.tsx index 5c60b284..c3d42d6d 100644 --- a/web/pages/make-predictions.tsx +++ b/web/pages/make-predictions.tsx @@ -3,11 +3,12 @@ import dayjs from 'dayjs' import Link from 'next/link' import { useState } from 'react' import Textarea from 'react-expanding-textarea' -import { getDpmProbability } from '../../common/calculate-dpm' + +import { getProbability } from '../../common/calculate' +import { Binary, CPMM, DPM, FullContract } from '../../common/contract' import { parseWordsAsTags } from '../../common/util/parse' import { AmountInput } from '../components/amount-input' import { InfoTooltip } from '../components/info-tooltip' - import { Col } from '../components/layout/col' import { Row } from '../components/layout/row' import { Spacer } from '../components/layout/spacer' @@ -16,7 +17,7 @@ import { Page } from '../components/page' import { Title } from '../components/title' import { useUser } from '../hooks/use-user' import { createContract } from '../lib/firebase/api-call' -import { Contract, contractPath } from '../lib/firebase/contracts' +import { contractPath } from '../lib/firebase/contracts' type Prediction = { question: string @@ -25,8 +26,8 @@ type Prediction = { createdUrl?: string } -function toPrediction(contract: Contract): Prediction { - const startProb = getDpmProbability(contract.totalShares) +function toPrediction(contract: FullContract): Prediction { + const startProb = getProbability(contract) return { question: contract.question, description: contract.description, @@ -101,7 +102,9 @@ export default function MakePredictions() { const [description, setDescription] = useState('') const [tags, setTags] = useState('') const [isSubmitting, setIsSubmitting] = useState(false) - const [createdContracts, setCreatedContracts] = useState([]) + const [createdContracts, setCreatedContracts] = useState< + FullContract[] + >([]) const [ante, setAnte] = useState(100) const [anteError, setAnteError] = useState()