Your outcome/cost=> acceptorOutcome/cost
This commit is contained in:
parent
5cb6f44c9c
commit
4252157290
|
@ -19,7 +19,8 @@ export type Challenge = {
|
|||
creatorOutcome: string
|
||||
|
||||
// Different than the creator
|
||||
yourOutcome: string
|
||||
acceptorOutcome: string
|
||||
acceptorAmount: number
|
||||
|
||||
// The probability the challenger thinks
|
||||
creatorOutcomeProb: number
|
||||
|
@ -51,9 +52,6 @@ export type Acceptance = {
|
|||
userName: string
|
||||
userAvatarUrl: string
|
||||
|
||||
// The amount acceptor put up
|
||||
amount: number
|
||||
|
||||
// The ID of the successful bet that tracks the money moved
|
||||
betId: string
|
||||
|
||||
|
|
|
@ -50,13 +50,15 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
|
|||
if (!creatorSnap.exists) throw new APIError(400, 'User not found.')
|
||||
const creator = creatorSnap.data() as User
|
||||
|
||||
const { creatorAmount, yourOutcome, creatorOutcome, creatorOutcomeProb } =
|
||||
challenge
|
||||
const {
|
||||
creatorAmount,
|
||||
acceptorOutcome,
|
||||
creatorOutcome,
|
||||
creatorOutcomeProb,
|
||||
acceptorAmount,
|
||||
} = challenge
|
||||
|
||||
const yourCost =
|
||||
((1 - creatorOutcomeProb) / creatorOutcomeProb) * creatorAmount
|
||||
|
||||
if (user.balance < yourCost)
|
||||
if (user.balance < acceptorAmount)
|
||||
throw new APIError(400, 'Insufficient balance.')
|
||||
|
||||
const contract = anyContract as CPMMBinaryContract
|
||||
|
@ -67,21 +69,21 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
|
|||
'Creating challenge bet for',
|
||||
user.username,
|
||||
shares,
|
||||
yourOutcome,
|
||||
acceptorOutcome,
|
||||
'shares',
|
||||
'at',
|
||||
formatPercent(creatorOutcomeProb),
|
||||
'for',
|
||||
formatMoney(yourCost)
|
||||
formatMoney(acceptorAmount)
|
||||
)
|
||||
|
||||
const yourNewBet: CandidateBet = removeUndefinedProps({
|
||||
orderAmount: yourCost,
|
||||
amount: yourCost,
|
||||
orderAmount: acceptorAmount,
|
||||
amount: acceptorAmount,
|
||||
shares: shares,
|
||||
isCancelled: false,
|
||||
contractId: contract.id,
|
||||
outcome: yourOutcome,
|
||||
outcome: acceptorOutcome,
|
||||
probBefore: creatorOutcomeProb,
|
||||
probAfter: creatorOutcomeProb,
|
||||
loanAmount: 0,
|
||||
|
@ -134,7 +136,7 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
|
|||
userId: user.id,
|
||||
betId: yourNewBetDoc.id,
|
||||
createdTime,
|
||||
amount: yourCost,
|
||||
amount: acceptorAmount,
|
||||
userUsername: user.username,
|
||||
userName: user.name,
|
||||
userAvatarUrl: user.avatarUrl,
|
||||
|
@ -147,7 +149,7 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
|
|||
user,
|
||||
creator,
|
||||
challenge,
|
||||
yourCost,
|
||||
acceptorAmount,
|
||||
contract
|
||||
)
|
||||
log('Done, sent notification.')
|
||||
|
|
|
@ -17,7 +17,7 @@ function buildCardUrl(props: OgCardProps, challenge?: Challenge) {
|
|||
acceptances,
|
||||
creatorOutcomeProb,
|
||||
creatorOutcome,
|
||||
yourOutcome,
|
||||
acceptorOutcome,
|
||||
} = challenge || {}
|
||||
const { userName, userAvatarUrl } = acceptances?.[0] ?? {}
|
||||
const challengeAmount =
|
||||
|
@ -35,7 +35,7 @@ function buildCardUrl(props: OgCardProps, challenge?: Challenge) {
|
|||
|
||||
const challengeUrlParams = challenge
|
||||
? `&creatorAmount=${creatorAmount}&creatorOutcome=${creatorOutcome}` +
|
||||
`&challengerAmount=${challengeAmount}&challengerOutcome=${yourOutcome}` +
|
||||
`&challengerAmount=${challengeAmount}&challengerOutcome=${acceptorOutcome}` +
|
||||
`&acceptedName=${userName ?? ''}&acceptedAvatarUrl=${userAvatarUrl ?? ''}`
|
||||
: ''
|
||||
|
||||
|
|
|
@ -21,9 +21,8 @@ export function AcceptChallengeButton(props: {
|
|||
const [open, setOpen] = useState(false)
|
||||
const [errorText, setErrorText] = useState('')
|
||||
const [loading, setLoading] = useState(false)
|
||||
const { creatorOutcomeProb, creatorAmount } = challenge
|
||||
const yourCost =
|
||||
((1 - creatorOutcomeProb) / creatorOutcomeProb) * creatorAmount
|
||||
const { acceptorAmount } = challenge
|
||||
|
||||
useEffect(() => {
|
||||
setErrorText('')
|
||||
}, [open])
|
||||
|
@ -69,7 +68,9 @@ export function AcceptChallengeButton(props: {
|
|||
<Col className="w-full items-center justify-start gap-2">
|
||||
<Row className={'w-full justify-start gap-20'}>
|
||||
<span className={'min-w-[4rem] font-bold'}>Cost to you:</span>{' '}
|
||||
<span className={'text-red-500'}>{formatMoney(yourCost)}</span>
|
||||
<span className={'text-red-500'}>
|
||||
{formatMoney(acceptorAmount)}
|
||||
</span>
|
||||
</Row>
|
||||
{/*<Row className={'w-full justify-start gap-8'}>*/}
|
||||
{/* <span className={'min-w-[4rem] font-bold'}>Probability:</span>{' '}*/}
|
||||
|
|
|
@ -23,7 +23,7 @@ type challengeInfo = {
|
|||
expiresTime: number | null
|
||||
message: string
|
||||
outcome: 'YES' | 'NO' | number
|
||||
prob: number
|
||||
acceptorAmount: number
|
||||
}
|
||||
export function CreateChallengeButton(props: {
|
||||
user: User | null | undefined
|
||||
|
@ -45,10 +45,10 @@ export function CreateChallengeButton(props: {
|
|||
onCreate={async (newChallenge) => {
|
||||
const challenge = await createChallenge({
|
||||
creator: user,
|
||||
amount: newChallenge.amount,
|
||||
creatorAmount: newChallenge.amount,
|
||||
expiresTime: newChallenge.expiresTime,
|
||||
message: newChallenge.message,
|
||||
prob: newChallenge.prob / 100,
|
||||
acceptorAmount: newChallenge.acceptorAmount,
|
||||
outcome: newChallenge.outcome,
|
||||
contract: contract,
|
||||
})
|
||||
|
@ -90,7 +90,7 @@ function CreateChallengeForm(props: {
|
|||
expiresTime: dayjs().add(2, defaultExpire).valueOf(),
|
||||
outcome: 'YES',
|
||||
amount: 100,
|
||||
prob: prob * 100,
|
||||
acceptorAmount: 100,
|
||||
message: defaultMessage,
|
||||
})
|
||||
useEffect(() => {
|
||||
|
@ -119,7 +119,8 @@ function CreateChallengeForm(props: {
|
|||
<Title className="!mt-2" text="Challenge a friend to bet " />
|
||||
{/*<Row className="label ">How much?</Row>*/}
|
||||
<div className="mt-2 flex flex-col flex-wrap gap-x-5 gap-y-2">
|
||||
<div className="mb-4 italic">{contract.question}</div>
|
||||
{/*<div>Question:</div>*/}
|
||||
{/*<div className="mb-4 italic">{contract.question}</div>*/}
|
||||
|
||||
<div>You are betting:</div>
|
||||
<Row className={'form-control w-full justify-start gap-4'}>
|
||||
|
@ -166,52 +167,6 @@ function CreateChallengeForm(props: {
|
|||
<span className="bold">{formatMoney(friendCost)}</span> on{' '}
|
||||
{challengeInfo.outcome === 'YES' ? <NoLabel /> : <YesLabel />}
|
||||
</div>
|
||||
{/*<div className="form-control flex flex-row gap-8">*/}
|
||||
{/* /!*<Col className={'mt-9 justify-center'}>at</Col>*!/*/}
|
||||
{/* <Col>*/}
|
||||
{/* <label className="label ">At</label>*/}
|
||||
{/* <div className="relative">*/}
|
||||
{/* <input*/}
|
||||
{/* className="input input-bordered max-w-[5rem]"*/}
|
||||
{/* type="number"*/}
|
||||
{/* min={1}*/}
|
||||
{/* max={100}*/}
|
||||
{/* value={challengeInfo.prob}*/}
|
||||
{/* onChange={(e) =>*/}
|
||||
{/* setChallengeInfo((m: challengeInfo) => {*/}
|
||||
{/* return {*/}
|
||||
{/* ...m,*/}
|
||||
{/* prob: parseFloat(e.target.value),*/}
|
||||
{/* }*/}
|
||||
{/* })*/}
|
||||
{/* }*/}
|
||||
{/* />*/}
|
||||
{/* <span className="absolute top-3.5 -right-5 text-sm text-gray-600">*/}
|
||||
{/* %*/}
|
||||
{/* </span>*/}
|
||||
{/* </div>*/}
|
||||
{/* </Col>*/}
|
||||
{/*</div>*/}
|
||||
|
||||
{/*<div className="form-control w-full">*/}
|
||||
{/* <label className="label">Message</label>*/}
|
||||
{/* <Textarea*/}
|
||||
{/* placeholder={defaultMessage}*/}
|
||||
{/* className="input input-bordered resize-none"*/}
|
||||
{/* autoFocus*/}
|
||||
{/* value={*/}
|
||||
{/* challengeInfo.message !== defaultMessage*/}
|
||||
{/* ? challengeInfo.message*/}
|
||||
{/* : ''*/}
|
||||
{/* }*/}
|
||||
{/* rows={2}*/}
|
||||
{/* onChange={(e) =>*/}
|
||||
{/* setChallengeInfo((m: challengeInfo) => {*/}
|
||||
{/* return { ...m, message: e.target.value }*/}
|
||||
{/* })*/}
|
||||
{/* }*/}
|
||||
{/* />*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
<Row className={'justify-end'}>
|
||||
<Button
|
||||
|
|
|
@ -25,14 +25,21 @@ export function getChallengeUrl(challenge: Challenge) {
|
|||
export async function createChallenge(data: {
|
||||
creator: User
|
||||
outcome: 'YES' | 'NO' | number
|
||||
prob: number
|
||||
contract: Contract
|
||||
amount: number
|
||||
creatorAmount: number
|
||||
acceptorAmount: number
|
||||
expiresTime: number | null
|
||||
message: string
|
||||
}) {
|
||||
const { creator, amount, expiresTime, message, prob, contract, outcome } =
|
||||
data
|
||||
const {
|
||||
creator,
|
||||
creatorAmount,
|
||||
expiresTime,
|
||||
message,
|
||||
contract,
|
||||
outcome,
|
||||
acceptorAmount,
|
||||
} = data
|
||||
|
||||
// At 100 IDs per hour, using this alphabet and 8 chars, there's a 1% chance of collision in 2 years
|
||||
// See https://zelark.github.io/nano-id-cc/
|
||||
|
@ -42,7 +49,10 @@ export async function createChallenge(data: {
|
|||
)
|
||||
const slug = nanoid()
|
||||
|
||||
if (amount <= 0 || isNaN(amount) || !isFinite(amount)) return null
|
||||
if (creatorAmount <= 0 || isNaN(creatorAmount) || !isFinite(creatorAmount))
|
||||
return null
|
||||
|
||||
const prob = 1 / (acceptorAmount / creatorAmount + 1)
|
||||
|
||||
const challenge: Challenge = {
|
||||
slug,
|
||||
|
@ -50,12 +60,13 @@ export async function createChallenge(data: {
|
|||
creatorUsername: creator.username,
|
||||
creatorName: creator.name,
|
||||
creatorAvatarUrl: creator.avatarUrl,
|
||||
creatorAmount: amount,
|
||||
creatorAmount: creatorAmount,
|
||||
contractSlug: contract.slug,
|
||||
contractId: contract.id,
|
||||
creatorOutcome: outcome.toString(),
|
||||
yourOutcome: outcome === 'YES' ? 'NO' : 'YES',
|
||||
acceptorOutcome: outcome === 'YES' ? 'NO' : 'YES',
|
||||
creatorOutcomeProb: prob,
|
||||
acceptorAmount,
|
||||
createdTime: Date.now(),
|
||||
expiresTime,
|
||||
maxUses: 1,
|
||||
|
|
|
@ -141,7 +141,8 @@ function ClosedChallengeContent(props: {
|
|||
creatorAmount,
|
||||
creatorOutcome,
|
||||
creatorOutcomeProb,
|
||||
yourOutcome,
|
||||
acceptorOutcome,
|
||||
acceptorAmount,
|
||||
} = challenge
|
||||
|
||||
const user = useUserById(acceptances[0].userId)
|
||||
|
@ -155,9 +156,7 @@ function ClosedChallengeContent(props: {
|
|||
}, [acceptances])
|
||||
|
||||
const creatorWon = resolution === creatorOutcome
|
||||
// const amountWon = creatorWon ? acceptances[0].amount : creatorAmount
|
||||
const yourCost =
|
||||
((1 - creatorOutcomeProb) / creatorOutcomeProb) * creatorAmount
|
||||
const amountWon = creatorWon ? acceptorAmount : creatorAmount
|
||||
|
||||
const href = `https://${DOMAIN}${contractPath(contract)}`
|
||||
|
||||
|
@ -211,8 +210,8 @@ function ClosedChallengeContent(props: {
|
|||
|
||||
<UserBetColumn
|
||||
challenger={user?.id === creator.id ? undefined : user}
|
||||
outcome={yourOutcome}
|
||||
amount={yourCost}
|
||||
outcome={acceptorOutcome}
|
||||
amount={acceptorAmount}
|
||||
isResolved={!!resolution}
|
||||
/>
|
||||
</Col>
|
||||
|
@ -240,14 +239,12 @@ function OpenChallengeContent(props: {
|
|||
creatorAmount,
|
||||
creatorId,
|
||||
creatorOutcome,
|
||||
creatorOutcomeProb,
|
||||
yourOutcome,
|
||||
acceptorAmount,
|
||||
acceptorOutcome,
|
||||
} = challenge
|
||||
|
||||
const yourCost =
|
||||
((1 - creatorOutcomeProb) / creatorOutcomeProb) * creatorAmount
|
||||
|
||||
const href = `https://${DOMAIN}${contractPath(contract)}`
|
||||
|
||||
const title = `${creator.name} is challenging you to bet`
|
||||
|
||||
return (
|
||||
|
@ -276,8 +273,8 @@ function OpenChallengeContent(props: {
|
|||
|
||||
<UserBetColumn
|
||||
challenger={user?.id === creatorId ? undefined : user}
|
||||
outcome={yourOutcome}
|
||||
amount={yourCost}
|
||||
outcome={acceptorOutcome}
|
||||
amount={acceptorAmount}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user