manifold/functions/src/create-contract.ts

118 lines
3.0 KiB
TypeScript
Raw Normal View History

import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
2022-01-10 22:49:04 +00:00
import { chargeUser, getUser } from './utils'
import { Contract } from '../../common/contract'
import { slugify } from '../../common/util/slugify'
import { randomString } from '../../common/util/random'
2022-01-10 22:49:04 +00:00
import { getNewContract } from '../../common/new-contract'
import { getAnteBets, MINIMUM_ANTE } from '../../common/antes'
export const createContract = functions
.runWith({ minInstances: 1 })
.https.onCall(
async (
data: {
question: string
description: string
initialProb: number
ante: number
closeTime: number
},
context
) => {
const userId = context?.auth?.uid
if (!userId) return { status: 'error', message: 'Not authorized' }
const creator = await getUser(userId)
if (!creator) return { status: 'error', message: 'User not found' }
const { question, description, initialProb, ante, closeTime } = data
if (!question || !initialProb)
return { status: 'error', message: 'Missing contract attributes' }
if (initialProb < 1 || initialProb > 99)
return { status: 'error', message: 'Invalid initial probability' }
2022-01-08 17:51:31 +00:00
if (
ante === undefined ||
ante < MINIMUM_ANTE ||
ante > creator.balance ||
isNaN(ante) ||
!isFinite(ante)
2022-01-08 17:51:31 +00:00
)
return { status: 'error', message: 'Invalid ante' }
console.log(
'creating contract for',
creator.username,
'on',
question,
'ante:',
ante || 0
)
const slug = await getSlug(question)
const contractRef = firestore.collection('contracts').doc()
const contract = getNewContract(
contractRef.id,
slug,
creator,
question,
description,
initialProb,
ante,
closeTime
)
2022-01-10 22:49:04 +00:00
if (ante) await chargeUser(creator.id, ante)
await contractRef.create(contract)
if (ante) {
const yesBetDoc = firestore
.collection(`contracts/${contract.id}/bets`)
.doc()
const noBetDoc = firestore
.collection(`contracts/${contract.id}/bets`)
.doc()
const { yesBet, noBet } = getAnteBets(
creator,
contract,
yesBetDoc.id,
noBetDoc.id
)
await yesBetDoc.set(yesBet)
await noBetDoc.set(noBet)
}
return { status: 'success', contract }
}
)
const getSlug = async (question: string) => {
2022-01-10 22:49:04 +00:00
const proposedSlug = slugify(question)
const preexistingContract = await getContractFromSlug(proposedSlug)
return preexistingContract
? proposedSlug + '-' + randomString()
: proposedSlug
}
const firestore = admin.firestore()
export async function getContractFromSlug(slug: string) {
const snap = await firestore
.collection('contracts')
.where('slug', '==', slug)
.get()
return snap.empty ? undefined : (snap.docs[0].data() as Contract)
}