manifold/functions/src/create-contract.ts
2022-01-10 16:49:13 -06:00

91 lines
2.3 KiB
TypeScript

import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
import { chargeUser, getUser } from './utils'
import { Contract } from '../../common/contract'
import { slugify } from '../../common/util/slugify'
import { randomString } from '../../common/util/random-string'
import { getNewContract } from '../../common/new-contract'
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 (
ante !== undefined &&
(ante < 0 || ante > creator.balance || isNaN(ante) || !isFinite(ante))
)
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
)
if (ante) await chargeUser(creator.id, ante)
await contractRef.create(contract)
return { status: 'success', contract }
}
)
const getSlug = async (question: string) => {
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)
}