manifold/functions/src/create-contract.ts
mantikoros 9d5490cf9a
Switch to new dpm mechanism (#26)
* initial commit

* antes

* rename path, compute to contractPath, contractMetrics

* merge

* Include antes as bets; more calculations

* fees on estimated winnings

* mkt payout calculation

* contract: remove startPool, add phantomShares

* Merge branch 'main' into new-dpm

* dpm migration script

* my service account
2022-01-12 13:01:04 -06:00

112 lines
2.8 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'
import { getAnteBets } 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 (
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)
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) => {
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)
}