Update range order UI
This commit is contained in:
parent
90f3204dbf
commit
1ae6756f8f
|
@ -262,7 +262,7 @@ export const getBinaryBetStats = (
|
||||||
|
|
||||||
const totalFees = sum(Object.values(newBet.fees))
|
const totalFees = sum(Object.values(newBet.fees))
|
||||||
|
|
||||||
return { currentPayout, currentReturn, totalFees }
|
return { currentPayout, currentReturn, totalFees, newBet }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getBinaryRangeBetInfo = (
|
export const getBinaryRangeBetInfo = (
|
||||||
|
|
|
@ -428,35 +428,58 @@ function RangeOrderPanel(props: {
|
||||||
highLimitProb !== undefined &&
|
highLimitProb !== undefined &&
|
||||||
lowLimitProb >= highLimitProb
|
lowLimitProb >= highLimitProb
|
||||||
|
|
||||||
|
const betDisabled = isSubmitting || !betAmount || rangeError || error
|
||||||
|
|
||||||
|
const hasYesLimitBet = lowLimitProb !== undefined && !!betAmount
|
||||||
|
const hasNoLimitBet = highLimitProb !== undefined && !!betAmount
|
||||||
|
const hasTwoBets = hasYesLimitBet && hasNoLimitBet
|
||||||
|
|
||||||
|
const yesLimitProb = (lowLimitProb ?? initialProb * 100) / 100
|
||||||
|
const noLimitProb = (highLimitProb ?? initialProb * 100) / 100
|
||||||
|
|
||||||
|
const shares = Math.min(
|
||||||
|
(betAmount ?? 0) / yesLimitProb,
|
||||||
|
(betAmount ?? 0) / (1 - noLimitProb)
|
||||||
|
)
|
||||||
|
const yesAmount = shares * yesLimitProb
|
||||||
|
const noAmount = shares * (1 - noLimitProb)
|
||||||
|
|
||||||
|
const profitIfBothFilled = shares - (yesAmount + noAmount)
|
||||||
|
|
||||||
function onBetChange(newAmount: number | undefined) {
|
function onBetChange(newAmount: number | undefined) {
|
||||||
setWasSubmitted(false)
|
setWasSubmitted(false)
|
||||||
setBetAmount(newAmount)
|
setBetAmount(newAmount)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submitBet() {
|
async function submitBet() {
|
||||||
if (!user || !betAmount || rangeError) return
|
if (!user || betDisabled) return
|
||||||
|
|
||||||
const limitProbScaled =
|
|
||||||
lowLimitProb !== undefined ? lowLimitProb / 100 : undefined
|
|
||||||
|
|
||||||
setError(undefined)
|
setError(undefined)
|
||||||
setIsSubmitting(true)
|
setIsSubmitting(true)
|
||||||
|
|
||||||
placeBet(
|
const betsPromise = hasTwoBets
|
||||||
removeUndefinedProps({
|
? Promise.all([
|
||||||
amount: betAmount,
|
placeBet({
|
||||||
outcome: betChoice,
|
betChoice: 'YES',
|
||||||
contractId: contract.id,
|
amount: yesAmount,
|
||||||
limitProb: limitProbScaled,
|
limitProb: yesLimitProb,
|
||||||
})
|
contractId: contract.id,
|
||||||
)
|
}),
|
||||||
.then((r) => {
|
placeBet({
|
||||||
console.log('placed bet. Result:', r)
|
betChoice: 'NO',
|
||||||
setIsSubmitting(false)
|
amount: noAmount,
|
||||||
setWasSubmitted(true)
|
limitProb: noLimitProb,
|
||||||
setBetAmount(undefined)
|
contractId: contract.id,
|
||||||
if (onBuySuccess) onBuySuccess()
|
}),
|
||||||
})
|
])
|
||||||
|
: placeBet({
|
||||||
|
betChoice: hasYesLimitBet ? 'YES' : 'NO',
|
||||||
|
amount: betAmount,
|
||||||
|
contractId: contract.id,
|
||||||
|
limitProb: hasYesLimitBet ? yesLimitProb : noLimitProb,
|
||||||
|
})
|
||||||
|
|
||||||
|
betsPromise
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
if (e instanceof APIError) {
|
if (e instanceof APIError) {
|
||||||
setError(e.toString())
|
setError(e.toString())
|
||||||
|
@ -466,54 +489,75 @@ function RangeOrderPanel(props: {
|
||||||
}
|
}
|
||||||
setIsSubmitting(false)
|
setIsSubmitting(false)
|
||||||
})
|
})
|
||||||
|
.then((r) => {
|
||||||
|
console.log('placed bet. Result:', r)
|
||||||
|
setIsSubmitting(false)
|
||||||
|
setWasSubmitted(true)
|
||||||
|
setBetAmount(undefined)
|
||||||
|
if (onBuySuccess) onBuySuccess()
|
||||||
|
})
|
||||||
|
|
||||||
track('bet', {
|
if (hasYesLimitBet) {
|
||||||
location: 'bet panel',
|
track('bet', {
|
||||||
outcomeType: contract.outcomeType,
|
location: 'bet panel',
|
||||||
slug: contract.slug,
|
outcomeType: contract.outcomeType,
|
||||||
contractId: contract.id,
|
slug: contract.slug,
|
||||||
amount: betAmount,
|
contractId: contract.id,
|
||||||
outcome: betChoice,
|
amount: yesAmount,
|
||||||
isLimitOrder: true,
|
outcome: 'YES',
|
||||||
limitProb: limitProbScaled,
|
limitProb: yesLimitProb,
|
||||||
})
|
isLimitOrder: true,
|
||||||
|
isRangeOrder: hasTwoBets,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (hasNoLimitBet) {
|
||||||
|
track('bet', {
|
||||||
|
location: 'bet panel',
|
||||||
|
outcomeType: contract.outcomeType,
|
||||||
|
slug: contract.slug,
|
||||||
|
contractId: contract.id,
|
||||||
|
amount: noAmount,
|
||||||
|
outcome: 'NO',
|
||||||
|
limitProb: noLimitProb,
|
||||||
|
isLimitOrder: true,
|
||||||
|
isRangeOrder: hasTwoBets,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const betDisabled = isSubmitting || !betAmount || rangeError || error
|
|
||||||
|
|
||||||
const lowProbFrac = (lowLimitProb ?? initialProb * 100) / 100
|
|
||||||
const {
|
const {
|
||||||
currentPayout: lowPayout,
|
currentPayout: yesPayout,
|
||||||
currentReturn: lowReturn,
|
currentReturn: yesReturn,
|
||||||
totalFees: lowFees,
|
totalFees: yesFees,
|
||||||
|
newBet: yesBet,
|
||||||
} = getBinaryBetStats(
|
} = getBinaryBetStats(
|
||||||
'YES',
|
'YES',
|
||||||
betAmount ?? 0,
|
yesAmount,
|
||||||
contract,
|
contract,
|
||||||
lowProbFrac,
|
yesLimitProb,
|
||||||
unfilledBets as LimitBet[]
|
unfilledBets as LimitBet[]
|
||||||
)
|
)
|
||||||
const lowReturnPercent = formatPercent(lowReturn)
|
const yesReturnPercent = formatPercent(yesReturn)
|
||||||
|
|
||||||
const highProbFrac = (highLimitProb ?? initialProb * 100) / 100
|
|
||||||
const {
|
const {
|
||||||
currentPayout: highPayout,
|
currentPayout: noPayout,
|
||||||
currentReturn: highReturn,
|
currentReturn: noReturn,
|
||||||
totalFees: highFees,
|
totalFees: noFees,
|
||||||
|
newBet: noBet,
|
||||||
} = getBinaryBetStats(
|
} = getBinaryBetStats(
|
||||||
'NO',
|
'NO',
|
||||||
betAmount ?? 0,
|
noAmount,
|
||||||
contract,
|
contract,
|
||||||
highProbFrac,
|
noLimitProb,
|
||||||
unfilledBets as LimitBet[]
|
unfilledBets as LimitBet[]
|
||||||
)
|
)
|
||||||
const highReturnPercent = formatPercent(highReturn)
|
const noReturnPercent = formatPercent(noReturn)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="my-3 text-sm text-gray-500">
|
<div className="my-3 text-sm text-gray-500">
|
||||||
Bet only when the {isPseudoNumeric ? 'value' : 'probability'} reaches
|
Bet only when the {isPseudoNumeric ? 'value' : 'probability'} reaches
|
||||||
low or high limit.
|
Low or High limit.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Row className="items-center gap-4">
|
<Row className="items-center gap-4">
|
||||||
|
@ -541,7 +585,7 @@ function RangeOrderPanel(props: {
|
||||||
|
|
||||||
{rangeError && (
|
{rangeError && (
|
||||||
<div className="mb-2 mr-auto self-center whitespace-nowrap text-xs font-medium tracking-wide text-red-500">
|
<div className="mb-2 mr-auto self-center whitespace-nowrap text-xs font-medium tracking-wide text-red-500">
|
||||||
Low limit must be less than high limit
|
Low limit must be less than High limit
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -558,7 +602,50 @@ function RangeOrderPanel(props: {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Col className="mt-3 w-full gap-3">
|
<Col className="mt-3 w-full gap-3">
|
||||||
{lowLimitProb !== undefined && (
|
{hasYesLimitBet && (
|
||||||
|
<Row className="items-center justify-between gap-2 text-sm">
|
||||||
|
<div className="whitespace-nowrap text-gray-500">
|
||||||
|
{isPseudoNumeric ? (
|
||||||
|
'Bought now'
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<BinaryOutcomeLabel outcome={'YES'} /> bought now
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="mr-2 whitespace-nowrap">
|
||||||
|
{formatMoney(yesBet.amount)}/
|
||||||
|
{formatMoney(yesBet.orderAmount ?? 0)}
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
)}
|
||||||
|
{hasNoLimitBet && (
|
||||||
|
<Row className="items-center justify-between gap-2 text-sm">
|
||||||
|
<div className="whitespace-nowrap text-gray-500">
|
||||||
|
{isPseudoNumeric ? (
|
||||||
|
'Bought now'
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<BinaryOutcomeLabel outcome={'NO'} /> bought now
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="mr-2 whitespace-nowrap">
|
||||||
|
{formatMoney(noBet.amount)}/{formatMoney(noBet.orderAmount ?? 0)}
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
)}
|
||||||
|
{hasTwoBets && (
|
||||||
|
<Row className="items-center justify-between gap-2 text-sm">
|
||||||
|
<div className="whitespace-nowrap text-gray-500">
|
||||||
|
Profit if both orders filled
|
||||||
|
</div>
|
||||||
|
<div className="mr-2 whitespace-nowrap">
|
||||||
|
{formatMoney(profitIfBothFilled)}
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
)}
|
||||||
|
{hasYesLimitBet && !hasTwoBets && (
|
||||||
<Row className="items-center justify-between gap-2 text-sm">
|
<Row className="items-center justify-between gap-2 text-sm">
|
||||||
<Row className="flex-nowrap items-center gap-2 whitespace-nowrap text-gray-500">
|
<Row className="flex-nowrap items-center gap-2 whitespace-nowrap text-gray-500">
|
||||||
<div>
|
<div>
|
||||||
|
@ -571,18 +658,18 @@ function RangeOrderPanel(props: {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<InfoTooltip
|
<InfoTooltip
|
||||||
text={`Includes ${formatMoneyWithDecimals(lowFees)} in fees`}
|
text={`Includes ${formatMoneyWithDecimals(yesFees)} in fees`}
|
||||||
/>
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
<div>
|
<div>
|
||||||
<span className="mr-2 whitespace-nowrap">
|
<span className="mr-2 whitespace-nowrap">
|
||||||
{formatMoney(lowPayout)}
|
{formatMoney(yesPayout)}
|
||||||
</span>
|
</span>
|
||||||
(+{lowReturnPercent})
|
(+{yesReturnPercent})
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
{highLimitProb !== undefined && (
|
{hasNoLimitBet && !hasTwoBets && (
|
||||||
<Row className="items-center justify-between gap-2 text-sm">
|
<Row className="items-center justify-between gap-2 text-sm">
|
||||||
<Row className="flex-nowrap items-center gap-2 whitespace-nowrap text-gray-500">
|
<Row className="flex-nowrap items-center gap-2 whitespace-nowrap text-gray-500">
|
||||||
<div>
|
<div>
|
||||||
|
@ -595,22 +682,20 @@ function RangeOrderPanel(props: {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<InfoTooltip
|
<InfoTooltip
|
||||||
text={`Includes ${formatMoneyWithDecimals(highFees)} in fees`}
|
text={`Includes ${formatMoneyWithDecimals(noFees)} in fees`}
|
||||||
/>
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
<div>
|
<div>
|
||||||
<span className="mr-2 whitespace-nowrap">
|
<span className="mr-2 whitespace-nowrap">
|
||||||
{formatMoney(highPayout)}
|
{formatMoney(noPayout)}
|
||||||
</span>
|
</span>
|
||||||
(+{highReturnPercent})
|
(+{noReturnPercent})
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
{(lowLimitProb !== undefined || highLimitProb !== undefined) && (
|
{(hasYesLimitBet || hasNoLimitBet) && <Spacer h={8} />}
|
||||||
<Spacer h={8} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{user && (
|
{user && (
|
||||||
<button
|
<button
|
||||||
|
@ -625,7 +710,9 @@ function RangeOrderPanel(props: {
|
||||||
)}
|
)}
|
||||||
onClick={betDisabled ? undefined : submitBet}
|
onClick={betDisabled ? undefined : submitBet}
|
||||||
>
|
>
|
||||||
{isSubmitting ? 'Submitting...' : 'Submit order'}
|
{isSubmitting
|
||||||
|
? 'Submitting...'
|
||||||
|
: `Submit order${hasTwoBets ? 's' : ''}`}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ export function BucketInput(props: {
|
||||||
error={undefined}
|
error={undefined}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
numberString={numberString}
|
numberString={numberString}
|
||||||
label="Value"
|
label=""
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user