Free response markets with investment cap (#157)
* Show error message for FR bet * Allow M$ limit for markets * Allow M$ limit for markets * Apply M$ limit to FR answer bets * Improve error message * Improve error message * Only check stats if mana limit set * Consolidate logic * Remove unused variable * absolute import * absolute imports
This commit is contained in:
parent
d55990d5d4
commit
a5b0372a6e
|
@ -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: '',
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ export type FullContract<
|
|||
|
||||
closeEmailsSent?: number
|
||||
|
||||
manaLimitPerUser?: number
|
||||
|
||||
volume: number
|
||||
volume24Hours: number
|
||||
volume7Days: number
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Answer>(
|
||||
firestore
|
||||
.collection(`contracts/${contractId}/answers`)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user