diff --git a/web/pages/api/hello.ts b/web/pages/api/hello.ts deleted file mode 100644 index f8bcc7e5..00000000 --- a/web/pages/api/hello.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type { NextApiRequest, NextApiResponse } from 'next' - -type Data = { - name: string -} - -export default function handler( - req: NextApiRequest, - res: NextApiResponse -) { - res.status(200).json({ name: 'John Doe' }) -} diff --git a/web/pages/api/v0/_types.ts b/web/pages/api/v0/_types.ts new file mode 100644 index 00000000..f63a0980 --- /dev/null +++ b/web/pages/api/v0/_types.ts @@ -0,0 +1,67 @@ +import { Bet } from '../../../../common/bet' +import { getProbability } from '../../../../common/calculate' +import { Comment } from '../../../../common/comment' +import { Contract } from '../../../../common/contract' + +export type LiteContract = { + id: string + creatorUsername: string + creatorName: string + createdTime: number + closeTime?: number + question: string + description: string + tags: string[] + url: string + pool: number + probability: number + volume7Days: number + volume24Hours: number + isResolved: boolean + resolution?: string +} + +export type FullContract = LiteContract & { + bets: Bet[] + comments: Comment[] +} + +export type ApiError = { + error: string +} + +export function toLiteContract({ + id, + creatorUsername, + creatorName, + createdTime, + closeTime, + question, + description, + tags, + slug, + pool, + totalShares, + volume7Days, + volume24Hours, + isResolved, + resolution, +}: Contract): LiteContract { + return { + id, + creatorUsername, + creatorName, + createdTime, + closeTime, + question, + description, + tags, + url: `https://manifold.markets/${creatorUsername}/${slug}`, + pool: pool.YES + pool.NO, + probability: getProbability(totalShares), + volume7Days, + volume24Hours, + isResolved, + resolution, + } +} diff --git a/web/pages/api/v0/market/[id].ts b/web/pages/api/v0/market/[id].ts new file mode 100644 index 00000000..48993866 --- /dev/null +++ b/web/pages/api/v0/market/[id].ts @@ -0,0 +1,32 @@ +import { NextApiRequest, NextApiResponse } from 'next' +import { listAllBets } from '../../../../lib/firebase/bets' +import { listAllComments } from '../../../../lib/firebase/comments' +import { getContractFromId } from '../../../../lib/firebase/contracts' +import { FullContract, ApiError, toLiteContract } from '../_types' + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + const { id } = req.query + const contractId = id as string + + const [contract, bets, comments] = await Promise.all([ + getContractFromId(contractId), + listAllBets(contractId), + listAllComments(contractId), + ]) + + if (!contract) { + res.status(404).json({ error: 'Contract not found' }) + return + } + + // Cache on Vercel edge servers for 2min + res.setHeader('Cache-Control', 'max-age=0, s-maxage=120') + return res.status(200).json({ + ...toLiteContract(contract), + bets, + comments, + }) +} diff --git a/web/pages/api/v0/markets.ts b/web/pages/api/v0/markets.ts new file mode 100644 index 00000000..5106dde0 --- /dev/null +++ b/web/pages/api/v0/markets.ts @@ -0,0 +1,16 @@ +// Next.js API route support: https://vercel.com/docs/concepts/functions/serverless-functions +import type { NextApiRequest, NextApiResponse } from 'next' +import { listAllContracts } from '../../../lib/firebase/contracts' +import { toLiteContract } from './_types' + +type Data = any[] + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + const contracts = await listAllContracts() + // Serve from Vercel cache, then update. see https://vercel.com/docs/concepts/functions/edge-caching + res.setHeader('Cache-Control', 's-maxage=1, stale-while-revalidate') + res.status(200).json(contracts.map(toLiteContract)) +} diff --git a/web/pages/api/v0/slug/[slug].ts b/web/pages/api/v0/slug/[slug].ts new file mode 100644 index 00000000..122fa5c1 --- /dev/null +++ b/web/pages/api/v0/slug/[slug].ts @@ -0,0 +1,32 @@ +import { NextApiRequest, NextApiResponse } from 'next' +import { listAllBets } from '../../../../lib/firebase/bets' +import { listAllComments } from '../../../../lib/firebase/comments' +import { getContractFromSlug } from '../../../../lib/firebase/contracts' +import { FullContract, ApiError, toLiteContract } from '../_types' + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + const { slug } = req.query + + const contract = await getContractFromSlug(slug as string) + + if (!contract) { + res.status(404).json({ error: 'Contract not found' }) + return + } + + const [bets, comments] = await Promise.all([ + listAllBets(contract.id), + listAllComments(contract.id), + ]) + + // Cache on Vercel edge servers for 2min + res.setHeader('Cache-Control', 'max-age=0, s-maxage=120') + return res.status(200).json({ + ...toLiteContract(contract), + bets, + comments, + }) +}