diff --git a/common/new-bet.ts b/common/new-bet.ts index 9b5e591b..c000b764 100644 --- a/common/new-bet.ts +++ b/common/new-bet.ts @@ -265,6 +265,53 @@ export const getBinaryBetStats = ( return { currentPayout, currentReturn, totalFees } } +export const getBinaryRangeBetInfo = ( + betAmount: number, + contract: CPMMBinaryContract | PseudoNumericContract, + lowLimitProb: number, + highLimitProb: number, + unfilledBets: LimitBet[] +) => { + const shares = Math.min( + betAmount / lowLimitProb, + betAmount / (1 - highLimitProb) + ) + const yesAmount = shares * lowLimitProb + const noAmount = shares * (1 - highLimitProb) + + const yesResult = getBinaryCpmmBetInfo( + 'YES', + yesAmount, + contract, + lowLimitProb, + unfilledBets + ) + const noResult = getBinaryCpmmBetInfo( + 'NO', + noAmount, + { + ...contract, + pool: yesResult.newPool, + p: yesResult.newP, + totalLiquidity: yesResult.newTotalLiquidity, + }, + highLimitProb, + unfilledBets + ) + + const { newP, newPool, newTotalLiquidity } = noResult + const makers = [...yesResult.makers, ...noResult.makers] + + return { + yesBet: yesResult.newBet, + noBet: noResult.newBet, + newP, + newPool, + newTotalLiquidity, + makers, + } +} + export const getNewBinaryDpmBetInfo = ( outcome: 'YES' | 'NO', amount: number, diff --git a/functions/src/place-bet.ts b/functions/src/place-bet.ts index 97ff9780..12589752 100644 --- a/functions/src/place-bet.ts +++ b/functions/src/place-bet.ts @@ -14,6 +14,7 @@ import { User } from '../../common/user' import { BetInfo, getBinaryCpmmBetInfo, + getBinaryRangeBetInfo, getNewMultiBetInfo, getNumericBetsInfo, } from '../../common/new-bet' @@ -28,10 +29,16 @@ const bodySchema = z.object({ amount: z.number().gte(1), }) -const binarySchema = z.object({ - outcome: z.enum(['YES', 'NO']), - limitProb: z.number().gte(0.001).lte(0.999).optional(), -}) +const binarySchema = z.union([ + z.object({ + outcome: z.enum(['YES', 'NO']), + limitProb: z.number().gte(0.001).lte(0.999).optional(), + }), + z.object({ + lowLimitProb: z.number().gte(0.001).lte(0.999), + highLimitProb: z.number().gte(0.001).lte(0.999), + }), +]) const freeResponseSchema = z.object({ outcome: z.string(), @@ -82,20 +89,32 @@ export const placebet = newEndpoint({}, async (req, auth) => { (outcomeType == 'BINARY' || outcomeType === 'PSEUDO_NUMERIC') && mechanism == 'cpmm-1' ) { - const { outcome, limitProb } = validate(binarySchema, req.body) - const unfilledBetsSnap = await trans.get( getUnfilledBetsQuery(contractDoc) ) const unfilledBets = unfilledBetsSnap.docs.map((doc) => doc.data()) + const data = validate(binarySchema, req.body) + if ('outcome' in data) { + const { outcome, limitProb } = data - return getBinaryCpmmBetInfo( - outcome, - amount, - contract, - limitProb, - unfilledBets - ) + return getBinaryCpmmBetInfo( + outcome, + amount, + contract, + limitProb, + unfilledBets + ) + } else { + const { lowLimitProb, highLimitProb } = data + const result = getBinaryRangeBetInfo( + amount, + contract, + lowLimitProb, + highLimitProb, + unfilledBets + ) + return { newBet: result.yesBet, ...result } + } } else if (outcomeType == 'FREE_RESPONSE' && mechanism == 'dpm-2') { const { outcome } = validate(freeResponseSchema, req.body) const answerDoc = contractDoc.collection('answers').doc(outcome)