import clsx from 'clsx' import _ from 'lodash' import { useUser } from '../hooks/use-user' import { formatMoney, formatWithCommas } from '../../common/util/format' import { Col } from './layout/col' import { Row } from './layout/row' import { Bet, MAX_LOAN_PER_CONTRACT } from '../../common/bet' import { InfoTooltip } from './info-tooltip' import { Spacer } from './layout/spacer' import { calculateCpmmSale } from '../../common/calculate-cpmm' import { Binary, CPMM, FullContract } from '../../common/contract' export function AmountInput(props: { amount: number | undefined onChange: (newAmount: number | undefined) => void error: string | undefined label: string disabled?: boolean className?: string inputClassName?: string // Needed to focus the amount input inputRef?: React.MutableRefObject children?: any }) { const { amount, onChange, error, label, disabled, className, inputClassName, inputRef, children, } = props const onAmountChange = (str: string) => { const amount = parseInt(str.replace(/\D/g, '')) const isInvalid = !str || isNaN(amount) onChange(isInvalid ? undefined : amount) } return ( {error && (
{error}
)} {children} ) } export function BuyAmountInput(props: { amount: number | undefined onChange: (newAmount: number | undefined) => void error: string | undefined setError: (error: string | undefined) => void contractIdForLoan: string | undefined userBets?: Bet[] minimumAmount?: number disabled?: boolean className?: string inputClassName?: string // Needed to focus the amount input inputRef?: React.MutableRefObject }) { const { amount, onChange, userBets, error, setError, contractIdForLoan, disabled, className, inputClassName, minimumAmount, inputRef, } = props const user = useUser() const openUserBets = (userBets ?? []).filter( (bet) => !bet.isSold && !bet.sale ) const prevLoanAmount = _.sumBy(openUserBets, (bet) => bet.loanAmount ?? 0) const loanAmount = contractIdForLoan ? Math.min(amount ?? 0, MAX_LOAN_PER_CONTRACT - prevLoanAmount) : 0 const onAmountChange = (amount: number | undefined) => { onChange(amount) // Check for errors. if (amount !== undefined) { const amountNetLoan = amount - loanAmount if (user && user.balance < amountNetLoan) { setError('Insufficient balance') } else if (minimumAmount && amount < minimumAmount) { setError('Minimum amount: ' + formatMoney(minimumAmount)) } else { setError(undefined) } } } return ( {user && ( {contractIdForLoan && ( Amount loaned{' '} {formatMoney(loanAmount)}{' '} )} )} ) } export function SellAmountInput(props: { contract: FullContract amount: number | undefined onChange: (newAmount: number | undefined) => void userBets: Bet[] error: string | undefined setError: (error: string | undefined) => void disabled?: boolean className?: string inputClassName?: string // Needed to focus the amount input inputRef?: React.MutableRefObject }) { const { contract, amount, onChange, userBets, error, setError, disabled, className, inputClassName, inputRef, } = props const user = useUser() const openUserBets = userBets.filter((bet) => !bet.isSold && !bet.sale) const [yesBets, noBets] = _.partition( openUserBets, (bet) => bet.outcome === 'YES' ) const [yesShares, noShares] = [ _.sumBy(yesBets, (bet) => bet.shares), _.sumBy(noBets, (bet) => bet.shares), ] const sellOutcome = yesShares ? 'YES' : noShares ? 'NO' : undefined const shares = yesShares || noShares const prevLoanAmount = _.sumBy(openUserBets, (bet) => bet.loanAmount ?? 0) const sharesSold = Math.min(amount ?? 0, yesShares || noShares) const { saleValue } = calculateCpmmSale( contract, sharesSold, sellOutcome as 'YES' | 'NO' ) const loanRepaid = Math.min(prevLoanAmount, saleValue) const onAmountChange = (amount: number | undefined) => { onChange(amount) // Check for errors. if (amount !== undefined) { if (amount > shares) { setError(`Maximum ${formatWithCommas(Math.floor(shares))} shares`) } else { setError(undefined) } } } return ( {user && ( Sale proceeds{' '} {formatMoney(saleValue)} {!!prevLoanAmount && ( Loan repaid{' '} {formatMoney(loanRepaid)}{' '} )} )} ) }