import clsx from 'clsx' import { getOutcomeProbability, getOutcomeProbabilityAfterBet, getProbability, getTopAnswer, } from 'common/calculate' import { getExpectedValue } from 'common/calculate-dpm' import { User } from 'common/user' import { BinaryContract, Contract, NumericContract, PseudoNumericContract, resolution, } 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' import { 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 { useSaveBinaryShares } from '../use-save-binary-shares' import { sellShares } from 'web/lib/firebase/api' import { calculateCpmmSale, getCpmmProbability } from 'common/calculate-cpmm' import { track } from 'web/lib/service/analytics' import { formatNumericProbability } from 'common/pseudo-numeric' import { useUnfilledBets } from 'web/hooks/use-bets' import { getBinaryProb } from 'common/contract-details' const BET_SIZE = 10 export function QuickBetArrows(props: { contract: BinaryContract | PseudoNumericContract user: User className?: string }) { const { contract, user, className } = props const { mechanism, outcomeType } = contract const isCpmm = mechanism === 'cpmm-1' const userBets = useUserContractBets(user.id, contract.id) const unfilledBets = useUnfilledBets(contract.id) ?? [] const { hasYesShares, hasNoShares, yesShares, noShares } = useSaveBinaryShares(contract, userBets) const hasUpShares = hasYesShares const hasDownShares = hasNoShares && !hasUpShares 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 } let sharesSold: number | undefined let sellOutcome: 'YES' | 'NO' | undefined let saleAmount: number | undefined if (isCpmm && (upHover || downHover)) { const oppositeShares = upHover ? noShares : yesShares if (oppositeShares) { sellOutcome = upHover ? 'NO' : 'YES' const prob = getProb(contract) const maxSharesSold = BET_SIZE / (sellOutcome === 'YES' ? prob : 1 - prob) sharesSold = Math.min(oppositeShares, maxSharesSold) const { cpmmState, saleValue } = calculateCpmmSale( contract, sharesSold, sellOutcome, unfilledBets ) saleAmount = saleValue previewProb = getCpmmProbability(cpmmState.pool, cpmmState.p) } } async function placeQuickBet(direction: 'UP' | 'DOWN') { const betPromise = async () => { if (sharesSold && sellOutcome) { return await sellShares({ shares: sharesSold, outcome: sellOutcome, contractId: contract.id, }) } const outcome = quickOutcome(contract, direction) return await placeBet({ amount: BET_SIZE, outcome, contractId: contract.id, }) } const shortQ = contract.question.slice(0, 20) const message = sellOutcome && saleAmount ? `${formatMoney(saleAmount)} sold of "${shortQ}"...` : `${formatMoney(BET_SIZE)} on "${shortQ}"...` toast.promise(betPromise(), { loading: message, success: message, error: (err) => `${err.message}`, }) track('quick bet', { slug: contract.slug, direction, contractId: contract.id, }) } return (