Support limit orders on numeric markets
This commit is contained in:
parent
a68c100df8
commit
60f5f311f9
|
@ -33,7 +33,10 @@ import {
|
|||
getCpmmLiquidityFee,
|
||||
calculateCpmmAmount,
|
||||
} from 'common/calculate-cpmm'
|
||||
import { getFormattedMappedValue } from 'common/pseudo-numeric'
|
||||
import {
|
||||
getFormattedMappedValue,
|
||||
getPseudoProbability,
|
||||
} from 'common/pseudo-numeric'
|
||||
import { SellRow } from './sell-row'
|
||||
import { useSaveShares } from './use-save-shares'
|
||||
import { SignUpPrompt } from './sign-up-prompt'
|
||||
|
@ -43,6 +46,7 @@ import { track } from 'web/lib/service/analytics'
|
|||
import { removeUndefinedProps } from 'common/util/object'
|
||||
import { useUnfilledBets } from 'web/hooks/use-bets'
|
||||
import { LimitBets } from './limit-bets'
|
||||
import { BucketInput } from './bucket-input'
|
||||
|
||||
export function BetPanel(props: {
|
||||
contract: CPMMBinaryContract | PseudoNumericContract
|
||||
|
@ -98,7 +102,11 @@ export function BetPanel(props: {
|
|||
<SignUpPrompt />
|
||||
</Col>
|
||||
{yourUnfilledBets.length > 0 && (
|
||||
<LimitBets className="mt-4" bets={yourUnfilledBets} />
|
||||
<LimitBets
|
||||
className="mt-4"
|
||||
contract={contract}
|
||||
bets={yourUnfilledBets}
|
||||
/>
|
||||
)}
|
||||
</Col>
|
||||
)
|
||||
|
@ -407,16 +415,37 @@ function BuyPanel(props: {
|
|||
{isLimitOrder && (
|
||||
<>
|
||||
<div className="my-3 text-left text-sm text-gray-500">
|
||||
{betChoice === 'NO' ? 'Min' : 'Max'} probability
|
||||
{betChoice === 'NO' ? 'Min' : 'Max'}{' '}
|
||||
{isPseudoNumeric ? 'value' : 'probability'}
|
||||
</div>
|
||||
<ProbabilityInput
|
||||
inputClassName="w-full max-w-none"
|
||||
prob={limitProb}
|
||||
onChange={setLimitProb}
|
||||
error={error}
|
||||
setError={setError}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
{isPseudoNumeric ? (
|
||||
<BucketInput
|
||||
contract={contract}
|
||||
onBucketChange={(value) =>
|
||||
setLimitProb(
|
||||
value === undefined
|
||||
? undefined
|
||||
: 100 *
|
||||
getPseudoProbability(
|
||||
value,
|
||||
contract.min,
|
||||
contract.max,
|
||||
contract.isLogScale
|
||||
)
|
||||
)
|
||||
}
|
||||
isSubmitting={isSubmitting}
|
||||
/>
|
||||
) : (
|
||||
<ProbabilityInput
|
||||
inputClassName="w-full max-w-none"
|
||||
prob={limitProb}
|
||||
onChange={setLimitProb}
|
||||
error={error}
|
||||
setError={setError}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<Col className="mt-3 w-full gap-3">
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { useState } from 'react'
|
||||
|
||||
import { NumericContract } from 'common/contract'
|
||||
import { NumericContract, PseudoNumericContract } from 'common/contract'
|
||||
import { getMappedBucket } from 'common/calculate-dpm'
|
||||
|
||||
import { NumberInput } from './number-input'
|
||||
|
||||
export function BucketInput(props: {
|
||||
contract: NumericContract
|
||||
contract: NumericContract | PseudoNumericContract
|
||||
isSubmitting?: boolean
|
||||
onBucketChange: (value?: number, bucket?: string) => void
|
||||
}) {
|
||||
|
@ -24,7 +24,10 @@ export function BucketInput(props: {
|
|||
return
|
||||
}
|
||||
|
||||
const bucket = getMappedBucket(value, contract)
|
||||
const bucket =
|
||||
contract.outcomeType === 'PSEUDO_NUMERIC'
|
||||
? ''
|
||||
: getMappedBucket(value, contract)
|
||||
|
||||
onBucketChange(value, bucket)
|
||||
}
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
import clsx from 'clsx'
|
||||
import { LimitBet } from 'common/bet'
|
||||
import { CPMMBinaryContract, PseudoNumericContract } from 'common/contract'
|
||||
import { getFormattedMappedValue } from 'common/pseudo-numeric'
|
||||
import { formatMoney, formatPercent } from 'common/util/format'
|
||||
import { sortBy, sumBy } from 'lodash'
|
||||
import { sortBy } from 'lodash'
|
||||
import { useState } from 'react'
|
||||
import { cancelBet } from 'web/lib/firebase/api-call'
|
||||
import { Col } from './layout/col'
|
||||
import { LoadingIndicator } from './loading-indicator'
|
||||
import { BinaryOutcomeLabel } from './outcome-label'
|
||||
import { BinaryOutcomeLabel, PseudoNumericOutcomeLabel } from './outcome-label'
|
||||
|
||||
export function LimitBets(props: { bets: LimitBet[]; className?: string }) {
|
||||
const { bets, className } = props
|
||||
export function LimitBets(props: {
|
||||
contract: CPMMBinaryContract | PseudoNumericContract
|
||||
bets: LimitBet[]
|
||||
className?: string
|
||||
}) {
|
||||
const { contract, bets, className } = props
|
||||
const recentBets = sortBy(bets, (bet) => bet.createdTime).reverse()
|
||||
|
||||
return (
|
||||
|
@ -18,7 +24,7 @@ export function LimitBets(props: { bets: LimitBet[]; className?: string }) {
|
|||
<table className="table-compact table w-full rounded text-gray-500">
|
||||
<tbody>
|
||||
{recentBets.map((bet) => (
|
||||
<LimitBet key={bet.id} bet={bet} />
|
||||
<LimitBet key={bet.id} bet={bet} contract={contract} />
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -26,9 +32,14 @@ export function LimitBets(props: { bets: LimitBet[]; className?: string }) {
|
|||
)
|
||||
}
|
||||
|
||||
function LimitBet(props: { bet: LimitBet }) {
|
||||
const { bet } = props
|
||||
function LimitBet(props: {
|
||||
contract: CPMMBinaryContract | PseudoNumericContract
|
||||
bet: LimitBet
|
||||
}) {
|
||||
const { contract, bet } = props
|
||||
const { orderAmount, amount, limitProb, outcome } = bet
|
||||
const isPseudoNumeric = contract.outcomeType === 'PSEUDO_NUMERIC'
|
||||
|
||||
const [isCancelling, setIsCancelling] = useState(false)
|
||||
|
||||
const onCancel = () => {
|
||||
|
@ -40,11 +51,19 @@ function LimitBet(props: { bet: LimitBet }) {
|
|||
<tr>
|
||||
<td>
|
||||
<div className="pl-2">
|
||||
<BinaryOutcomeLabel outcome={outcome as 'YES' | 'NO'} />
|
||||
{isPseudoNumeric ? (
|
||||
<PseudoNumericOutcomeLabel outcome={outcome as 'YES' | 'NO'} />
|
||||
) : (
|
||||
<BinaryOutcomeLabel outcome={outcome as 'YES' | 'NO'} />
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td>{formatMoney(orderAmount - amount)}</td>
|
||||
<td>{formatPercent(limitProb)}</td>
|
||||
<td>
|
||||
{isPseudoNumeric
|
||||
? getFormattedMappedValue(contract)(limitProb)
|
||||
: formatPercent(limitProb)}
|
||||
</td>
|
||||
<td>
|
||||
{isCancelling ? (
|
||||
<LoadingIndicator />
|
||||
|
|
|
@ -96,7 +96,7 @@ export function NumericResolutionPanel(props: {
|
|||
|
||||
{outcomeMode === 'NUMBER' && (
|
||||
<BucketInput
|
||||
contract={contract as any}
|
||||
contract={contract}
|
||||
isSubmitting={isSubmitting}
|
||||
onBucketChange={(v, o) => (setValue(v), setOutcome(o))}
|
||||
/>
|
||||
|
|
|
@ -39,7 +39,7 @@ import { FeedBet } from 'web/components/feed/feed-bets'
|
|||
import { useIsIframe } from 'web/hooks/use-is-iframe'
|
||||
import ContractEmbedPage from '../embed/[username]/[contractSlug]'
|
||||
import { useBets, useUnfilledBets } from 'web/hooks/use-bets'
|
||||
import { CPMMBinaryContract } from 'common/contract'
|
||||
import { CPMMBinaryContract, PseudoNumericContract } from 'common/contract'
|
||||
import { AlertBox } from 'web/components/alert-box'
|
||||
import { useTracking } from 'web/hooks/use-tracking'
|
||||
import { CommentTipMap, useTipTxns } from 'web/hooks/use-tip-txns'
|
||||
|
@ -222,7 +222,11 @@ export function ContractPageContent(
|
|||
<ContractOverview contract={contract} bets={bets} />
|
||||
|
||||
{yourUnfilledBets.length > 0 && (
|
||||
<LimitBets className="mb-4 xl:hidden" bets={yourUnfilledBets} />
|
||||
<LimitBets
|
||||
className="mb-4 xl:hidden"
|
||||
contract={contract as CPMMBinaryContract | PseudoNumericContract}
|
||||
bets={yourUnfilledBets}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isNumeric && (
|
||||
|
|
Loading…
Reference in New Issue
Block a user