diff --git a/common/calculate.ts b/common/calculate.ts index 06820edc..4c11a660 100644 --- a/common/calculate.ts +++ b/common/calculate.ts @@ -161,6 +161,7 @@ export function getContractBetMetrics(contract: Contract, yourBets: Bet[]) { return { invested: Math.max(0, currentInvested), + currentInvested, payout, netPayout, profit, @@ -189,3 +190,29 @@ export function getTopAnswer(contract: FreeResponseContract) { ) return top?.answer } + +export function hasUserHitManaLimit( + contract: FreeResponseContract, + bets: Bet[], + amount: number +) { + const { manaLimitPerUser } = contract + if (manaLimitPerUser) { + const contractMetrics = getContractBetMetrics(contract, bets) + const currentInvested = contractMetrics.currentInvested + console.log('user current invested amount', currentInvested) + console.log('mana limit:', manaLimitPerUser) + + if (currentInvested + amount > manaLimitPerUser) { + const manaAllowed = manaLimitPerUser - currentInvested + return { + status: 'error', + message: `Market bet cap is M$${manaLimitPerUser}, you've M$${manaAllowed} left`, + } + } + } + return { + status: 'success', + message: '', + } +} diff --git a/common/contract.ts b/common/contract.ts index 82a330b5..3434d6d6 100644 --- a/common/contract.ts +++ b/common/contract.ts @@ -31,6 +31,8 @@ export type FullContract< closeEmailsSent?: number + manaLimitPerUser?: number + volume: number volume24Hours: number volume7Days: number diff --git a/common/new-contract.ts b/common/new-contract.ts index b86ebb71..764d32d3 100644 --- a/common/new-contract.ts +++ b/common/new-contract.ts @@ -22,7 +22,8 @@ export function getNewContract( initialProb: number, ante: number, closeTime: number, - extraTags: string[] + extraTags: string[], + manaLimitPerUser: number ) { const tags = parseTags( `${question} ${description} ${extraTags.map((tag) => `#${tag}`).join(' ')}` @@ -64,6 +65,7 @@ export function getNewContract( liquidityFee: 0, platformFee: 0, }, + manaLimitPerUser, }) return contract as Contract diff --git a/functions/src/create-answer.ts b/functions/src/create-answer.ts index 1da8f350..9f303630 100644 --- a/functions/src/create-answer.ts +++ b/functions/src/create-answer.ts @@ -12,7 +12,11 @@ import { getLoanAmount, getNewMultiBetInfo } from '../../common/new-bet' import { Answer, MAX_ANSWER_LENGTH } from '../../common/answer' import { getContract, getValues } from './utils' import { sendNewAnswerEmail } from './emails' -import { Bet } from '../../common/bet' +import { Bet } from 'common/bet' +import { + getContractBetMetrics, + hasUserHitManaLimit, +} from 'common/calculate' export const createAnswer = functions.runWith({ minInstances: 1 }).https.onCall( async ( @@ -66,6 +70,13 @@ export const createAnswer = functions.runWith({ minInstances: 1 }).https.onCall( ) const yourBets = yourBetsSnap.docs.map((doc) => doc.data() as Bet) + const { status, message } = hasUserHitManaLimit( + contract, + yourBets, + amount + ) + if (status === 'error') return { status, message: message } + const [lastAnswer] = await getValues( firestore .collection(`contracts/${contractId}/answers`) diff --git a/functions/src/create-contract.ts b/functions/src/create-contract.ts index dfc8128d..322579a5 100644 --- a/functions/src/create-contract.ts +++ b/functions/src/create-contract.ts @@ -39,6 +39,7 @@ export const createContract = functions ante: number closeTime: number tags?: string[] + manaLimitPerUser?: number }, context ) => { @@ -48,7 +49,14 @@ export const createContract = functions const creator = await getUser(userId) if (!creator) return { status: 'error', message: 'User not found' } - let { question, description, initialProb, closeTime, tags } = data + let { + question, + description, + initialProb, + closeTime, + tags, + manaLimitPerUser, + } = data if (!question || typeof question != 'string') return { status: 'error', message: 'Missing or invalid question field' } @@ -115,7 +123,8 @@ export const createContract = functions initialProb, ante, closeTime, - tags ?? [] + tags ?? [], + manaLimitPerUser ?? 0 ) if (!isFree && ante) await chargeUser(creator.id, ante) diff --git a/functions/src/place-bet.ts b/functions/src/place-bet.ts index 74487126..4d76c824 100644 --- a/functions/src/place-bet.ts +++ b/functions/src/place-bet.ts @@ -12,7 +12,11 @@ import { import { addObjects, removeUndefinedProps } from '../../common/util/object' import { Bet } from '../../common/bet' import { redeemShares } from './redeem-shares' -import { Fees } from '../../common/fees' +import { Fees } from 'common/fees' +import { + getContractBetMetrics, + hasUserHitManaLimit, +} from 'common/calculate' export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall( async ( @@ -69,6 +73,13 @@ export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall( ) if (!answerSnap.exists) return { status: 'error', message: 'Invalid contract' } + + const { status, message } = hasUserHitManaLimit( + contract, + yourBets, + amount + ) + if (status === 'error') return { status, message: message } } const newBetDoc = firestore diff --git a/web/components/answers/answer-bet-panel.tsx b/web/components/answers/answer-bet-panel.tsx index e0984f6a..ab4c9600 100644 --- a/web/components/answers/answer-bet-panel.tsx +++ b/web/components/answers/answer-bet-panel.tsx @@ -66,7 +66,7 @@ export function AnswerBetPanel(props: { setBetAmount(undefined) props.closePanel() } else { - setError(result?.error || 'Error placing bet') + setError(result?.message || 'Error placing bet') setIsSubmitting(false) } }