From 6a35d3bf2d87ea779c14b9f8d2e40a5c8056f324 Mon Sep 17 00:00:00 2001 From: Ian Philips Date: Wed, 22 Jun 2022 17:19:17 -0500 Subject: [PATCH] Remove group details cache, update group directly --- common/contract.ts | 3 -- common/group.ts | 6 --- common/new-contract.ts | 5 +- functions/src/create-contract.ts | 48 ++++++++++---------- web/components/contract/contract-details.tsx | 14 +++--- web/hooks/use-group.ts | 11 +++++ web/lib/firebase/groups.ts | 14 ++++++ web/pages/group/[...slugs]/index.tsx | 10 +--- 8 files changed, 60 insertions(+), 51 deletions(-) diff --git a/common/contract.ts b/common/contract.ts index d8f2f032..8427c84b 100644 --- a/common/contract.ts +++ b/common/contract.ts @@ -1,6 +1,5 @@ import { Answer } from './answer' import { Fees } from './fees' -import { GroupDetails } from 'common/group' export type AnyMechanism = DPM | CPMM export type AnyOutcomeType = Binary | FreeResponse | Numeric @@ -25,8 +24,6 @@ export type Contract = { lowercaseTags: string[] visibility: 'public' | 'unlisted' - groupDetails?: GroupDetails[] // Starting with one group per contract - createdTime: number // Milliseconds since epoch lastUpdatedTime?: number // Updated on new bet or comment lastBetTime?: number diff --git a/common/group.ts b/common/group.ts index c0b497bc..f06fdd15 100644 --- a/common/group.ts +++ b/common/group.ts @@ -13,9 +13,3 @@ export type Group = { export const MAX_GROUP_NAME_LENGTH = 75 export const MAX_ABOUT_LENGTH = 140 export const MAX_ID_LENGTH = 60 - -export type GroupDetails = { - groupId: string - groupSlug: string - groupName: string -} diff --git a/common/new-contract.ts b/common/new-contract.ts index 99190165..0b7d294a 100644 --- a/common/new-contract.ts +++ b/common/new-contract.ts @@ -11,7 +11,6 @@ import { import { User } from './user' import { parseTags } from './util/parse' import { removeUndefinedProps } from './util/object' -import { GroupDetails } from 'common/group' export function getNewContract( id: string, @@ -28,8 +27,7 @@ export function getNewContract( // used for numeric markets bucketCount: number, min: number, - max: number, - groupDetails?: GroupDetails + max: number ) { const tags = parseTags( `${question} ${description} ${extraTags.map((tag) => `#${tag}`).join(' ')}` @@ -71,7 +69,6 @@ export function getNewContract( liquidityFee: 0, platformFee: 0, }, - groupDetails: groupDetails ? [groupDetails] : undefined, }) return contract as Contract diff --git a/functions/src/create-contract.ts b/functions/src/create-contract.ts index d62de2ec..ec81ba6e 100644 --- a/functions/src/create-contract.ts +++ b/functions/src/create-contract.ts @@ -77,19 +77,6 @@ export const createmarket = newEndpoint(['POST'], async (req, auth) => { } const user = userDoc.data() as User - let group = null - if (groupId) { - const groupDoc = await firestore.collection('groups').doc(groupId).get() - if (!groupDoc.exists) { - throw new APIError(400, 'No group exists with the given group ID.') - } - - group = groupDoc.data() as Group - if (!group.memberIds.includes(user.id)) { - throw new APIError(400, 'User is not a member of the group.') - } - } - const userContractsCreatedTodaySnapshot = await firestore .collection(`contracts`) .where('creatorId', '==', auth.uid) @@ -104,6 +91,30 @@ export const createmarket = newEndpoint(['POST'], async (req, auth) => { if (ante > user.balance && !isFree) throw new APIError(400, `Balance must be at least ${ante}.`) + const slug = await getSlug(question) + const contractRef = firestore.collection('contracts').doc() + + let group = null + if (groupId) { + const groupDocRef = await firestore.collection('groups').doc(groupId) + const groupDoc = await groupDocRef.get() + if (!groupDoc.exists) { + throw new APIError(400, 'No group exists with the given group ID.') + } + + group = groupDoc.data() as Group + if (!group.memberIds.includes(user.id)) { + throw new APIError( + 400, + 'User must be a member of the group to add markets to it.' + ) + } + if (!group.contractIds.includes(contractRef.id)) + await groupDocRef.update({ + contractIds: [...group.contractIds, contractRef.id], + }) + } + console.log( 'creating contract for', user.username, @@ -113,8 +124,6 @@ export const createmarket = newEndpoint(['POST'], async (req, auth) => { ante || 0 ) - const slug = await getSlug(question) - const contractRef = firestore.collection('contracts').doc() const contract = getNewContract( contractRef.id, slug, @@ -128,14 +137,7 @@ export const createmarket = newEndpoint(['POST'], async (req, auth) => { tags ?? [], NUMERIC_BUCKET_COUNT, min ?? 0, - max ?? 0, - group - ? { - groupId: group.id, - groupName: group.name, - groupSlug: group.slug, - } - : undefined + max ?? 0 ) if (!isFree && ante) await chargeUser(user.id, ante, true) diff --git a/web/components/contract/contract-details.tsx b/web/components/contract/contract-details.tsx index 3e953fd6..863d8c27 100644 --- a/web/components/contract/contract-details.tsx +++ b/web/components/contract/contract-details.tsx @@ -28,6 +28,7 @@ import { UserFollowButton } from '../follow-button' import { groupPath } from 'web/lib/firebase/groups' import { SiteLink } from 'web/components/site-link' import { DAY_MS } from 'common/util/time' +import { useGroupsWithContract } from 'web/hooks/use-group' export function MiscDetails(props: { contract: Contract @@ -110,10 +111,10 @@ export function ContractDetails(props: { disabled?: boolean }) { const { contract, bets, isCreator, disabled } = props - const { closeTime, creatorName, creatorUsername, creatorId, groupDetails } = - contract + const { closeTime, creatorName, creatorUsername, creatorId } = contract const { volumeLabel, resolvedDate } = contractMetrics(contract) - + // Find a group that this contract id is in + const groups = useGroupsWithContract(contract.id) return ( @@ -134,11 +135,12 @@ export function ContractDetails(props: { )} {!disabled && } - {groupDetails && ( + {/*// TODO: we can add contracts to multiple groups but only show the first it was added to*/} + {groups && groups.length > 0 && ( - + - {groupDetails[0].groupName} + {groups[0].name} )} diff --git a/web/hooks/use-group.ts b/web/hooks/use-group.ts index 806aa111..de260f2f 100644 --- a/web/hooks/use-group.ts +++ b/web/hooks/use-group.ts @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react' import { Group } from 'common/group' import { User } from 'common/user' import { + getGroupsWithContractId, listenForGroup, listenForGroups, listenForMemberGroups, @@ -76,3 +77,13 @@ export function useMembers(group: Group) { }, [group]) return members } + +export const useGroupsWithContract = (contractId: string | undefined) => { + const [groups, setGroups] = useState() + + useEffect(() => { + if (contractId) getGroupsWithContractId(contractId, setGroups) + }, [contractId]) + + return groups +} diff --git a/web/lib/firebase/groups.ts b/web/lib/firebase/groups.ts index 7f292e70..4d57d303 100644 --- a/web/lib/firebase/groups.ts +++ b/web/lib/firebase/groups.ts @@ -1,7 +1,9 @@ import { collection, + collectionGroup, deleteDoc, doc, + orderBy, query, updateDoc, where, @@ -82,3 +84,15 @@ export function listenForMemberGroups( setGroups(sorted) }) } + +export async function getGroupsWithContractId( + contractId: string, + setGroups: (groups: Group[]) => void +) { + const q = query( + groupCollection, + where('contractIds', 'array-contains', contractId) + ) + const groups = await getValues(q) + setGroups(groups) +} diff --git a/web/pages/group/[...slugs]/index.tsx b/web/pages/group/[...slugs]/index.tsx index 01fce7e6..9ca1e1fa 100644 --- a/web/pages/group/[...slugs]/index.tsx +++ b/web/pages/group/[...slugs]/index.tsx @@ -451,15 +451,7 @@ function AddContractButton(props: { group: Group; user: User }) { useEffect(() => { return listenForUserContracts(user.id, (contracts) => { - setContracts( - contracts.filter( - (c) => - !group.contractIds.includes(c.id) && - // TODO: It'll be easy to allow questions to be in multiple groups as long as we - // have the on-update-group function update the newly added contract's groupDetails (via contractIds) - !c.groupDetails - ) - ) + setContracts(contracts.filter((c) => !group.contractIds.includes(c.id))) }) }, [group.contractIds, user.id])