fix accept challenge: don't change pool/probability

This commit is contained in:
mantikoros 2022-07-26 10:57:51 -07:00
parent 776e0cd86d
commit cecf696e1f

View File

@ -8,20 +8,22 @@ import { FieldValue } from 'firebase-admin/firestore'
import { removeUndefinedProps } from '../../common/util/object' import { removeUndefinedProps } from '../../common/util/object'
import { Acceptance, Challenge } from '../../common/challenge' import { Acceptance, Challenge } from '../../common/challenge'
import { CandidateBet } from '../../common/new-bet' import { CandidateBet } from '../../common/new-bet'
import { getCpmmProbability } from '../../common/calculate-cpmm'
import { createChallengeAcceptedNotification } from './create-notification' import { createChallengeAcceptedNotification } from './create-notification'
import { noFees } from 'common/fees'
import { formatMoney, formatPercent } from 'common/util/format'
const bodySchema = z.object({ const bodySchema = z.object({
contractId: z.string(), contractId: z.string(),
challengeSlug: z.string(), challengeSlug: z.string(),
outcomeType: z.literal('BINARY'),
closeTime: z.number().gte(Date.now()),
}) })
const firestore = admin.firestore() const firestore = admin.firestore()
export const acceptchallenge = newEndpoint({}, async (req, auth) => { export const acceptchallenge = newEndpoint({}, async (req, auth) => {
log('Inside endpoint handler.')
const { challengeSlug, contractId } = validate(bodySchema, req.body) const { challengeSlug, contractId } = validate(bodySchema, req.body)
const result = await firestore.runTransaction(async (trans) => { const result = await firestore.runTransaction(async (trans) => {
log('Inside main transaction.')
const contractDoc = firestore.doc(`contracts/${contractId}`) const contractDoc = firestore.doc(`contracts/${contractId}`)
const userDoc = firestore.doc(`users/${auth.uid}`) const userDoc = firestore.doc(`users/${auth.uid}`)
const challengeDoc = firestore.doc( const challengeDoc = firestore.doc(
@ -35,7 +37,6 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
if (!contractSnap.exists) throw new APIError(400, 'Contract not found.') if (!contractSnap.exists) throw new APIError(400, 'Contract not found.')
if (!userSnap.exists) throw new APIError(400, 'User not found.') if (!userSnap.exists) throw new APIError(400, 'User not found.')
if (!challengeSnap.exists) throw new APIError(400, 'Challenge not found.') if (!challengeSnap.exists) throw new APIError(400, 'Challenge not found.')
log('Loaded user and contract snapshots.')
const anyContract = contractSnap.data() as Contract const anyContract = contractSnap.data() as Contract
const user = userSnap.data() as User const user = userSnap.data() as User
@ -51,28 +52,28 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
const { creatorAmount, yourOutcome, creatorsOutcome, creatorsOutcomeProb } = const { creatorAmount, yourOutcome, creatorsOutcome, creatorsOutcomeProb } =
challenge challenge
const yourCost = const yourCost =
((1 - creatorsOutcomeProb) / creatorsOutcomeProb) * creatorAmount ((1 - creatorsOutcomeProb) / creatorsOutcomeProb) * creatorAmount
if (user.balance < yourCost) if (user.balance < yourCost)
throw new APIError(400, 'Insufficient balance.') throw new APIError(400, 'Insufficient balance.')
const { closeTime, outcomeType } = anyContract
if (closeTime && Date.now() > closeTime)
throw new APIError(400, 'Trading is closed.')
if (outcomeType !== 'BINARY')
throw new APIError(400, 'Challenges only accepted for binary markets.')
const contract = anyContract as CPMMBinaryContract const contract = anyContract as CPMMBinaryContract
const { YES: y, NO: n } = contract.pool
const shares = (1 / creatorsOutcomeProb) * creatorAmount const shares = (1 / creatorsOutcomeProb) * creatorAmount
const createdTime = Date.now()
const newPool = { log(
YES: y + shares, 'Creating challenge bet for',
NO: n + shares, user.username,
} shares,
const probBefore = getCpmmProbability(contract.pool, contract.p) yourOutcome,
const probAfter = getCpmmProbability(newPool, contract.p) 'shares',
'at',
formatPercent(creatorsOutcomeProb),
'for',
formatMoney(yourCost)
)
const yourNewBet: CandidateBet = removeUndefinedProps({ const yourNewBet: CandidateBet = removeUndefinedProps({
orderAmount: yourCost, orderAmount: yourCost,
@ -81,22 +82,21 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
isCancelled: false, isCancelled: false,
contractId: contract.id, contractId: contract.id,
outcome: yourOutcome, outcome: yourOutcome,
probBefore, probBefore: creatorsOutcomeProb,
probAfter, probAfter: creatorsOutcomeProb,
loanAmount: 0, loanAmount: 0,
createdTime: Date.now(), createdTime,
fees: { creatorFee: 0, platformFee: 0, liquidityFee: 0 }, fees: noFees,
}) })
const yourNewBetDoc = contractDoc.collection('bets').doc() const yourNewBetDoc = contractDoc.collection('bets').doc()
trans.create(yourNewBetDoc, { trans.create(yourNewBetDoc, {
id: yourNewBetDoc.id, id: yourNewBetDoc.id,
userId: user.id, userId: user.id,
...yourNewBet, ...yourNewBet,
}) })
log('Created new bet document.')
trans.update(userDoc, { balance: FieldValue.increment(-yourNewBet.amount) }) trans.update(userDoc, { balance: FieldValue.increment(-yourNewBet.amount) })
log('Updated user balance.')
const creatorNewBet: CandidateBet = removeUndefinedProps({ const creatorNewBet: CandidateBet = removeUndefinedProps({
orderAmount: creatorAmount, orderAmount: creatorAmount,
@ -105,11 +105,11 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
isCancelled: false, isCancelled: false,
contractId: contract.id, contractId: contract.id,
outcome: creatorsOutcome, outcome: creatorsOutcome,
probBefore, probBefore: creatorsOutcomeProb,
probAfter, probAfter: creatorsOutcomeProb,
loanAmount: 0, loanAmount: 0,
createdTime: Date.now(), createdTime,
fees: { creatorFee: 0, platformFee: 0, liquidityFee: 0 }, fees: noFees,
}) })
const creatorBetDoc = contractDoc.collection('bets').doc() const creatorBetDoc = contractDoc.collection('bets').doc()
trans.create(creatorBetDoc, { trans.create(creatorBetDoc, {
@ -117,21 +117,13 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
userId: creator.id, userId: creator.id,
...creatorNewBet, ...creatorNewBet,
}) })
log('Created new bet document.')
trans.update(creatorDoc, { trans.update(creatorDoc, {
balance: FieldValue.increment(-creatorNewBet.amount), balance: FieldValue.increment(-creatorNewBet.amount),
}) })
log('Updated user balance.')
trans.update( const volume = contract.volume + yourNewBet.amount + creatorNewBet.amount
contractDoc, trans.update(contractDoc, { volume })
removeUndefinedProps({
pool: newPool,
volume: contract.volume + yourNewBet.amount + creatorNewBet.amount,
})
)
log('Updated contract properties.')
trans.update( trans.update(
challengeDoc, challengeDoc,
@ -141,7 +133,7 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
{ {
userId: user.id, userId: user.id,
betId: yourNewBetDoc.id, betId: yourNewBetDoc.id,
createdTime: Date.now(), createdTime,
amount: yourCost, amount: yourCost,
userUsername: user.username, userUsername: user.username,
userName: user.name, userName: user.name,
@ -150,7 +142,6 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
], ],
}) })
) )
log('Updated challenge properties with new acceptance.')
await createChallengeAcceptedNotification( await createChallengeAcceptedNotification(
user, user,
@ -159,7 +150,7 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
yourCost, yourCost,
contract contract
) )
log('Created notification.') log('Done, sent notification.')
return yourNewBetDoc return yourNewBetDoc
}) })