Add numeric resolution panel

This commit is contained in:
James Grugett 2022-05-06 16:06:18 -04:00
parent 47f18cb307
commit 3c55843030
3 changed files with 157 additions and 7 deletions

View File

@ -2,17 +2,23 @@ import clsx from 'clsx'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { Col } from './layout/col' import { Col } from './layout/col'
import { Title } from './title'
import { User } from '../lib/firebase/users' import { User } from '../lib/firebase/users'
import { YesNoCancelSelector } from './yes-no-selector' import { NumberCancelSelector, YesNoCancelSelector } from './yes-no-selector'
import { Spacer } from './layout/spacer' import { Spacer } from './layout/spacer'
import { ResolveConfirmationButton } from './confirmation-button' import { ResolveConfirmationButton } from './confirmation-button'
import { resolveMarket } from '../lib/firebase/api-call' import { resolveMarket } from '../lib/firebase/api-call'
import { ProbabilitySelector } from './probability-selector' import { ProbabilitySelector } from './probability-selector'
import { DPM_CREATOR_FEE } from '../../common/fees' import { DPM_CREATOR_FEE } from '../../common/fees'
import { getProbability } from '../../common/calculate' import { getProbability } from '../../common/calculate'
import { Binary, CPMM, DPM, FullContract } from '../../common/contract' import {
Binary,
CPMM,
DPM,
FullContract,
NumericContract,
} from '../../common/contract'
import { formatMoney } from '../../common/util/format' import { formatMoney } from '../../common/util/format'
import { BucketAmountInput } from './amount-input'
export function ResolutionPanel(props: { export function ResolutionPanel(props: {
creator: User creator: User
@ -129,3 +135,104 @@ export function ResolutionPanel(props: {
</Col> </Col>
) )
} }
export function NumericResolutionPanel(props: {
creator: User
contract: NumericContract
className?: string
}) {
useEffect(() => {
// warm up cloud function
resolveMarket({} as any).catch()
}, [])
const { contract, className } = props
const { bucketCount, min, max } = contract
const [outcomeMode, setOutcomeMode] = useState<
'NUMBER' | 'CANCEL' | undefined
>()
const [outcome, setOutcome] = useState<string | undefined>()
const [isSubmitting, setIsSubmitting] = useState(false)
const [valueError, setValueError] = useState<string | undefined>()
const [error, setError] = useState<string | undefined>(undefined)
const resolve = async () => {
if (!outcome) return
setIsSubmitting(true)
const result = await resolveMarket({
outcome: outcome,
contractId: contract.id,
}).then((r) => r.data)
console.log('resolved', outcome, 'result:', result)
if (result?.status !== 'success') {
setError(result?.message || 'Error resolving market')
}
setIsSubmitting(false)
}
const submitButtonClass =
outcome === 'CANCEL'
? 'bg-yellow-400 hover:bg-yellow-500'
: outcome
? 'btn-primary'
: 'btn-disabled'
console.log('outcome', outcome)
return (
<Col className={clsx('rounded-md bg-white px-8 py-6', className)}>
<div className="mb-6 whitespace-nowrap text-2xl">Resolve market</div>
<div className="mb-3 text-sm text-gray-500">Outcome</div>
<Spacer h={4} />
<NumberCancelSelector selected={outcomeMode} onSelect={setOutcomeMode} />
<Spacer h={4} />
{outcomeMode === 'NUMBER' && (
<>
<BucketAmountInput
bucket={outcome && outcome !== 'CANCEL' ? +outcome : undefined}
bucketCount={bucketCount}
min={min}
max={max}
inputClassName="w-full max-w-none"
onChange={(outcome) =>
setOutcome(outcome ? `${outcome}` : undefined)
}
error={valueError}
setError={setValueError}
disabled={isSubmitting}
/>
</>
)}
<div>
{outcome === 'CANCEL' ? (
<>All trades will be returned with no fees.</>
) : (
<>Resolving this market will immediately pay out traders.</>
)}
</div>
<Spacer h={4} />
{!!error && <div className="text-red-500">{error}</div>}
<ResolveConfirmationButton
onResolve={resolve}
isSubmitting={isSubmitting}
openModalButtonClass={clsx('w-full mt-2', submitButtonClass)}
submitButtonClass={submitButtonClass}
/>
</Col>
)
}

View File

@ -195,6 +195,37 @@ export function BuyButton(props: { className?: string; onClick?: () => void }) {
) )
} }
export function NumberCancelSelector(props: {
selected: 'NUMBER' | 'CANCEL' | undefined
onSelect: (selected: 'NUMBER' | 'CANCEL') => void
className?: string
btnClassName?: string
}) {
const { selected, onSelect, className } = props
const btnClassName = clsx('px-6 flex-1', props.btnClassName)
return (
<Col className={clsx('gap-2', className)}>
<Button
color={selected === 'NUMBER' ? 'green' : 'gray'}
onClick={() => onSelect('NUMBER')}
className={clsx('whitespace-nowrap', btnClassName)}
>
Choose value
</Button>
<Button
color={selected === 'CANCEL' ? 'yellow' : 'gray'}
onClick={() => onSelect('CANCEL')}
className={clsx(btnClassName, '')}
>
N/A
</Button>
</Col>
)
}
function Button(props: { function Button(props: {
className?: string className?: string
onClick?: () => void onClick?: () => void

View File

@ -7,7 +7,10 @@ import { ContractOverview } from '../../components/contract/contract-overview'
import { BetPanel } from '../../components/bet-panel' import { BetPanel } from '../../components/bet-panel'
import { Col } from '../../components/layout/col' import { Col } from '../../components/layout/col'
import { useUser } from '../../hooks/use-user' import { useUser } from '../../hooks/use-user'
import { ResolutionPanel } from '../../components/resolution-panel' import {
NumericResolutionPanel,
ResolutionPanel,
} from '../../components/resolution-panel'
import { Title } from '../../components/title' import { Title } from '../../components/title'
import { Spacer } from '../../components/layout/spacer' import { Spacer } from '../../components/layout/spacer'
import { listUsers, User } from '../../lib/firebase/users' import { listUsers, User } from '../../lib/firebase/users'
@ -141,9 +144,18 @@ export function ContractPageContent(props: FirstArgument<typeof ContractPage>) {
) : ( ) : (
<BetPanel className="hidden xl:flex" contract={contract} /> <BetPanel className="hidden xl:flex" contract={contract} />
))} ))}
{allowResolve && ( {allowResolve &&
<ResolutionPanel creator={user} contract={contract as BinaryContract} /> (isNumeric ? (
)} <NumericResolutionPanel
creator={user}
contract={contract as NumericContract}
/>
) : (
<ResolutionPanel
creator={user}
contract={contract as BinaryContract}
/>
))}
</Col> </Col>
) : null ) : null