From b9f0da9d3bc7a86897934916bc3740c9558da3d2 Mon Sep 17 00:00:00 2001 From: Ian Philips Date: Thu, 25 Aug 2022 05:51:56 -0600 Subject: [PATCH] Give all users 5 free markets --- common/economy.ts | 1 + common/envs/prod.ts | 1 + common/user.ts | 1 + functions/src/create-market.ts | 27 ++++++++++++----- .../src/on-create-liquidity-provision.ts | 18 ++++++++++-- web/pages/create.tsx | 29 ++++++++++++++----- 6 files changed, 60 insertions(+), 17 deletions(-) diff --git a/common/economy.ts b/common/economy.ts index 8db4a7b9..c1449d4f 100644 --- a/common/economy.ts +++ b/common/economy.ts @@ -14,3 +14,4 @@ export const BETTING_STREAK_BONUS_AMOUNT = econ?.BETTING_STREAK_BONUS_AMOUNT ?? 10 export const BETTING_STREAK_BONUS_MAX = econ?.BETTING_STREAK_BONUS_MAX ?? 50 export const BETTING_STREAK_RESET_HOUR = econ?.BETTING_STREAK_RESET_HOUR ?? 0 +export const FREE_MARKETS_PER_USER_MAX = econ?.FREE_MARKETS_PER_USER_MAX ?? 5 diff --git a/common/envs/prod.ts b/common/envs/prod.ts index 033d050f..33cf03c1 100644 --- a/common/envs/prod.ts +++ b/common/envs/prod.ts @@ -35,6 +35,7 @@ export type Economy = { BETTING_STREAK_BONUS_AMOUNT?: number BETTING_STREAK_BONUS_MAX?: number BETTING_STREAK_RESET_HOUR?: number + FREE_MARKETS_PER_USER_MAX?: number } type FirebaseConfig = { diff --git a/common/user.ts b/common/user.ts index b278300c..48a3d59c 100644 --- a/common/user.ts +++ b/common/user.ts @@ -43,6 +43,7 @@ export type User = { lastBetTime?: number currentBettingStreak?: number hasSeenContractFollowModal?: boolean + freeMarketsCreated?: number } export type PrivateUser = { diff --git a/functions/src/create-market.ts b/functions/src/create-market.ts index ae120c43..e9804f90 100644 --- a/functions/src/create-market.ts +++ b/functions/src/create-market.ts @@ -15,15 +15,17 @@ import { import { slugify } from '../../common/util/slugify' import { randomString } from '../../common/util/random' -import { chargeUser, getContract } from './utils' +import { chargeUser, getContract, isProd } from './utils' import { APIError, newEndpoint, validate, zTimestamp } from './api' -import { FIXED_ANTE } from '../../common/economy' +import { FIXED_ANTE, FREE_MARKETS_PER_USER_MAX } from '../../common/economy' import { + DEV_HOUSE_LIQUIDITY_PROVIDER_ID, getCpmmInitialLiquidity, getFreeAnswerAnte, getMultipleChoiceAntes, getNumericAnte, + HOUSE_LIQUIDITY_PROVIDER_ID, } from '../../common/antes' import { Answer, getNoneAnswer } from '../../common/answer' import { getNewContract } from '../../common/new-contract' @@ -34,6 +36,7 @@ import { getPseudoProbability } from '../../common/pseudo-numeric' import { JSONContent } from '@tiptap/core' import { uniq, zip } from 'lodash' import { Bet } from '../../common/bet' +import { FieldValue } from 'firebase-admin/firestore' const descScehma: z.ZodType = z.lazy(() => z.intersection( @@ -137,9 +140,10 @@ export const createmarket = newEndpoint({}, async (req, auth) => { const user = userDoc.data() as User const ante = FIXED_ANTE - + const deservesFreeMarket = + (user?.freeMarketsCreated ?? 0) < FREE_MARKETS_PER_USER_MAX // TODO: this is broken because it's not in a transaction - if (ante > user.balance) + if (ante > user.balance && !deservesFreeMarket) throw new APIError(400, `Balance must be at least ${ante}.`) let group: Group | null = null @@ -207,7 +211,18 @@ export const createmarket = newEndpoint({}, async (req, auth) => { visibility ) - if (ante) await chargeUser(user.id, ante, true) + const providerId = deservesFreeMarket + ? isProd() + ? HOUSE_LIQUIDITY_PROVIDER_ID + : DEV_HOUSE_LIQUIDITY_PROVIDER_ID + : user.id + + if (ante) await chargeUser(providerId, ante, true) + if (deservesFreeMarket) + await firestore + .collection('users') + .doc(user.id) + .update({ freeMarketsCreated: FieldValue.increment(1) }) await contractRef.create(contract) @@ -221,8 +236,6 @@ export const createmarket = newEndpoint({}, async (req, auth) => { } } - const providerId = user.id - if (outcomeType === 'BINARY' || outcomeType === 'PSEUDO_NUMERIC') { const liquidityDoc = firestore .collection(`contracts/${contract.id}/liquidity`) diff --git a/functions/src/on-create-liquidity-provision.ts b/functions/src/on-create-liquidity-provision.ts index 56a01bbb..3a1e551f 100644 --- a/functions/src/on-create-liquidity-provision.ts +++ b/functions/src/on-create-liquidity-provision.ts @@ -1,8 +1,13 @@ import * as functions from 'firebase-functions' -import { getContract, getUser } from './utils' +import { getContract, getUser, log } from './utils' import { createNotification } from './create-notification' -import { LiquidityProvision } from 'common/liquidity-provision' +import { LiquidityProvision } from '../../common/liquidity-provision' import { addUserToContractFollowers } from './follow-market' +import { FIXED_ANTE } from '../../common/economy' +import { + DEV_HOUSE_LIQUIDITY_PROVIDER_ID, + HOUSE_LIQUIDITY_PROVIDER_ID, +} from '../../common/antes' export const onCreateLiquidityProvision = functions.firestore .document('contracts/{contractId}/liquidity/{liquidityId}') @@ -11,7 +16,14 @@ export const onCreateLiquidityProvision = functions.firestore const { eventId } = context // Ignore Manifold Markets liquidity for now - users see a notification for free market liquidity provision - if (liquidity.userId === 'IPTOzEqrpkWmEzh6hwvAyY9PqFb2') return + if ( + (liquidity.userId === HOUSE_LIQUIDITY_PROVIDER_ID || + liquidity.userId === DEV_HOUSE_LIQUIDITY_PROVIDER_ID) && + liquidity.amount === FIXED_ANTE + ) + return + + log(`onCreateLiquidityProvision: ${JSON.stringify(liquidity)}`) const contract = await getContract(liquidity.contractId) if (!contract) diff --git a/web/pages/create.tsx b/web/pages/create.tsx index 2ec86bb7..0c142d67 100644 --- a/web/pages/create.tsx +++ b/web/pages/create.tsx @@ -7,7 +7,7 @@ import { Spacer } from 'web/components/layout/spacer' import { getUserAndPrivateUser } from 'web/lib/firebase/users' import { Contract, contractPath } from 'web/lib/firebase/contracts' import { createMarket } from 'web/lib/firebase/api' -import { FIXED_ANTE } from 'common/economy' +import { FIXED_ANTE, FREE_MARKETS_PER_USER_MAX } from 'common/economy' import { InfoTooltip } from 'web/components/info-tooltip' import { Page } from 'web/components/page' import { Row } from 'web/components/layout/row' @@ -158,6 +158,8 @@ export function NewContract(props: { : undefined const balance = creator.balance || 0 + const deservesFreeMarket = + (creator.freeMarketsCreated ?? 0) < FREE_MARKETS_PER_USER_MAX const min = minString ? parseFloat(minString) : undefined const max = maxString ? parseFloat(maxString) : undefined @@ -177,7 +179,7 @@ export function NewContract(props: { question.length > 0 && ante !== undefined && ante !== null && - ante <= balance && + (ante <= balance || deservesFreeMarket) && // closeTime must be in the future closeTime && closeTime > Date.now() && @@ -461,12 +463,25 @@ export function NewContract(props: { text={`Cost to create your question. This amount is used to subsidize betting.`} /> + {!deservesFreeMarket ? ( +
+ {formatMoney(ante)} +
+ ) : ( +
+
+ FREE{' '} + + (You have{' '} + {FREE_MARKETS_PER_USER_MAX - + (creator?.freeMarketsCreated ?? 0)}{' '} + free markets left) + +
+
+ )} -
- {formatMoney(ante)} -
- - {ante > balance && ( + {ante > balance && !deservesFreeMarket && (
Insufficient balance