import clsx from 'clsx' import { getOutcomeProbability, getOutcomeProbabilityAfterBet, getTopAnswer, } from 'common/calculate' import { getExpectedValue } from 'common/calculate-dpm' import { User } from 'common/user' import { Contract, NumericContract } from 'common/contract' import { formatLargeNumber, formatMoney, formatPercent, } from 'common/util/format' import { useState } from 'react' import toast from 'react-hot-toast' import { useUserContractBets } from 'web/hooks/use-user-bets' import { placeBet } from 'web/lib/firebase/api-call' import { getBinaryProb, getBinaryProbPercent } from 'web/lib/firebase/contracts' import TriangleDownFillIcon from 'web/lib/icons/triangle-down-fill-icon' import TriangleFillIcon from 'web/lib/icons/triangle-fill-icon' import { Col } from '../layout/col' import { OUTCOME_TO_COLOR } from '../outcome-label' import { useSaveShares } from '../use-save-shares' const BET_SIZE = 10 export function QuickBet(props: { contract: Contract; user: User }) { const { contract, user } = props const userBets = useUserContractBets(user.id, contract.id) const topAnswer = contract.outcomeType === 'FREE_RESPONSE' ? getTopAnswer(contract) : undefined // TODO: yes/no from useSaveShares doesn't work on numeric contracts const { yesFloorShares, noFloorShares } = useSaveShares( contract, userBets, topAnswer?.number.toString() || undefined ) const hasUpShares = yesFloorShares || (noFloorShares && contract.outcomeType === 'NUMERIC') const hasDownShares = noFloorShares && yesFloorShares <= 0 && contract.outcomeType !== 'NUMERIC' const [upHover, setUpHover] = useState(false) const [downHover, setDownHover] = useState(false) let previewProb = undefined try { previewProb = upHover ? getOutcomeProbabilityAfterBet( contract, quickOutcome(contract, 'UP') || '', BET_SIZE ) : downHover ? 1 - getOutcomeProbabilityAfterBet( contract, quickOutcome(contract, 'DOWN') || '', BET_SIZE ) : undefined } catch (e) { // Catch any errors from hovering on an invalid option } const color = getColor(contract, previewProb) async function placeQuickBet(direction: 'UP' | 'DOWN') { const betPromise = async () => { const outcome = quickOutcome(contract, direction) return await placeBet({ amount: BET_SIZE, outcome, contractId: contract.id, }) } const shortQ = contract.question.slice(0, 20) toast.promise(betPromise(), { loading: `${formatMoney(BET_SIZE)} on "${shortQ}"...`, success: `${formatMoney(BET_SIZE)} on "${shortQ}"...`, error: (err) => `${err.message}`, }) } function quickOutcome(contract: Contract, direction: 'UP' | 'DOWN') { if (contract.outcomeType === 'BINARY') { return direction === 'UP' ? 'YES' : 'NO' } if (contract.outcomeType === 'FREE_RESPONSE') { // TODO: Implement shorting of free response answers if (direction === 'DOWN') { throw new Error("Can't bet against free response answers") } return getTopAnswer(contract)?.id } if (contract.outcomeType === 'NUMERIC') { // TODO: Ideally an 'UP' bet would be a uniform bet between [current, max] throw new Error("Can't quick bet on numeric markets") } } return (