Remove Contract and Bet type params. Use string type for outcomes.
This commit is contained in:
parent
18376f8a3f
commit
f161661e7e
|
@ -64,7 +64,7 @@ export function getAnteBets(
|
|||
|
||||
export function getFreeAnswerAnte(
|
||||
creator: User,
|
||||
contract: Contract<'MULTI'>,
|
||||
contract: Contract,
|
||||
anteBetId: string
|
||||
) {
|
||||
const { totalBets, totalShares } = contract
|
||||
|
@ -73,7 +73,7 @@ export function getFreeAnswerAnte(
|
|||
|
||||
const { createdTime } = contract
|
||||
|
||||
const anteBet: Bet<'MULTI'> = {
|
||||
const anteBet: Bet = {
|
||||
id: anteBetId,
|
||||
userId: creator.id,
|
||||
contractId: contract.id,
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
export type Bet<outcomeType extends 'BINARY' | 'MULTI' = 'BINARY'> = {
|
||||
export type Bet = {
|
||||
id: string
|
||||
userId: string
|
||||
contractId: string
|
||||
|
||||
amount: number // bet size; negative if SELL bet
|
||||
outcome: {
|
||||
BINARY: 'YES' | 'NO'
|
||||
MULTI: string
|
||||
}[outcomeType]
|
||||
outcome: string
|
||||
shares: number // dynamic parimutuel pool weight; negative if SELL bet
|
||||
|
||||
probBefore: number
|
||||
|
|
|
@ -3,7 +3,8 @@ import { Bet } from './bet'
|
|||
import { Contract } from './contract'
|
||||
import { FEES } from './fees'
|
||||
|
||||
export function getProbability(totalShares: { YES: number; NO: number }) {
|
||||
export function getProbability(totalShares: { [outcome: string]: number }) {
|
||||
// For binary contracts only.
|
||||
return getOutcomeProbability(totalShares, 'YES')
|
||||
}
|
||||
|
||||
|
@ -70,9 +71,9 @@ export function calculateRawShareValue(
|
|||
return currentValue - postSaleValue
|
||||
}
|
||||
|
||||
export function calculateMoneyRatio<T extends 'BINARY' | 'MULTI'>(
|
||||
contract: Contract<T>,
|
||||
bet: Bet<T>,
|
||||
export function calculateMoneyRatio(
|
||||
contract: Contract,
|
||||
bet: Bet,
|
||||
shareValue: number
|
||||
) {
|
||||
const { totalShares, totalBets, pool } = contract
|
||||
|
@ -115,11 +116,7 @@ export function calculateSaleAmount(contract: Contract, bet: Bet) {
|
|||
return deductFees(amount, winnings)
|
||||
}
|
||||
|
||||
export function calculatePayout(
|
||||
contract: Contract,
|
||||
bet: Bet,
|
||||
outcome: 'YES' | 'NO' | 'CANCEL' | 'MKT'
|
||||
) {
|
||||
export function calculatePayout(contract: Contract, bet: Bet, outcome: string) {
|
||||
if (outcome === 'CANCEL') return calculateCancelPayout(contract, bet)
|
||||
if (outcome === 'MKT') return calculateMktPayout(contract, bet)
|
||||
|
||||
|
@ -182,7 +179,7 @@ function calculateMktPayout(contract: Contract, bet: Bet) {
|
|||
if (contract.outcomeType === 'BINARY')
|
||||
return calculateBinaryMktPayout(contract, bet)
|
||||
|
||||
const { totalShares, pool } = contract as any as Contract<'MULTI'>
|
||||
const { totalShares, pool } = contract
|
||||
|
||||
const totalPool = _.sum(Object.values(pool))
|
||||
const sharesSquareSum = _.sumBy(
|
||||
|
@ -206,16 +203,17 @@ function calculateMktPayout(contract: Contract, bet: Bet) {
|
|||
}
|
||||
|
||||
function calculateBinaryMktPayout(contract: Contract, bet: Bet) {
|
||||
const { resolutionProbability, totalShares, phantomShares } = contract
|
||||
const p =
|
||||
contract.resolutionProbability !== undefined
|
||||
? contract.resolutionProbability
|
||||
: getProbability(contract.totalShares)
|
||||
resolutionProbability !== undefined
|
||||
? resolutionProbability
|
||||
: getProbability(totalShares)
|
||||
|
||||
const pool = contract.pool.YES + contract.pool.NO
|
||||
|
||||
const weightedShareTotal =
|
||||
p * (contract.totalShares.YES - contract.phantomShares.YES) +
|
||||
(1 - p) * (contract.totalShares.NO - contract.phantomShares.NO)
|
||||
p * (totalShares.YES - (phantomShares?.YES ?? 0)) +
|
||||
(1 - p) * (totalShares.NO - (phantomShares?.NO ?? 0))
|
||||
|
||||
const { outcome, amount, shares } = bet
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export type Contract<outcomeType extends 'BINARY' | 'MULTI' = 'BINARY'> = {
|
||||
export type Contract = {
|
||||
id: string
|
||||
slug: string // auto-generated; must be unique
|
||||
|
||||
|
@ -13,29 +13,14 @@ export type Contract<outcomeType extends 'BINARY' | 'MULTI' = 'BINARY'> = {
|
|||
lowercaseTags: string[]
|
||||
visibility: 'public' | 'unlisted'
|
||||
|
||||
outcomeType: outcomeType
|
||||
outcomes: {
|
||||
BINARY: undefined
|
||||
MULTI: 'FREE_ANSWER' | string[]
|
||||
}[outcomeType]
|
||||
outcomeType: 'BINARY' | 'MULTI'
|
||||
outcomes?: 'FREE_ANSWER' | string[]
|
||||
|
||||
mechanism: 'dpm-2'
|
||||
phantomShares: {
|
||||
BINARY: { YES: number; NO: number }
|
||||
MULTI: undefined
|
||||
}[outcomeType]
|
||||
pool: {
|
||||
BINARY: { YES: number; NO: number }
|
||||
MULTI: { [answerId: string]: number }
|
||||
}[outcomeType]
|
||||
totalShares: {
|
||||
BINARY: { YES: number; NO: number }
|
||||
MULTI: { [answerId: string]: number }
|
||||
}[outcomeType]
|
||||
totalBets: {
|
||||
BINARY: { YES: number; NO: number }
|
||||
MULTI: { [answerId: string]: number }
|
||||
}[outcomeType]
|
||||
phantomShares?: { [outcome: string]: number }
|
||||
pool: { [outcome: string]: number }
|
||||
totalShares: { [outcome: string]: number }
|
||||
totalBets: { [outcome: string]: number }
|
||||
|
||||
createdTime: number // Milliseconds since epoch
|
||||
lastUpdatedTime: number // If the question or description was changed
|
||||
|
@ -43,14 +28,9 @@ export type Contract<outcomeType extends 'BINARY' | 'MULTI' = 'BINARY'> = {
|
|||
|
||||
isResolved: boolean
|
||||
resolutionTime?: number // When the contract creator resolved the market
|
||||
resolution?: {
|
||||
BINARY: outcome
|
||||
MULTI: string
|
||||
}[outcomeType]
|
||||
resolution?: string
|
||||
resolutionProbability?: number
|
||||
|
||||
volume24Hours: number
|
||||
volume7Days: number
|
||||
}
|
||||
|
||||
export type outcome = 'YES' | 'NO' | 'CANCEL' | 'MKT'
|
||||
|
|
|
@ -61,7 +61,7 @@ export const getNewMultiBetInfo = (
|
|||
user: User,
|
||||
outcome: string,
|
||||
amount: number,
|
||||
contract: Contract<'MULTI'>,
|
||||
contract: Contract,
|
||||
newBetId: string
|
||||
) => {
|
||||
const { pool, totalShares, totalBets } = contract
|
||||
|
@ -80,7 +80,7 @@ export const getNewMultiBetInfo = (
|
|||
const probBefore = getOutcomeProbability(totalShares, outcome)
|
||||
const probAfter = getOutcomeProbability(newTotalShares, outcome)
|
||||
|
||||
const newBet: Bet<'MULTI'> = {
|
||||
const newBet: Bet = {
|
||||
id: newBetId,
|
||||
userId: user.id,
|
||||
contractId: contract.id,
|
||||
|
|
|
@ -26,7 +26,7 @@ export function getNewContract(
|
|||
? getBinaryProps(initialProb, ante)
|
||||
: getFreeAnswerProps(ante)
|
||||
|
||||
const contract: Contract<'BINARY' | 'MULTI'> = removeUndefinedProps({
|
||||
const contract: Contract = removeUndefinedProps({
|
||||
id,
|
||||
slug,
|
||||
mechanism: 'dpm-2',
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as _ from 'lodash'
|
|||
|
||||
import { Bet } from './bet'
|
||||
import { deductFees, getProbability } from './calculate'
|
||||
import { Contract, outcome } from './contract'
|
||||
import { Contract } from './contract'
|
||||
import { CREATOR_FEE, FEES } from './fees'
|
||||
|
||||
export const getCancelPayouts = (contract: Contract, bets: Bet[]) => {
|
||||
|
@ -100,7 +100,7 @@ export const getMktPayouts = (
|
|||
}
|
||||
|
||||
export const getPayouts = (
|
||||
outcome: outcome,
|
||||
outcome: string,
|
||||
contract: Contract,
|
||||
bets: Bet[],
|
||||
resolutionProbability?: number
|
||||
|
|
|
@ -42,7 +42,7 @@ export const createAnswer = functions.runWith({ minInstances: 1 }).https.onCall(
|
|||
const contractSnap = await transaction.get(contractDoc)
|
||||
if (!contractSnap.exists)
|
||||
return { status: 'error', message: 'Invalid contract' }
|
||||
const contract = contractSnap.data() as Contract<'MULTI'>
|
||||
const contract = contractSnap.data() as Contract
|
||||
|
||||
if (
|
||||
contract.outcomeType !== 'MULTI' ||
|
||||
|
|
|
@ -100,7 +100,7 @@ export const createContract = functions
|
|||
|
||||
const { yesBet, noBet } = getAnteBets(
|
||||
creator,
|
||||
contract as Contract<'BINARY'>,
|
||||
contract,
|
||||
yesBetDoc.id,
|
||||
noBetDoc.id
|
||||
)
|
||||
|
@ -116,11 +116,7 @@ export const createContract = functions
|
|||
const anteBetDoc = firestore
|
||||
.collection(`contracts/${contract.id}/bets`)
|
||||
.doc()
|
||||
const anteBet = getFreeAnswerAnte(
|
||||
creator,
|
||||
contract as Contract<'MULTI'>,
|
||||
anteBetDoc.id
|
||||
)
|
||||
const anteBet = getFreeAnswerAnte(creator, contract, anteBetDoc.id)
|
||||
await anteBetDoc.set(anteBet)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,10 +35,7 @@ import { useAnswers } from '../hooks/use-answers'
|
|||
import { ResolveConfirmationButton } from './confirmation-button'
|
||||
import { tradingAllowed } from '../lib/firebase/contracts'
|
||||
|
||||
export function AnswersPanel(props: {
|
||||
contract: Contract<'MULTI'>
|
||||
answers: Answer[]
|
||||
}) {
|
||||
export function AnswersPanel(props: { contract: Contract; answers: Answer[] }) {
|
||||
const { contract } = props
|
||||
const { creatorId, resolution } = contract
|
||||
|
||||
|
@ -101,7 +98,7 @@ export function AnswersPanel(props: {
|
|||
|
||||
function AnswerItem(props: {
|
||||
answer: Answer
|
||||
contract: Contract<'MULTI'>
|
||||
contract: Contract
|
||||
showChoice: boolean
|
||||
isChosen: boolean
|
||||
onChoose: () => void
|
||||
|
@ -209,7 +206,7 @@ function AnswerItem(props: {
|
|||
|
||||
function AnswerBetPanel(props: {
|
||||
answer: Answer
|
||||
contract: Contract<'MULTI'>
|
||||
contract: Contract
|
||||
closePanel: () => void
|
||||
}) {
|
||||
const { answer, contract, closePanel } = props
|
||||
|
@ -267,14 +264,11 @@ function AnswerBetPanel(props: {
|
|||
const shares = calculateShares(contract.totalShares, betAmount ?? 0, answerId)
|
||||
|
||||
const currentPayout = betAmount
|
||||
? calculatePayoutAfterCorrectBet(
|
||||
contract as any as Contract,
|
||||
{
|
||||
? calculatePayoutAfterCorrectBet(contract, {
|
||||
outcome: answerId,
|
||||
amount: betAmount,
|
||||
shares,
|
||||
} as Bet
|
||||
)
|
||||
} as Bet)
|
||||
: 0
|
||||
|
||||
const currentReturn = betAmount ? (currentPayout - betAmount) / betAmount : 0
|
||||
|
@ -351,7 +345,7 @@ function AnswerBetPanel(props: {
|
|||
)
|
||||
}
|
||||
|
||||
function CreateAnswerInput(props: { contract: Contract<'MULTI'> }) {
|
||||
function CreateAnswerInput(props: { contract: Contract }) {
|
||||
const { contract } = props
|
||||
const [text, setText] = useState('')
|
||||
const [betAmount, setBetAmount] = useState<number | undefined>(10)
|
||||
|
@ -426,7 +420,7 @@ function CreateAnswerInput(props: { contract: Contract<'MULTI'> }) {
|
|||
}
|
||||
|
||||
function AnswerResolvePanel(props: {
|
||||
contract: Contract<'MULTI'>
|
||||
contract: Contract
|
||||
resolveOption: 'CHOOSE' | 'NONE' | 'CANCEL' | undefined
|
||||
setResolveOption: (option: 'CHOOSE' | 'NONE' | 'CANCEL' | undefined) => void
|
||||
answer: string | undefined
|
||||
|
|
|
@ -49,6 +49,7 @@ export function BetPanel(props: {
|
|||
}, [])
|
||||
|
||||
const { contract, className, title, selected, onBetSuccess } = props
|
||||
const { totalShares, phantomShares } = contract
|
||||
|
||||
const user = useUser()
|
||||
|
||||
|
@ -179,8 +180,8 @@ export function BetPanel(props: {
|
|||
shares
|
||||
)} / ${formatWithCommas(
|
||||
shares +
|
||||
contract.totalShares[betChoice] -
|
||||
contract.phantomShares[betChoice]
|
||||
totalShares[betChoice] -
|
||||
(phantomShares ? phantomShares[betChoice] : 0)
|
||||
)} ${betChoice} shares`}
|
||||
/>
|
||||
</Row>
|
||||
|
|
|
@ -31,6 +31,7 @@ import {
|
|||
import { sellBet } from '../lib/firebase/api-call'
|
||||
import { ConfirmationButton } from './confirmation-button'
|
||||
import { OutcomeLabel, YesLabel, NoLabel } from './outcome-label'
|
||||
import { filterDefined } from '../../common/util/array'
|
||||
|
||||
type BetSort = 'newest' | 'profit'
|
||||
|
||||
|
@ -49,7 +50,7 @@ export function BetsList(props: { user: User }) {
|
|||
let disposed = false
|
||||
Promise.all(contractIds.map((id) => getContractFromId(id))).then(
|
||||
(contracts) => {
|
||||
if (!disposed) setContracts(contracts.filter(Boolean) as Contract[])
|
||||
if (!disposed) setContracts(filterDefined(contracts))
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import {
|
|||
contractPath,
|
||||
updateContract,
|
||||
tradingAllowed,
|
||||
getBinaryProbPercent,
|
||||
} from '../lib/firebase/contracts'
|
||||
import { useUser } from '../hooks/use-user'
|
||||
import { Linkify } from './linkify'
|
||||
|
@ -38,7 +37,6 @@ import { useBets } from '../hooks/use-bets'
|
|||
import { Bet } from '../lib/firebase/bets'
|
||||
import { Comment, mapCommentsByBetId } from '../lib/firebase/comments'
|
||||
import { JoinSpans } from './join-spans'
|
||||
import { outcome } from '../../common/contract'
|
||||
import { fromNow } from '../lib/util/time'
|
||||
import BetRow from './bet-row'
|
||||
import { parseTags } from '../../common/util/parse'
|
||||
|
@ -382,7 +380,7 @@ function FeedDescription(props: { contract: Contract }) {
|
|||
)
|
||||
}
|
||||
|
||||
function OutcomeIcon(props: { outcome?: outcome }) {
|
||||
function OutcomeIcon(props: { outcome?: string }) {
|
||||
const { outcome } = props
|
||||
switch (outcome) {
|
||||
case 'YES':
|
||||
|
|
|
@ -13,7 +13,9 @@ export function ContractProbGraph(props: { contract: Contract; bets: Bet[] }) {
|
|||
|
||||
const bets = useBetsWithoutAntes(contract, props.bets)
|
||||
|
||||
const startProb = getProbability(phantomShares)
|
||||
const startProb = getProbability(
|
||||
phantomShares as { [outcome: string]: number }
|
||||
)
|
||||
|
||||
const times = bets
|
||||
? [contract.createdTime, ...bets.map((bet) => bet.createdTime)].map(
|
||||
|
|
|
@ -49,7 +49,7 @@ export function getBinaryProbPercent(contract: Contract) {
|
|||
return probPercent
|
||||
}
|
||||
|
||||
export function tradingAllowed(contract: Contract<'BINARY' | 'MULTI'>) {
|
||||
export function tradingAllowed(contract: Contract) {
|
||||
return (
|
||||
!contract.isResolved &&
|
||||
(!contract.closeTime || contract.closeTime > Date.now())
|
||||
|
@ -84,9 +84,7 @@ export async function getContractFromSlug(slug: string) {
|
|||
const q = query(contractCollection, where('slug', '==', slug))
|
||||
const snapshot = await getDocs(q)
|
||||
|
||||
return snapshot.empty
|
||||
? undefined
|
||||
: (snapshot.docs[0].data() as Contract<'BINARY' | 'MULTI'>)
|
||||
return snapshot.empty ? undefined : (snapshot.docs[0].data() as Contract)
|
||||
}
|
||||
|
||||
export async function deleteContract(contractId: string) {
|
||||
|
|
|
@ -186,7 +186,7 @@ function BetsSection(props: {
|
|||
)
|
||||
}
|
||||
|
||||
const getOpenGraphProps = (contract: Contract<'BINARY'>) => {
|
||||
const getOpenGraphProps = (contract: Contract) => {
|
||||
const { resolution, question, creatorName, creatorUsername } = contract
|
||||
const probPercent = getBinaryProbPercent(contract)
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ type Prediction = {
|
|||
}
|
||||
|
||||
function toPrediction(contract: Contract): Prediction {
|
||||
const startProb = getProbability(contract.phantomShares)
|
||||
const startProb = getProbability(contract.totalShares)
|
||||
return {
|
||||
question: contract.question,
|
||||
description: contract.description,
|
||||
|
|
Loading…
Reference in New Issue
Block a user