manifold/functions/src/place-bet.ts

70 lines
2.3 KiB
TypeScript
Raw Normal View History

2021-12-11 00:06:17 +00:00
import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
import { Contract } from '../../common/contract'
import { User } from '../../common/user'
2022-01-10 22:49:04 +00:00
import { getNewBetInfo } from '../../common/new-bet'
2021-12-11 00:06:17 +00:00
export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
async (
data: {
amount: number
outcome: string
contractId: string
},
context
) => {
2021-12-11 03:45:05 +00:00
const userId = context?.auth?.uid
if (!userId) return { status: 'error', message: 'Not authorized' }
2021-12-11 03:45:05 +00:00
const { amount, outcome, contractId } = data
2022-01-08 17:51:31 +00:00
if (amount <= 0 || isNaN(amount) || !isFinite(amount))
return { status: 'error', message: 'Invalid amount' }
2021-12-11 03:45:05 +00:00
if (outcome !== 'YES' && outcome !== 'NO')
return { status: 'error', message: 'Invalid outcome' }
// run as transaction to prevent race conditions
return await firestore.runTransaction(async (transaction) => {
2021-12-11 03:45:05 +00:00
const userDoc = firestore.doc(`users/${userId}`)
const userSnap = await transaction.get(userDoc)
if (!userSnap.exists)
return { status: 'error', message: 'User not found' }
2021-12-11 03:45:05 +00:00
const user = userSnap.data() as User
2021-12-13 17:58:47 +00:00
if (user.balance < amount)
2021-12-11 03:45:05 +00:00
return { status: 'error', message: 'Insufficient balance' }
const contractDoc = firestore.doc(`contracts/${contractId}`)
const contractSnap = await transaction.get(contractDoc)
if (!contractSnap.exists)
return { status: 'error', message: 'Invalid contract' }
2021-12-11 03:45:05 +00:00
const contract = contractSnap.data() as Contract
const { closeTime } = contract
if (closeTime && Date.now() > closeTime)
return { status: 'error', message: 'Trading is closed' }
const newBetDoc = firestore
.collection(`contracts/${contractId}/bets`)
.doc()
2021-12-11 03:45:05 +00:00
const { newBet, newPool, newTotalShares, newTotalBets, newBalance } =
getNewBetInfo(user, outcome, amount, contract, newBetDoc.id)
2021-12-11 03:45:05 +00:00
transaction.create(newBetDoc, newBet)
2021-12-17 22:15:09 +00:00
transaction.update(contractDoc, {
pool: newPool,
totalShares: newTotalShares,
totalBets: newTotalBets,
2021-12-17 22:15:09 +00:00
})
2021-12-13 17:58:47 +00:00
transaction.update(userDoc, { balance: newBalance })
2021-12-11 03:45:05 +00:00
2022-01-06 18:55:31 +00:00
return { status: 'success', betId: newBetDoc.id }
2021-12-11 03:45:05 +00:00
})
}
)
2021-12-11 00:06:17 +00:00
const firestore = admin.firestore()