diff --git a/common/antes.ts b/common/antes.ts
index c396edad..d36ef584 100644
--- a/common/antes.ts
+++ b/common/antes.ts
@@ -80,7 +80,7 @@ export function getFreeAnswerAnte(
amount,
shares,
outcome: '0',
- probBefore: 1,
+ probBefore: 0,
probAfter: 1,
createdTime,
isAnte: true,
diff --git a/common/contract.ts b/common/contract.ts
index c977fdff..17c4918e 100644
--- a/common/contract.ts
+++ b/common/contract.ts
@@ -13,8 +13,8 @@ export type Contract = {
lowercaseTags: string[]
visibility: 'public' | 'unlisted'
- outcomeType: 'BINARY' | 'MULTI'
- outcomes?: 'FREE_ANSWER' | string[]
+ outcomeType: 'BINARY' | 'MULTI' | 'FREE_RESPONSE'
+ multiOutcomes?: string[] // Used for outcomeType 'MULTI'.
mechanism: 'dpm-2'
phantomShares?: { [outcome: string]: number }
@@ -34,3 +34,5 @@ export type Contract = {
volume24Hours: number
volume7Days: number
}
+
+export type outcomeType = 'BINARY' | 'MULTI' | 'FREE_RESPONSE'
diff --git a/common/new-contract.ts b/common/new-contract.ts
index c7b56c90..263877f1 100644
--- a/common/new-contract.ts
+++ b/common/new-contract.ts
@@ -1,5 +1,5 @@
import { calcStartPool } from './antes'
-import { Contract } from './contract'
+import { Contract, outcomeType } from './contract'
import { User } from './user'
import { parseTags } from './util/parse'
import { removeUndefinedProps } from './util/object'
@@ -9,7 +9,7 @@ export function getNewContract(
slug: string,
creator: User,
question: string,
- outcomeType: 'BINARY' | 'MULTI',
+ outcomeType: outcomeType,
description: string,
initialProb: number,
ante: number,
@@ -64,7 +64,6 @@ const getBinaryProps = (initialProb: number, ante: number) => {
pool: { YES: poolYes, NO: poolNo },
totalShares: { YES: sharesYes, NO: sharesNo },
totalBets: { YES: poolYes, NO: poolNo },
- outcomes: undefined,
}
}
@@ -73,8 +72,6 @@ const getFreeAnswerProps = (ante: number) => {
pool: { '0': ante },
totalShares: { '0': ante },
totalBets: { '0': ante },
- phantomShares: undefined,
- outcomes: 'FREE_ANSWER' as const,
}
}
diff --git a/functions/src/create-answer.ts b/functions/src/create-answer.ts
index 1b6d5f2f..6c28b245 100644
--- a/functions/src/create-answer.ts
+++ b/functions/src/create-answer.ts
@@ -44,13 +44,10 @@ export const createAnswer = functions.runWith({ minInstances: 1 }).https.onCall(
return { status: 'error', message: 'Invalid contract' }
const contract = contractSnap.data() as Contract
- if (
- contract.outcomeType !== 'MULTI' ||
- contract.outcomes !== 'FREE_ANSWER'
- )
+ if (contract.outcomeType !== 'FREE_RESPONSE')
return {
status: 'error',
- message: 'Requires a multi, free answer contract',
+ message: 'Requires a free response contract',
}
const { closeTime } = contract
diff --git a/functions/src/create-contract.ts b/functions/src/create-contract.ts
index 18042768..bb78f134 100644
--- a/functions/src/create-contract.ts
+++ b/functions/src/create-contract.ts
@@ -2,7 +2,7 @@ import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
import { chargeUser, getUser } from './utils'
-import { Contract } from '../../common/contract'
+import { Contract, outcomeType } from '../../common/contract'
import { slugify } from '../../common/util/slugify'
import { randomString } from '../../common/util/random'
import { getNewContract } from '../../common/new-contract'
@@ -19,7 +19,7 @@ export const createContract = functions
async (
data: {
question: string
- outcomeType: 'BINARY' | 'MULTI'
+ outcomeType: outcomeType
description: string
initialProb: number
ante: number
@@ -40,7 +40,7 @@ export const createContract = functions
return { status: 'error', message: 'Missing question field' }
let outcomeType = data.outcomeType ?? 'BINARY'
- if (outcomeType !== 'BINARY' && outcomeType !== 'MULTI')
+ if (!['BINARY', 'MULTI', 'FREE_RESPONSE'].includes(outcomeType))
return { status: 'error', message: 'Invalid outcomeType' }
if (
@@ -106,7 +106,7 @@ export const createContract = functions
)
await yesBetDoc.set(yesBet)
await noBetDoc.set(noBet)
- } else if (outcomeType === 'MULTI') {
+ } else if (outcomeType === 'FREE_RESPONSE') {
const noneAnswerDoc = firestore
.collection(`contracts/${contract.id}/answers`)
.doc('0')
diff --git a/functions/src/place-bet.ts b/functions/src/place-bet.ts
index 3be51790..e37dc12c 100644
--- a/functions/src/place-bet.ts
+++ b/functions/src/place-bet.ts
@@ -42,12 +42,11 @@ export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
return { status: 'error', message: 'Invalid contract' }
const contract = contractSnap.data() as Contract
- const { closeTime, outcomes } = contract
+ const { closeTime, outcomeType } = contract
if (closeTime && Date.now() > closeTime)
return { status: 'error', message: 'Trading is closed' }
- const isFreeAnswer = outcomes === 'FREE_ANSWER'
- if (isFreeAnswer) {
+ if (outcomeType === 'FREE_RESPONSE') {
const answerSnap = await transaction.get(
contractDoc.collection('answers').doc(outcome)
)
@@ -60,21 +59,15 @@ export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
.doc()
const { newBet, newPool, newTotalShares, newTotalBets, newBalance } =
- isFreeAnswer
- ? getNewMultiBetInfo(
- user,
- outcome,
- amount,
- contract as any,
- newBetDoc.id
- )
- : getNewBinaryBetInfo(
+ outcomeType === 'BINARY'
+ ? getNewBinaryBetInfo(
user,
outcome as 'YES' | 'NO',
amount,
contract,
newBetDoc.id
)
+ : getNewMultiBetInfo(user, outcome, amount, contract, newBetDoc.id)
transaction.create(newBetDoc, newBet)
transaction.update(contractDoc, {
diff --git a/functions/src/resolve-market.ts b/functions/src/resolve-market.ts
index 201087d2..d0b6d1da 100644
--- a/functions/src/resolve-market.ts
+++ b/functions/src/resolve-market.ts
@@ -35,7 +35,7 @@ export const resolveMarket = functions
if (outcomeType === 'BINARY') {
if (!['YES', 'NO', 'MKT', 'CANCEL'].includes(outcome))
return { status: 'error', message: 'Invalid outcome' }
- } else if (outcomeType === 'MULTI') {
+ } else if (outcomeType === 'FREE_RESPONSE') {
if (outcome !== 'CANCEL' && isNaN(+outcome))
return { status: 'error', message: 'Invalid outcome' }
} else {
diff --git a/web/pages/[username]/[contractSlug].tsx b/web/pages/[username]/[contractSlug].tsx
index fec1880d..98c314a4 100644
--- a/web/pages/[username]/[contractSlug].tsx
+++ b/web/pages/[username]/[contractSlug].tsx
@@ -42,7 +42,7 @@ export async function getStaticProps(props: {
const [bets, comments, answers] = await Promise.all([
contractId ? listAllBets(contractId) : [],
contractId ? listAllComments(contractId) : [],
- contractId && contract.outcomes === 'FREE_ANSWER'
+ contractId && contract.outcomeType === 'FREE_RESPONSE'
? listAllAnswers(contractId)
: [],
])
@@ -120,7 +120,7 @@ export default function ContractPage(props: {
comments={comments ?? []}
folds={folds}
>
- {contract.outcomes === 'FREE_ANSWER' && (
+ {contract.outcomeType === 'FREE_RESPONSE' && (
<>
('BINARY')
+ const [outcomeType, setOutcomeType] = useState('BINARY')
const [initialProb, setInitialProb] = useState(50)
const [description, setDescription] = useState('')
const [tagText, setTagText] = useState(tag ?? '')
@@ -143,7 +144,7 @@ export function NewContract(props: { question: string; tag?: string }) {
name="opt"
checked={outcomeType === 'BINARY'}
value="BINARY"
- onChange={(e) => setOutcomeType(e.target.value as 'BINARY')}
+ onChange={() => setOutcomeType('BINARY')}
/>
Yes / No
@@ -153,9 +154,9 @@ export function NewContract(props: { question: string; tag?: string }) {
className="radio"
type="radio"
name="opt"
- checked={outcomeType === 'MULTI'}
- value="MULTI"
- onChange={(e) => setOutcomeType(e.target.value as 'MULTI')}
+ checked={outcomeType === 'FREE_RESPONSE'}
+ value="FREE_RESPONSE"
+ onChange={() => setOutcomeType('FREE_RESPONSE')}
/>
Free response