From e92674117786985ae3af9d5d22c2e909eeb21bf1 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 27 Apr 2022 13:40:02 -0400 Subject: [PATCH 1/8] sitemap: remove non-public pages; sort by 24hr volume; make market page priority depend on volume --- web/pages/server-sitemap.xml.tsx | 22 ++++++++++++++-------- web/public/robots.txt | 2 +- web/public/sitemap-0.xml | 19 +++---------------- 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/web/pages/server-sitemap.xml.tsx b/web/pages/server-sitemap.xml.tsx index 8625860c..e8f77e58 100644 --- a/web/pages/server-sitemap.xml.tsx +++ b/web/pages/server-sitemap.xml.tsx @@ -1,20 +1,26 @@ +import _ from 'lodash' import { GetServerSideProps } from 'next' -import { getServerSideSitemap } from 'next-sitemap' +import { getServerSideSitemap, ISitemapField } from 'next-sitemap' + import { DOMAIN } from '../../common/envs/constants' +import { LiteMarket } from './api/v0/_types' export const getServerSideProps: GetServerSideProps = async (ctx) => { - // Fetching data from https://docs.manifold.markets/api + // Fetching data from https://manifold.markets/api const response = await fetch(`https://${DOMAIN}/api/v0/markets`) - const liteMarkets = await response.json() - const fields = liteMarkets.map((liteMarket: any) => ({ + const liteMarkets = (await response.json()) as LiteMarket[] + const sortedMarkets = _.sortBy(liteMarkets, (m) => -m.volume24Hours) + + const fields = sortedMarkets.map((market) => ({ // See https://www.sitemaps.org/protocol.html - loc: liteMarket.url, + loc: market.url, changefreq: 'hourly', - priority: 0.2, // Individual markets aren't that important + priority: market.volume24Hours + market.volume7Days > 100 ? 0.7 : 0.1, // TODO: Add `lastmod` aka last modified time - })) - return getServerSideSitemap(ctx, fields) + })) as ISitemapField[] + + return await getServerSideSitemap(ctx, fields) } // Default export to prevent next.js errors diff --git a/web/public/robots.txt b/web/public/robots.txt index 014904fd..adb6e505 100644 --- a/web/public/robots.txt +++ b/web/public/robots.txt @@ -6,5 +6,5 @@ Allow: / Host: https://manifold.markets # Sitemaps -Sitemap: https://manifold.markets/sitemap.xml Sitemap: https://manifold.markets/server-sitemap.xml +Sitemap: https://manifold.markets/sitemap.xml diff --git a/web/public/sitemap-0.xml b/web/public/sitemap-0.xml index 80d0d7e3..6378f587 100644 --- a/web/public/sitemap-0.xml +++ b/web/public/sitemap-0.xml @@ -1,19 +1,6 @@ -https://manifold.marketshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/abouthourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/accounthourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/add-fundshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/analyticshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/createhourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/embed/analyticshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/foldshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/homehourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/landing-pagehourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/leaderboardshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/make-predictionshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/marketshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/profilehourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/simulatorhourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/portfoliohourly0.72022-03-24T16:51:19.526Z +https://manifold.marketshourly0.7 +https://manifold.markets/marketshourly0.2 +https://manifold.markets/leaderboardshourly0.2 \ No newline at end of file From 5a5069a4198ab03d17fcc2198c2ec856dfd8003d Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 27 Apr 2022 13:47:51 -0400 Subject: [PATCH 2/8] sitemap: market changefreq; homepage priority = 1 --- web/pages/server-sitemap.xml.tsx | 2 +- web/public/sitemap-0.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/pages/server-sitemap.xml.tsx b/web/pages/server-sitemap.xml.tsx index e8f77e58..9a3cdfe8 100644 --- a/web/pages/server-sitemap.xml.tsx +++ b/web/pages/server-sitemap.xml.tsx @@ -15,7 +15,7 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { const fields = sortedMarkets.map((market) => ({ // See https://www.sitemaps.org/protocol.html loc: market.url, - changefreq: 'hourly', + changefreq: market.volume24Hours > 10 ? 'hourly' : 'daily', priority: market.volume24Hours + market.volume7Days > 100 ? 0.7 : 0.1, // TODO: Add `lastmod` aka last modified time })) as ISitemapField[] diff --git a/web/public/sitemap-0.xml b/web/public/sitemap-0.xml index 6378f587..3b4618fb 100644 --- a/web/public/sitemap-0.xml +++ b/web/public/sitemap-0.xml @@ -1,6 +1,6 @@ -https://manifold.marketshourly0.7 +https://manifold.marketshourly1.0 https://manifold.markets/marketshourly0.2 -https://manifold.markets/leaderboardshourly0.2 +https://manifold.markets/leaderboardsdaily0.2 \ No newline at end of file From d33913a11139965ebb535111aae14d1b22f917fb Mon Sep 17 00:00:00 2001 From: Marshall Polaris Date: Wed, 27 Apr 2022 13:15:14 -0700 Subject: [PATCH 3/8] A couple additions to help newbies out (#104) --- README.md | 10 +++++++--- web/README.md | 17 ++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 7416d3bd..56dceae0 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,9 @@ Operations with complicated contracts (e.g. buying shares) are provided in a sep - `functions/`: Firebase cloud functions, for secure work (e.g. balances, Stripe payments, emails). Also contains in `functions/src/scripts/` some Typescript scripts that do ad hoc CLI interaction with Firebase. -- `common/`: Typescript library code shared between `web/` & `functions/`. Also contains in `common/envs` configuration for - the different environments (i.e. prod, dev, Manifold for Teams instances.) +- `common/`: Typescript library code shared between `web/` & `functions/`. If you want to look at how the market math + works, most of that's in here (it gets called from the `placeBet` and `sellBet` endpoints in `functions/`.) Also + contains in `common/envs` configuration for the different environments (i.e. prod, dev, Manifold for Teams instances.) - `og-image/`: The OpenGraph image generator; creates the preview images shown on Twitter/social media. @@ -34,7 +35,9 @@ Also: Our docs are currently in [a separate repo](https://github.com/manifoldmar ## Contributing -Since we are just now open-sourcing things, we will see how things go. Feel free to open issues, submit PRs, and chat about the process on Discord. We would prefer [small PRs][small-prs] that we can effectively evaluate and review -- maybe check in with us first if you are thinking to work on a big change. +Since we are just now open-sourcing things, we will see how things go. Feel free to open issues, submit PRs, and chat about the process on [Discord][discord]. We would prefer [small PRs][small-prs] that we can effectively evaluate and review -- maybe check in with us first if you are thinking to work on a big change. + +If you need additional access to any infrastructure in order to work on something (e.g. Vercel, Firebase) let us know about that on Discord as well. [vercel]: https://vercel.com/ [jamstack]: https://jamstack.org/ @@ -45,3 +48,4 @@ Since we are just now open-sourcing things, we will see how things go. Feel free [cloud-firestore]: https://firebase.google.com/docs/firestore [cloud-functions]: https://firebase.google.com/docs/functions [small-prs]: https://google.github.io/eng-practices/review/developer/small-cls.html +[discord]: https://discord.gg/eHQBNBqXuh diff --git a/web/README.md b/web/README.md index 8b3e65db..2bfd5056 100644 --- a/web/README.md +++ b/web/README.md @@ -2,13 +2,15 @@ ## Getting started -To run the development server, install [Yarn][yarn], and then in this directory: +To run the development server, install [Yarn 1.x][yarn], and then in this directory: 1. `yarn` to install all dependencies 2. `yarn dev:dev` starts a development web server, pointing at the development database 3. Your site will be available on http://localhost:3000 -Check package.json for other command-line tasks. (e.g. `yarn dev` will point the development server at the prod database. `yarn emulate` will run against a local emulated database, if you are serving it via `yarn serve` from the [`functions/` package][functions-readme].) +Check package.json for other command-line tasks. (e.g. `yarn dev` will point the development server at the prod +database. `yarn emulate` will run against a local emulated database, if you are serving it via `yarn serve` from the +[`functions/` package][functions-readme].) ## Tech stack @@ -24,16 +26,17 @@ branch (to production) and PR branches (to ephemeral staging servers that can be Parts of the file structure that directly map to HTTP endpoints are organized specially per Next.js's prescriptions: -### /public +### public/ These are static files that will be [served by Next verbatim][next-static-files]. -### /pages +### pages/ These are components that [Next's router][next-pages] is aware of and interprets as page roots per their filename, -e.g. the React component in pages/portfolio.tsx is rendered on the user portfolio page at /portfolio. +e.g. the React component in pages/portfolio.tsx is rendered on the user portfolio page at /portfolio. You should +look in here or in `components/` to find any specific piece of UI you are interested in working on. -### /pages/api +### pages/api/ Modules under this route are specially interpreted by Next/Vercel as [functions that will be hosted by Vercel][vercel-functions]. This is where the public Manifold HTTP API lives. @@ -52,7 +55,7 @@ integration][prettier-integrations] to format it in your editor. [nextjs]: https://nextjs.org [vercel]: https://vercel.com [tailwind]: https://tailwindcss.com -[yarn]: https://yarnpkg.com +[yarn]: https://classic.yarnpkg.com/lang/en/docs/install/ [prettier]: https://prettier.io [prettier-integrations]: https://prettier.io/docs/en/editors.html [next-static-files]: https://nextjs.org/docs/basic-features/static-file-serving From 8e514de28f99156cf1dbe1e51d739df0f465a642 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Wed, 27 Apr 2022 16:25:54 -0400 Subject: [PATCH 4/8] Add volume factor to feed --- web/hooks/use-algo-feed.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/web/hooks/use-algo-feed.ts b/web/hooks/use-algo-feed.ts index 543f484b..e8d6396b 100644 --- a/web/hooks/use-algo-feed.ts +++ b/web/hooks/use-algo-feed.ts @@ -151,6 +151,10 @@ function getContractsActivityScores( const activityCountScore = 0.5 + 0.5 * logInterpolation(0, 200, activtyCount) + const { volume7Days, volume } = contract + const combinedVolume = Math.log(volume7Days + 1) + Math.log(volume + 1) + const volumeScore = 0.5 + 0.5 * logInterpolation(4, 25, combinedVolume) + const lastBetTime = contractMostRecentBet[contract.id]?.createdTime ?? contract.createdTime const timeSinceLastBet = Date.now() - lastBetTime @@ -169,7 +173,11 @@ function getContractsActivityScores( const probScore = 0.5 + frac * 0.5 const score = - newCommentScore * activityCountScore * timeAgoScore * probScore + newCommentScore * + activityCountScore * + volumeScore * + timeAgoScore * + probScore // Map score to [0.5, 1] since no recent activty is not a deal breaker. const mappedScore = 0.5 + score / 2 From d9ee03a96ff1b3a7a1cab733154575c8cc422611 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 27 Apr 2022 22:18:52 -0400 Subject: [PATCH 5/8] sendNewCommentEmail: handle sold shares for cfmm --- functions/src/emails.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/functions/src/emails.ts b/functions/src/emails.ts index 290aaecb..20cd002b 100644 --- a/functions/src/emails.ts +++ b/functions/src/emails.ts @@ -48,8 +48,8 @@ export const sendMarketResolutionEmail = async ( creatorName: creator.name, question: contract.question, outcome, - investment: `${Math.round(investment)}`, - payout: `${Math.round(payout)}`, + investment: `${Math.floor(investment)}`, + payout: `${Math.floor(payout)}`, url: `https://${DOMAIN}/${creator.username}/${contract.slug}`, } @@ -189,7 +189,9 @@ export const sendNewCommentEmail = async ( let betDescription = '' if (bet) { const { amount, sale } = bet - betDescription = `${sale ? 'sold' : 'bought'} M$ ${Math.round(amount)}` + betDescription = `${sale || amount < 0 ? 'sold' : 'bought'} ${formatMoney( + amount + )}` } const subject = `Comment on ${question}` From 45aa6646fa2cb863071486757bf0960f27ac6718 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 27 Apr 2022 23:34:50 -0400 Subject: [PATCH 6/8] sendNewCommentEmail: forgot abs value --- functions/src/emails.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/src/emails.ts b/functions/src/emails.ts index 20cd002b..c3b70734 100644 --- a/functions/src/emails.ts +++ b/functions/src/emails.ts @@ -190,7 +190,7 @@ export const sendNewCommentEmail = async ( if (bet) { const { amount, sale } = bet betDescription = `${sale || amount < 0 ? 'sold' : 'bought'} ${formatMoney( - amount + Math.abs(amount) )}` } From da153ceea92a3d20914fff26f77f5c9c8204bed9 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Thu, 28 Apr 2022 10:47:18 -0400 Subject: [PATCH 7/8] bound initial probability to [0.1, 0.9] --- web/components/probability-selector.tsx | 22 +++++++++++++++++----- web/pages/create.tsx | 7 ++++++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/web/components/probability-selector.tsx b/web/components/probability-selector.tsx index 2fc03787..74dab3c6 100644 --- a/web/components/probability-selector.tsx +++ b/web/components/probability-selector.tsx @@ -4,8 +4,11 @@ export function ProbabilitySelector(props: { probabilityInt: number setProbabilityInt: (p: number) => void isSubmitting?: boolean + minProb?: number + maxProb?: number }) { - const { probabilityInt, setProbabilityInt, isSubmitting } = props + const { probabilityInt, setProbabilityInt, isSubmitting, minProb, maxProb } = + props return ( @@ -15,19 +18,28 @@ export function ProbabilitySelector(props: { value={probabilityInt} className="input input-bordered input-md text-lg" disabled={isSubmitting} - min={1} - max={99} + min={minProb ?? 1} + max={maxProb ?? 99} onChange={(e) => setProbabilityInt(parseInt(e.target.value.substring(0, 2))) } + onBlur={() => + setProbabilityInt( + maxProb && probabilityInt > maxProb + ? maxProb + : minProb && probabilityInt < minProb + ? minProb + : probabilityInt + ) + } /> % setProbabilityInt(parseInt(e.target.value))} /> diff --git a/web/pages/create.tsx b/web/pages/create.tsx index b668fffb..4a4a07b5 100644 --- a/web/pages/create.tsx +++ b/web/pages/create.tsx @@ -106,11 +106,14 @@ export function NewContract(props: { question: string; tag?: string }) { setIsSubmitting(true) + const boundedProb = + initialProb > 90 ? 90 : initialProb < 10 ? 10 : initialProb + const result: any = await createContract({ question, outcomeType, description, - initialProb, + initialProb: boundedProb, ante, closeTime, tags, @@ -172,6 +175,8 @@ export function NewContract(props: { question: string; tag?: string }) { )} From 625308c19d6f59ea7ce4b92b01357d5256a60ef6 Mon Sep 17 00:00:00 2001 From: Ian Philips Date: Thu, 28 Apr 2022 12:29:02 -0600 Subject: [PATCH 8/8] Readme: must be in dev for emulators to work --- functions/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/functions/README.md b/functions/README.md index 5f24a217..7601b7c8 100644 --- a/functions/README.md +++ b/functions/README.md @@ -34,9 +34,10 @@ Adapted from https://firebase.google.com/docs/functions/get-started ## Developing locally +0. `$ firebase use dev` if you haven't already 1. `$ yarn serve` to spin up the emulators - The Emulator UI is at http://localhost:4000; the functions are hosted on :5001. - Note: You have to kill and restart emulators when you change code; no hot reload =( + 1. The Emulator UI is at http://localhost:4000; the functions are hosted on :5001. + Note: You have to kill and restart emulators when you change code; no hot reload =( 2. `$ yarn dev:emulate` in `/web` to connect to emulators with the frontend 1. Note: emulated database is cleared after every shutdown