Merge branch 'main' into loans2
This commit is contained in:
commit
2eb88a8d36
|
@ -23,13 +23,8 @@ type JwtCredentials = { kind: 'jwt'; data: admin.auth.DecodedIdToken }
|
||||||
type KeyCredentials = { kind: 'key'; data: string }
|
type KeyCredentials = { kind: 'key'; data: string }
|
||||||
type Credentials = JwtCredentials | KeyCredentials
|
type Credentials = JwtCredentials | KeyCredentials
|
||||||
|
|
||||||
const auth = admin.auth()
|
|
||||||
const firestore = admin.firestore()
|
|
||||||
const privateUsers = firestore.collection(
|
|
||||||
'private-users'
|
|
||||||
) as admin.firestore.CollectionReference<PrivateUser>
|
|
||||||
|
|
||||||
export const parseCredentials = async (req: Request): Promise<Credentials> => {
|
export const parseCredentials = async (req: Request): Promise<Credentials> => {
|
||||||
|
const auth = admin.auth()
|
||||||
const authHeader = req.get('Authorization')
|
const authHeader = req.get('Authorization')
|
||||||
if (!authHeader) {
|
if (!authHeader) {
|
||||||
throw new APIError(403, 'Missing Authorization header.')
|
throw new APIError(403, 'Missing Authorization header.')
|
||||||
|
@ -57,6 +52,8 @@ export const parseCredentials = async (req: Request): Promise<Credentials> => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const lookupUser = async (creds: Credentials): Promise<AuthedUser> => {
|
export const lookupUser = async (creds: Credentials): Promise<AuthedUser> => {
|
||||||
|
const firestore = admin.firestore()
|
||||||
|
const privateUsers = firestore.collection('private-users')
|
||||||
switch (creds.kind) {
|
switch (creds.kind) {
|
||||||
case 'jwt': {
|
case 'jwt': {
|
||||||
if (typeof creds.data.user_id !== 'string') {
|
if (typeof creds.data.user_id !== 'string') {
|
||||||
|
@ -70,7 +67,7 @@ export const lookupUser = async (creds: Credentials): Promise<AuthedUser> => {
|
||||||
if (privateUserQ.empty) {
|
if (privateUserQ.empty) {
|
||||||
throw new APIError(403, `No private user exists with API key ${key}.`)
|
throw new APIError(403, `No private user exists with API key ${key}.`)
|
||||||
}
|
}
|
||||||
const privateUser = privateUserQ.docs[0].data()
|
const privateUser = privateUserQ.docs[0].data() as PrivateUser
|
||||||
return { uid: privateUser.id, creds: { privateUser, ...creds } }
|
return { uid: privateUser.id, creds: { privateUser, ...creds } }
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -21,6 +21,7 @@ const bodySchema = z.object({
|
||||||
})
|
})
|
||||||
|
|
||||||
export const creategroup = newEndpoint({}, async (req, auth) => {
|
export const creategroup = newEndpoint({}, async (req, auth) => {
|
||||||
|
const firestore = admin.firestore()
|
||||||
const { name, about, memberIds, anyoneCanJoin } = validate(
|
const { name, about, memberIds, anyoneCanJoin } = validate(
|
||||||
bodySchema,
|
bodySchema,
|
||||||
req.body
|
req.body
|
||||||
|
@ -67,7 +68,7 @@ export const creategroup = newEndpoint({}, async (req, auth) => {
|
||||||
return { status: 'success', group: group }
|
return { status: 'success', group: group }
|
||||||
})
|
})
|
||||||
|
|
||||||
const getSlug = async (name: string) => {
|
export const getSlug = async (name: string) => {
|
||||||
const proposedSlug = slugify(name)
|
const proposedSlug = slugify(name)
|
||||||
|
|
||||||
const preexistingGroup = await getGroupFromSlug(proposedSlug)
|
const preexistingGroup = await getGroupFromSlug(proposedSlug)
|
||||||
|
@ -75,9 +76,8 @@ const getSlug = async (name: string) => {
|
||||||
return preexistingGroup ? proposedSlug + '-' + randomString() : proposedSlug
|
return preexistingGroup ? proposedSlug + '-' + randomString() : proposedSlug
|
||||||
}
|
}
|
||||||
|
|
||||||
const firestore = admin.firestore()
|
|
||||||
|
|
||||||
export async function getGroupFromSlug(slug: string) {
|
export async function getGroupFromSlug(slug: string) {
|
||||||
|
const firestore = admin.firestore()
|
||||||
const snap = await firestore
|
const snap = await firestore
|
||||||
.collection('groups')
|
.collection('groups')
|
||||||
.where('slug', '==', slug)
|
.where('slug', '==', slug)
|
||||||
|
|
|
@ -15,17 +15,15 @@ import {
|
||||||
import { slugify } from '../../common/util/slugify'
|
import { slugify } from '../../common/util/slugify'
|
||||||
import { randomString } from '../../common/util/random'
|
import { randomString } from '../../common/util/random'
|
||||||
|
|
||||||
import { chargeUser, getContract, isProd } from './utils'
|
import { chargeUser, getContract } from './utils'
|
||||||
import { APIError, newEndpoint, validate, zTimestamp } from './api'
|
import { APIError, newEndpoint, validate, zTimestamp } from './api'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DEV_HOUSE_LIQUIDITY_PROVIDER_ID,
|
|
||||||
FIXED_ANTE,
|
FIXED_ANTE,
|
||||||
getCpmmInitialLiquidity,
|
getCpmmInitialLiquidity,
|
||||||
getFreeAnswerAnte,
|
getFreeAnswerAnte,
|
||||||
getMultipleChoiceAntes,
|
getMultipleChoiceAntes,
|
||||||
getNumericAnte,
|
getNumericAnte,
|
||||||
HOUSE_LIQUIDITY_PROVIDER_ID,
|
|
||||||
} from '../../common/antes'
|
} from '../../common/antes'
|
||||||
import { Answer, getNoneAnswer } from '../../common/answer'
|
import { Answer, getNoneAnswer } from '../../common/answer'
|
||||||
import { getNewContract } from '../../common/new-contract'
|
import { getNewContract } from '../../common/new-contract'
|
||||||
|
@ -223,9 +221,7 @@ export const createmarket = newEndpoint({}, async (req, auth) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const providerId = isProd()
|
const providerId = user.id
|
||||||
? HOUSE_LIQUIDITY_PROVIDER_ID
|
|
||||||
: DEV_HOUSE_LIQUIDITY_PROVIDER_ID
|
|
||||||
|
|
||||||
if (outcomeType === 'BINARY' || outcomeType === 'PSEUDO_NUMERIC') {
|
if (outcomeType === 'BINARY' || outcomeType === 'PSEUDO_NUMERIC') {
|
||||||
const liquidityDoc = firestore
|
const liquidityDoc = firestore
|
||||||
|
|
|
@ -103,94 +103,28 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body style="word-spacing: normal; background-color: #f4f4f4">
|
<body style="word-spacing: normal; background-color: #f4f4f4">
|
||||||
<div style="background-color: #f4f4f4">
|
|
||||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
<!--[if mso | IE]></td></tr></table><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||||
<div style="
|
<div style="
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
margin: 0px auto;
|
margin: 0px auto;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
">
|
">
|
||||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||||
style="background: #ffffff; background-color: #ffffff; width: 100%">
|
style="background: #ffffff; background-color: #ffffff; width: 100%">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="
|
<td style="width:550px;">
|
||||||
direction: ltr;
|
<a href="https://manifold.markets" target="_blank">
|
||||||
font-size: 0px;
|
<img alt="banner logo" height="auto" src="https://manifold.markets/logo-banner.png"
|
||||||
padding: 0px 0px 0px 0px;
|
style="border:none;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:13px;"
|
||||||
padding-bottom: 0px;
|
title="" width="550">
|
||||||
padding-left: 0px;
|
</a>
|
||||||
padding-right: 0px;
|
</td>
|
||||||
padding-top: 0px;
|
</tr>
|
||||||
text-align: center;
|
<tr>
|
||||||
">
|
<td style="
|
||||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]-->
|
|
||||||
<div class="mj-column-per-100 mj-outlook-group-fix" style="
|
|
||||||
font-size: 0px;
|
|
||||||
text-align: left;
|
|
||||||
direction: ltr;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: top;
|
|
||||||
width: 100%;
|
|
||||||
">
|
|
||||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align: top"
|
|
||||||
width="100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td align="center" style="
|
|
||||||
font-size: 0px;
|
|
||||||
padding: 0px 25px 0px 25px;
|
|
||||||
padding-top: 0px;
|
|
||||||
padding-right: 25px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
padding-left: 25px;
|
|
||||||
word-break: break-word;
|
|
||||||
">
|
|
||||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-spacing: 0px;
|
|
||||||
">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="width: 550px">
|
|
||||||
<a href="https://manifold.markets/home" target="_blank"><img alt="" height="auto"
|
|
||||||
src="https://03jlj.mjt.lu/img/03jlj/b/96u/omk8.gif" style="
|
|
||||||
border: none;
|
|
||||||
display: block;
|
|
||||||
outline: none;
|
|
||||||
text-decoration: none;
|
|
||||||
height: auto;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 13px;
|
|
||||||
" width="550" /></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<!--[if mso | IE]></td></tr></table><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
|
||||||
<div style="
|
|
||||||
background: #ffffff;
|
|
||||||
background-color: #ffffff;
|
|
||||||
margin: 0px auto;
|
|
||||||
max-width: 600px;
|
|
||||||
">
|
|
||||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
|
||||||
style="background: #ffffff; background-color: #ffffff; width: 100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="
|
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
font-size: 0px;
|
font-size: 0px;
|
||||||
padding: 20px 0px 0px 0px;
|
padding: 20px 0px 0px 0px;
|
||||||
|
@ -200,8 +134,8 @@
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
">
|
">
|
||||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]-->
|
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]-->
|
||||||
<div class="mj-column-per-100 mj-outlook-group-fix" style="
|
<div class="mj-column-per-100 mj-outlook-group-fix" style="
|
||||||
font-size: 0px;
|
font-size: 0px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
|
@ -209,24 +143,24 @@
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
">
|
">
|
||||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align: top"
|
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align: top"
|
||||||
width="100%">
|
width="100%">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left"
|
<td align="left"
|
||||||
style="font-size:0px;padding:10px 25px;padding-top:0px;padding-bottom:0px;word-break:break-word;">
|
style="font-size:0px;padding:10px 25px;padding-top:0px;padding-bottom:0px;word-break:break-word;">
|
||||||
<div
|
<div
|
||||||
style="font-family:Arial, sans-serif;font-size:18px;letter-spacing:normal;line-height:1;text-align:left;color:#000000;">
|
style="font-family:Arial, sans-serif;font-size:18px;letter-spacing:normal;line-height:1;text-align:left;color:#000000;">
|
||||||
<p class="text-build-content"
|
<p class="text-build-content"
|
||||||
style="line-height: 24px; margin: 10px 0; margin-top: 10px; margin-bottom: 10px;"
|
style="line-height: 24px; margin: 10px 0; margin-top: 10px; margin-bottom: 10px;"
|
||||||
data-testid="4XoHRGw1Y"><span
|
data-testid="4XoHRGw1Y"><span
|
||||||
style="color:#000000;font-family:Arial, Helvetica, sans-serif;font-size:18px;">
|
style="color:#000000;font-family:Arial, Helvetica, sans-serif;font-size:18px;">
|
||||||
Hi {{name}},</span></p>
|
Hi {{name}},</span></p>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left" style="
|
<td align="left" style="
|
||||||
font-size: 0px;
|
font-size: 0px;
|
||||||
padding: 0px 25px 20px 25px;
|
padding: 0px 25px 20px 25px;
|
||||||
padding-top: 0px;
|
padding-top: 0px;
|
||||||
|
@ -235,7 +169,7 @@
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
">
|
">
|
||||||
<div style="
|
<div style="
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
letter-spacing: normal;
|
letter-spacing: normal;
|
||||||
|
@ -243,197 +177,253 @@
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
">
|
">
|
||||||
<p class="text-build-content" style="
|
<p class="text-build-content" style="
|
||||||
line-height: 23px;
|
line-height: 23px;
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
" data-testid="3Q8BP69fq">
|
" data-testid="3Q8BP69fq">
|
||||||
<span style="
|
<span style="
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
">Congrats on creating your first market on <a class="link-build-content"
|
">Did you know you create your own prediction market on <a class="link-build-content"
|
||||||
style="color: #55575d" target="_blank"
|
style="color: #55575d" target="_blank" href="https://manifold.markets">Manifold</a> for
|
||||||
href="https://manifold.markets">Manifold</a>!</span>
|
any question you care about?</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="text-build-content" style="line-height: 23px; margin: 10px 0"
|
<p class="text-build-content" style="line-height: 23px; margin: 10px 0" data-testid="3Q8BP69fq">
|
||||||
data-testid="3Q8BP69fq">
|
<span style="
|
||||||
<span style="
|
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
">The following is a short guide to creating markets.</span>
|
">Whether it's current events like <a class="link-build-content" style="color: #55575d"
|
||||||
</p>
|
target="_blank"
|
||||||
<p class="text-build-content" style="line-height: 23px; margin: 10px 0"
|
href="https://manifold.markets/SG/will-elon-musk-buy-twitter-this-yea">Musk buying
|
||||||
data-testid="3Q8BP69fq">
|
Twitter</a> or <a class="link-build-content" style="color: #55575d" target="_blank"
|
||||||
|
href="https://manifold.markets/NathanpmYoung/will-biden-be-the-2024-democratic-n">2024
|
||||||
</p>
|
elections</a> or personal matters
|
||||||
<p class="text-build-content" style="line-height: 23px; margin: 10px 0"
|
like <a class="link-build-content" style="color: #55575d" target="_blank"
|
||||||
data-testid="3Q8BP69fq">
|
href="https://manifold.markets/dreev/which-book-will-i-like-best">book
|
||||||
<span style="
|
recommendations</a> or <a class="link-build-content" style="color: #55575d"
|
||||||
|
target="_blank"
|
||||||
|
href="https://manifold.markets/agentydragon/will-my-weight-go-under-115-kg-in-2">losing
|
||||||
|
weight</a>,
|
||||||
|
Manifold can help you find the answer.</span>
|
||||||
|
</p>
|
||||||
|
<p class="text-build-content" style="line-height: 23px; margin: 10px 0;margin-bottom: 20px;"
|
||||||
|
data-testid="3Q8BP69fq">
|
||||||
|
<span style="
|
||||||
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
|
sans-serif;
|
||||||
|
font-size: 17px;
|
||||||
|
">The following is a
|
||||||
|
short guide to creating markets.</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table cellspacing="0" cellpadding="0" align="center">
|
||||||
|
<tr>
|
||||||
|
<td style="border-radius: 4px;" bgcolor="#4337c9">
|
||||||
|
<a href="https://manifold.markets/create" target="_blank"
|
||||||
|
style="padding: 12px 16px; border: 1px solid #4337c9;border-radius: 16px;font-family: Helvetica, Arial, sans-serif;font-size: 24px; color: #ffffff;text-decoration: none;font-weight:semibold;display: inline-block;">
|
||||||
|
Create a market
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="text-build-content" style="line-height: 23px; margin: 10px 0" data-testid="3Q8BP69fq">
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<p class="text-build-content" style="line-height: 23px; margin: 10px 0" data-testid="3Q8BP69fq">
|
||||||
|
<span style="
|
||||||
color: #292fd7;
|
color: #292fd7;
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
"><b>What makes a good market?</b></span>
|
"><b>What makes a good market?</b></span>
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li style="line-height: 23px; margin-bottom: 8px;">
|
<li style="line-height: 23px; margin-bottom: 8px;">
|
||||||
<span
|
<span
|
||||||
style="font-family: Readex Pro, Arial, Helvetica, sans-serif;font-size: 17px;"><b>Interesting
|
style="font-family: Readex Pro, Arial, Helvetica, sans-serif;font-size: 17px;"><b>Interesting
|
||||||
topic. </b>Manifold gives
|
topic. </b>Manifold gives
|
||||||
creators M$10 for
|
creators M$10 for
|
||||||
each unique trader that bets on your
|
each unique trader that bets on your
|
||||||
market, so it pays to ask a question people are interested in!</span>
|
market, so it pays to ask a question people are interested in!</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li style="line-height: 23px; margin-bottom: 8px;">
|
<li style="line-height: 23px; margin-bottom: 8px;">
|
||||||
<span style="
|
<span style="
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
"><b>Clear resolution criteria. </b>Any ambiguities or edge cases in your description
|
"><b>Clear resolution criteria. </b>Any ambiguities or edge cases in your description
|
||||||
will drive traders away from your markets.</span>
|
will drive traders away from your markets.</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li style="line-height: 23px; margin-bottom: 8px;">
|
<li style="line-height: 23px; margin-bottom: 8px;">
|
||||||
<span style="
|
<span style="
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
"><b>Detailed description. </b>Include images/videos/tweets and any context or
|
"><b>Detailed description. </b>Include images/videos/tweets and any context or
|
||||||
background
|
background
|
||||||
information that could be useful to people who
|
information that could be useful to people who
|
||||||
are interested in learning more that are
|
are interested in learning more that are
|
||||||
uneducated on the subject.</span>
|
uneducated on the subject.</span>
|
||||||
</li>
|
</li>
|
||||||
<li style="line-height: 23px; margin-bottom: 8px;">
|
<li style="line-height: 23px; margin-bottom: 8px;">
|
||||||
<span style="
|
<span style="
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
"><b>Add it to a group. </b>Groups are the
|
"><b>Part of a group. </b>Groups are the
|
||||||
primary way users filter for relevant markets.
|
primary way users filter for relevant markets.
|
||||||
Also, consider making your own groups and
|
Also, consider making your own groups and
|
||||||
inviting friends/interested communities to
|
inviting friends/interested communities to
|
||||||
them from other sites!</span>
|
them from other sites!</span>
|
||||||
</li>
|
</li>
|
||||||
<li style="line-height: 23px; margin-bottom: 8px;">
|
<li style="line-height: 23px; margin-bottom: 8px;">
|
||||||
<span style="
|
<span style="
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
"><b>Share it on social media</b>. You'll earn the <a class="link-build-content"
|
"><b>Sharing it on social media</b>. You'll earn the <a class="link-build-content"
|
||||||
style="color: inherit; text-decoration: none" target="_blank"
|
style="color: inherit; text-decoration: none" target="_blank"
|
||||||
href="https://manifold.markets/referrals"><span style="
|
href="https://manifold.markets/referrals"><span style="
|
||||||
color: #55575d;
|
color: #55575d;
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
"><u>M$500
|
"><u>M$500
|
||||||
referral bonus</u></span></a> if you get new users to sign up!</span>
|
referral bonus</u></span></a> if you get new users to sign up!</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p class="text-build-content" style="line-height: 23px; margin: 10px 0"
|
<p class="text-build-content" style="line-height: 23px; margin: 10px 0" data-testid="3Q8BP69fq">
|
||||||
data-testid="3Q8BP69fq">
|
|
||||||
|
</p>
|
||||||
</p>
|
|
||||||
<p class="text-build-content" style="line-height: 23px; margin: 10px 0"
|
<p class="text-build-content" style="line-height: 23px; margin: 10px 0" data-testid="3Q8BP69fq">
|
||||||
data-testid="3Q8BP69fq">
|
<span style="
|
||||||
<span style="
|
|
||||||
color: #292fd7;
|
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
|
||||||
sans-serif;
|
|
||||||
font-size: 20px;
|
|
||||||
"><b>Examples of markets you should
|
|
||||||
emulate! </b></span>
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li style="line-height: 23px">
|
|
||||||
<a class="link-build-content" style="color: inherit; text-decoration: none"
|
|
||||||
target="_blank"
|
|
||||||
href="https://manifold.markets/DavidChee/will-our-upcoming-twitch-bot-be-a-s"><span
|
|
||||||
style="
|
|
||||||
color: #55575d;
|
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
|
||||||
sans-serif;
|
|
||||||
font-size: 17px;
|
|
||||||
"><u>This complex market</u></span></a><span style="
|
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
|
||||||
sans-serif;
|
|
||||||
font-size: 17px;
|
|
||||||
">
|
|
||||||
about the project I am working on.</span>
|
|
||||||
</li>
|
|
||||||
<li style="line-height: 23px">
|
|
||||||
<a class="link-build-content" style="color: inherit; text-decoration: none"
|
|
||||||
target="_blank"
|
|
||||||
href="https://manifold.markets/SneakySly/will-manifold-reach-1000-weekly-act"><span
|
|
||||||
style="
|
|
||||||
color: #55575d;
|
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
|
||||||
sans-serif;
|
|
||||||
font-size: 17px;
|
|
||||||
"><u>This simple market</u></span></a><span style="
|
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
|
||||||
sans-serif;
|
|
||||||
font-size: 17px;
|
|
||||||
">
|
|
||||||
about Manifold's weekly active
|
|
||||||
users.</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p class="text-build-content" style="line-height: 23px; margin: 10px 0"
|
|
||||||
data-testid="3Q8BP69fq">
|
|
||||||
|
|
||||||
</p>
|
|
||||||
<p class="text-build-content" style="line-height: 23px; margin: 10px 0"
|
|
||||||
data-testid="3Q8BP69fq">
|
|
||||||
<span style="
|
|
||||||
color: #000000;
|
color: #000000;
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
">Why not </span>
|
">Why not </span>
|
||||||
|
<a class="link-build-content" style="color: inherit; text-decoration: none" target="_blank"
|
||||||
|
href="https://manifold.markets/create"><span style="
|
||||||
|
|
||||||
<a class="link-build-content" style="color: inherit; text-decoration: none" target="_blank"
|
|
||||||
href="https://manifold.markets/create"><span style="
|
|
||||||
color: #55575d;
|
color: #55575d;
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
"><u>create another market</u></span></a><span style="
|
"><u>create a market</u></span></a><span style="
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
">
|
">
|
||||||
while it is still fresh on your mind?
|
while it is still fresh on your mind?
|
||||||
</p>
|
</p>
|
||||||
<p class="text-build-content" style="line-height: 23px; margin: 10px 0"
|
<p class="text-build-content" style="line-height: 23px; margin: 10px 0" data-testid="3Q8BP69fq">
|
||||||
data-testid="3Q8BP69fq">
|
|
||||||
<span style="
|
</p>
|
||||||
|
<p class="text-build-content" style="line-height: 23px; margin: 10px 0" data-testid="3Q8BP69fq">
|
||||||
|
<span style="
|
||||||
color: #000000;
|
color: #000000;
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
">Thanks for reading!</span>
|
">Thanks for reading!</span>
|
||||||
</p>
|
</p>
|
||||||
<p class="text-build-content" style="
|
<p class="text-build-content" style="
|
||||||
line-height: 23px;
|
line-height: 23px;
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
" data-testid="3Q8BP69fq">
|
" data-testid="3Q8BP69fq">
|
||||||
<span style="
|
<span style="
|
||||||
color: #000000;
|
color: #000000;
|
||||||
font-family: Readex Pro, Arial, Helvetica,
|
font-family: Readex Pro, Arial, Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
">David from Manifold</span>
|
">David from Manifold</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background-color: #f4f4f4">
|
||||||
|
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||||
|
<div style="
|
||||||
|
background: #ffffff;
|
||||||
|
background-color: #ffffff;
|
||||||
|
margin: 0px auto;
|
||||||
|
max-width: 600px;
|
||||||
|
">
|
||||||
|
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||||
|
style="background: #ffffff; background-color: #ffffff; width: 100%">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="
|
||||||
|
direction: ltr;
|
||||||
|
font-size: 0px;
|
||||||
|
padding: 0px 0px 0px 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
padding-left: 0px;
|
||||||
|
padding-right: 0px;
|
||||||
|
padding-top: 0px;
|
||||||
|
text-align: center;
|
||||||
|
">
|
||||||
|
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]-->
|
||||||
|
<div class="mj-column-per-100 mj-outlook-group-fix" style="
|
||||||
|
font-size: 0px;
|
||||||
|
text-align: left;
|
||||||
|
direction: ltr;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 100%;
|
||||||
|
">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align: top"
|
||||||
|
width="100%">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="
|
||||||
|
font-size: 0px;
|
||||||
|
padding: 0px 25px 0px 25px;
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-right: 25px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
padding-left: 25px;
|
||||||
|
word-break: break-word;
|
||||||
|
">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0px;
|
||||||
|
">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="width: 550px">
|
||||||
|
<a href="https://manifold.markets/create" target="_blank"><img alt="" height="auto"
|
||||||
|
src="https://03jlj.mjt.lu/img/03jlj/b/96u/omk8.gif" style="
|
||||||
|
border: none;
|
||||||
|
display: block;
|
||||||
|
outline: none;
|
||||||
|
text-decoration: none;
|
||||||
|
height: auto;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 13px;
|
||||||
|
" width="550" /></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -107,19 +107,12 @@
|
||||||
width="100%">
|
width="100%">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"
|
<td style="width:550px;">
|
||||||
style="font-size:0px;padding:0px 25px 0px 25px;padding-top:0px;padding-right:25px;padding-bottom:0px;padding-left:25px;word-break:break-word;">
|
<a href="https://manifold.markets" target="_blank">
|
||||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation"
|
<img alt="banner logo" height="auto" src="https://manifold.markets/logo-banner.png"
|
||||||
style="border-collapse:collapse;border-spacing:0px;">
|
style="border:none;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:13px;"
|
||||||
<tbody>
|
title="" width="550">
|
||||||
<tr>
|
</a>
|
||||||
<td style="width:550px;"><a href="https://manifold.markets/home" target="_blank"><img
|
|
||||||
alt="" height="auto" src="https://03jlj.mjt.lu/img/03jlj/b/urx/sjtz.gif"
|
|
||||||
style="border:none;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:13px;"
|
|
||||||
width="550"></a></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -175,9 +168,9 @@
|
||||||
<td>
|
<td>
|
||||||
<table cellspacing="0" cellpadding="0">
|
<table cellspacing="0" cellpadding="0">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border-radius: 2px;" bgcolor="#4337c9">
|
<td style="border-radius: 4px;" bgcolor="#4337c9">
|
||||||
<a href="https://manifold.markets" target="_blank"
|
<a href="https://manifold.markets" target="_blank"
|
||||||
style="padding: 12px 16px; border: 1px solid #4337c9;border-radius: 16px;font-family: Helvetica, Arial, sans-serif;font-size: 24px; color: #ffffff;text-decoration: none;font-weight:bold;display: inline-block;">
|
style="padding: 12px 16px; border: 1px solid #4337c9;border-radius: 16px;font-family: Helvetica, Arial, sans-serif;font-size: 24px; color: #ffffff;text-decoration: none;font-weight:semibold;display: inline-block;">
|
||||||
Explore markets
|
Explore markets
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
@ -225,22 +218,12 @@
|
||||||
style="color:#55575d;font-family:Arial;font-size:18px;"><u>Join our Discord
|
style="color:#55575d;font-family:Arial;font-size:18px;"><u>Join our Discord
|
||||||
chat</u></span></a></span></li>
|
chat</u></span></a></span></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p class="text-build-content" data-testid="3Q8BP69fq" style="margin: 10px 0;"> </p>
|
|
||||||
<p class="text-build-content" data-testid="3Q8BP69fq" style="margin: 10px 0;"><span
|
|
||||||
style="color:#000000;font-family:Arial;font-size:18px;">Cheers,</span>
|
|
||||||
</p>
|
|
||||||
<p class="text-build-content" data-testid="3Q8BP69fq" style="margin: 10px 0;"><span
|
|
||||||
style="color:#000000;font-family:Arial;font-size:18px;">David
|
|
||||||
from Manifold</span></p>
|
|
||||||
<p class="text-build-content" data-testid="3Q8BP69fq"
|
|
||||||
style="margin: 10px 0; margin-bottom: 10px;"> </p>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left"
|
<td align="left"
|
||||||
style="font-size:0px;padding:15px 25px 0px 25px;padding-top:15px;padding-right:25px;padding-bottom:0px;padding-left:25px;word-break:break-word;">
|
style="font-size:0px;padding:15px 25px 0px 25px;padding-top:0px;padding-right:25px;padding-bottom:0px;padding-left:25px;word-break:break-word;">
|
||||||
<div
|
<div
|
||||||
style="font-family:Arial, sans-serif;font-size:18px;letter-spacing:normal;line-height:1;text-align:left;color:#000000;">
|
style="font-family:Arial, sans-serif;font-size:18px;letter-spacing:normal;line-height:1;text-align:left;color:#000000;">
|
||||||
<p class="text-build-content" style="line-height: 23px; margin: 10px 0; margin-top: 10px;"
|
<p class="text-build-content" style="line-height: 23px; margin: 10px 0; margin-top: 10px;"
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
import { DOMAIN } from '../../common/envs/constants'
|
import { DOMAIN } from '../../common/envs/constants'
|
||||||
import { Answer } from '../../common/answer'
|
import { Answer } from '../../common/answer'
|
||||||
import { Bet } from '../../common/bet'
|
import { Bet } from '../../common/bet'
|
||||||
|
@ -192,7 +191,6 @@ Cofounder of Manifold Markets
|
||||||
https://manifold.markets
|
https://manifold.markets
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
||||||
await sendTextEmail(
|
await sendTextEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
'How are you finding Manifold?',
|
'How are you finding Manifold?',
|
||||||
|
@ -238,7 +236,8 @@ export const sendOneWeekBonusEmail = async (
|
||||||
|
|
||||||
export const sendCreatorGuideEmail = async (
|
export const sendCreatorGuideEmail = async (
|
||||||
user: User,
|
user: User,
|
||||||
privateUser: PrivateUser
|
privateUser: PrivateUser,
|
||||||
|
sendTime: string
|
||||||
) => {
|
) => {
|
||||||
if (
|
if (
|
||||||
!privateUser ||
|
!privateUser ||
|
||||||
|
@ -255,7 +254,7 @@ export const sendCreatorGuideEmail = async (
|
||||||
|
|
||||||
return await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
'Market creation guide',
|
'Create your own prediction market',
|
||||||
'creating-market',
|
'creating-market',
|
||||||
{
|
{
|
||||||
name: firstName,
|
name: firstName,
|
||||||
|
@ -263,6 +262,7 @@ export const sendCreatorGuideEmail = async (
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: 'David from Manifold <david@manifold.markets>',
|
from: 'David from Manifold <david@manifold.markets>',
|
||||||
|
'o:deliverytime': sendTime,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
import * as functions from 'firebase-functions'
|
import * as functions from 'firebase-functions'
|
||||||
import * as admin from 'firebase-admin'
|
|
||||||
|
|
||||||
import { getPrivateUser, getUser } from './utils'
|
import { getUser } from './utils'
|
||||||
import { createNotification } from './create-notification'
|
import { createNotification } from './create-notification'
|
||||||
import { Contract } from '../../common/contract'
|
import { Contract } from '../../common/contract'
|
||||||
import { parseMentions, richTextToString } from '../../common/util/parse'
|
import { parseMentions, richTextToString } from '../../common/util/parse'
|
||||||
import { JSONContent } from '@tiptap/core'
|
import { JSONContent } from '@tiptap/core'
|
||||||
import { User } from 'common/user'
|
|
||||||
import { sendCreatorGuideEmail } from './emails'
|
|
||||||
|
|
||||||
export const onCreateContract = functions
|
export const onCreateContract = functions
|
||||||
.runWith({ secrets: ['MAILGUN_KEY'] })
|
.runWith({ secrets: ['MAILGUN_KEY'] })
|
||||||
|
@ -31,23 +28,4 @@ export const onCreateContract = functions
|
||||||
richTextToString(desc),
|
richTextToString(desc),
|
||||||
{ contract, recipients: mentioned }
|
{ contract, recipients: mentioned }
|
||||||
)
|
)
|
||||||
|
|
||||||
await sendGuideEmail(contractCreator)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const firestore = admin.firestore()
|
|
||||||
|
|
||||||
const sendGuideEmail = async (contractCreator: User) => {
|
|
||||||
const query = await firestore
|
|
||||||
.collection(`contracts`)
|
|
||||||
.where('creatorId', '==', contractCreator.id)
|
|
||||||
.limit(2)
|
|
||||||
.get()
|
|
||||||
|
|
||||||
if (query.size >= 2) return
|
|
||||||
|
|
||||||
const privateUser = await getPrivateUser(contractCreator.id)
|
|
||||||
if (!privateUser) return
|
|
||||||
|
|
||||||
await sendCreatorGuideEmail(contractCreator, privateUser)
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ dayjs.extend(utc)
|
||||||
import { getPrivateUser } from './utils'
|
import { getPrivateUser } from './utils'
|
||||||
import { User } from 'common/user'
|
import { User } from 'common/user'
|
||||||
import {
|
import {
|
||||||
|
sendCreatorGuideEmail,
|
||||||
sendInterestingMarketsEmail,
|
sendInterestingMarketsEmail,
|
||||||
sendPersonalFollowupEmail,
|
sendPersonalFollowupEmail,
|
||||||
sendWelcomeEmail,
|
sendWelcomeEmail,
|
||||||
|
@ -22,7 +23,10 @@ export const onCreateUser = functions
|
||||||
|
|
||||||
await sendWelcomeEmail(user, privateUser)
|
await sendWelcomeEmail(user, privateUser)
|
||||||
|
|
||||||
const followupSendTime = dayjs().add(4, 'hours').toString()
|
const guideSendTime = dayjs().add(28, 'hours').toString()
|
||||||
|
await sendCreatorGuideEmail(user, privateUser, guideSendTime)
|
||||||
|
|
||||||
|
const followupSendTime = dayjs().add(48, 'hours').toString()
|
||||||
await sendPersonalFollowupEmail(user, privateUser, followupSendTime)
|
await sendPersonalFollowupEmail(user, privateUser, followupSendTime)
|
||||||
|
|
||||||
// skip email if weekly email is about to go out
|
// skip email if weekly email is about to go out
|
||||||
|
|
66
functions/src/scripts/convert-tag-to-group.ts
Normal file
66
functions/src/scripts/convert-tag-to-group.ts
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// Takes a tag and makes a new group with all the contracts in it.
|
||||||
|
|
||||||
|
import * as admin from 'firebase-admin'
|
||||||
|
import { initAdmin } from './script-init'
|
||||||
|
import { isProd, log } from '../utils'
|
||||||
|
import { getSlug } from '../create-group'
|
||||||
|
import { Group } from '../../../common/group'
|
||||||
|
|
||||||
|
const getTaggedContractIds = async (tag: string) => {
|
||||||
|
const firestore = admin.firestore()
|
||||||
|
const results = await firestore
|
||||||
|
.collection('contracts')
|
||||||
|
.where('lowercaseTags', 'array-contains', tag.toLowerCase())
|
||||||
|
.get()
|
||||||
|
return results.docs.map((d) => d.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const createGroup = async (
|
||||||
|
name: string,
|
||||||
|
about: string,
|
||||||
|
contractIds: string[]
|
||||||
|
) => {
|
||||||
|
const firestore = admin.firestore()
|
||||||
|
const creatorId = isProd()
|
||||||
|
? 'IPTOzEqrpkWmEzh6hwvAyY9PqFb2'
|
||||||
|
: '94YYTk1AFWfbWMpfYcvnnwI1veP2'
|
||||||
|
|
||||||
|
const slug = await getSlug(name)
|
||||||
|
const groupRef = firestore.collection('groups').doc()
|
||||||
|
const now = Date.now()
|
||||||
|
const group: Group = {
|
||||||
|
id: groupRef.id,
|
||||||
|
creatorId,
|
||||||
|
slug,
|
||||||
|
name,
|
||||||
|
about,
|
||||||
|
createdTime: now,
|
||||||
|
mostRecentActivityTime: now,
|
||||||
|
contractIds: contractIds,
|
||||||
|
anyoneCanJoin: true,
|
||||||
|
memberIds: [],
|
||||||
|
}
|
||||||
|
return await groupRef.create(group)
|
||||||
|
}
|
||||||
|
|
||||||
|
const convertTagToGroup = async (tag: string, groupName: string) => {
|
||||||
|
log(`Looking up contract IDs with tag ${tag}...`)
|
||||||
|
const contractIds = await getTaggedContractIds(tag)
|
||||||
|
log(`${contractIds.length} contracts found.`)
|
||||||
|
if (contractIds.length > 0) {
|
||||||
|
log(`Creating group ${groupName}...`)
|
||||||
|
const about = `Contracts that used to be tagged ${tag}.`
|
||||||
|
const result = await createGroup(groupName, about, contractIds)
|
||||||
|
log(`Done. Group: `, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
initAdmin()
|
||||||
|
const args = process.argv.slice(2)
|
||||||
|
if (args.length != 2) {
|
||||||
|
console.log('Usage: convert-tag-to-group [tag] [group-name]')
|
||||||
|
} else {
|
||||||
|
convertTagToGroup(args[0], args[1]).catch((e) => console.error(e))
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,20 +22,20 @@ export function LimitBets(props: {
|
||||||
className?: string
|
className?: string
|
||||||
}) {
|
}) {
|
||||||
const { contract, bets, className } = props
|
const { contract, bets, className } = props
|
||||||
const sortedBets = sortBy(
|
|
||||||
bets,
|
|
||||||
(bet) => -1 * bet.limitProb,
|
|
||||||
(bet) => -1 * bet.createdTime
|
|
||||||
)
|
|
||||||
const user = useUser()
|
const user = useUser()
|
||||||
const yourBets = sortedBets.filter((bet) => bet.userId === user?.id)
|
|
||||||
|
const yourBets = sortBy(
|
||||||
|
bets.filter((bet) => bet.userId === user?.id),
|
||||||
|
(bet) => -1 * bet.limitProb,
|
||||||
|
(bet) => bet.createdTime
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col className={className}>
|
<Col className={className}>
|
||||||
{yourBets.length === 0 && (
|
{yourBets.length === 0 && (
|
||||||
<OrderBookButton
|
<OrderBookButton
|
||||||
className="self-end"
|
className="self-end"
|
||||||
limitBets={sortedBets}
|
limitBets={bets}
|
||||||
contract={contract}
|
contract={contract}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -49,7 +49,7 @@ export function LimitBets(props: {
|
||||||
|
|
||||||
<OrderBookButton
|
<OrderBookButton
|
||||||
className="self-end"
|
className="self-end"
|
||||||
limitBets={sortedBets}
|
limitBets={bets}
|
||||||
contract={contract}
|
contract={contract}
|
||||||
/>
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -163,8 +163,18 @@ export function OrderBookButton(props: {
|
||||||
const { limitBets, contract, className } = props
|
const { limitBets, contract, className } = props
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
|
|
||||||
const yesBets = limitBets.filter((bet) => bet.outcome === 'YES')
|
const sortedBets = sortBy(
|
||||||
const noBets = limitBets.filter((bet) => bet.outcome === 'NO').reverse()
|
limitBets,
|
||||||
|
(bet) => -1 * bet.limitProb,
|
||||||
|
(bet) => bet.createdTime
|
||||||
|
)
|
||||||
|
|
||||||
|
const yesBets = sortedBets.filter((bet) => bet.outcome === 'YES')
|
||||||
|
const noBets = sortBy(
|
||||||
|
sortedBets.filter((bet) => bet.outcome === 'NO'),
|
||||||
|
(bet) => bet.limitProb,
|
||||||
|
(bet) => bet.createdTime
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -194,7 +204,7 @@ export function OrderBookButton(props: {
|
||||||
</Row>
|
</Row>
|
||||||
<Col className="md:hidden">
|
<Col className="md:hidden">
|
||||||
<LimitOrderTable
|
<LimitOrderTable
|
||||||
limitBets={limitBets}
|
limitBets={sortedBets}
|
||||||
contract={contract}
|
contract={contract}
|
||||||
isYou={false}
|
isYou={false}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -14,7 +14,7 @@ export const PortfolioValueSection = memo(
|
||||||
}) {
|
}) {
|
||||||
const { disableSelector, userId } = props
|
const { disableSelector, userId } = props
|
||||||
|
|
||||||
const [portfolioPeriod, setPortfolioPeriod] = useState<Period>('allTime')
|
const [portfolioPeriod, setPortfolioPeriod] = useState<Period>('weekly')
|
||||||
const [portfolioHistory, setUsersPortfolioHistory] = useState<
|
const [portfolioHistory, setUsersPortfolioHistory] = useState<
|
||||||
PortfolioMetrics[]
|
PortfolioMetrics[]
|
||||||
>([])
|
>([])
|
||||||
|
@ -53,13 +53,15 @@ export const PortfolioValueSection = memo(
|
||||||
{!disableSelector && (
|
{!disableSelector && (
|
||||||
<select
|
<select
|
||||||
className="select select-bordered self-start"
|
className="select select-bordered self-start"
|
||||||
|
value={portfolioPeriod}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setPortfolioPeriod(e.target.value as Period)
|
setPortfolioPeriod(e.target.value as Period)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<option value="allTime">{allTimeLabel}</option>
|
<option value="allTime">{allTimeLabel}</option>
|
||||||
<option value="weekly">7 days</option>
|
<option value="weekly">Last 7d</option>
|
||||||
<option value="daily">24 hours</option>
|
{/* Note: 'daily' seems to be broken? */}
|
||||||
|
{/* <option value="daily">Last 24h</option> */}
|
||||||
</select>
|
</select>
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
|
|
|
@ -39,8 +39,8 @@ export async function getStaticProps() {
|
||||||
])
|
])
|
||||||
const matches = quadraticMatches(txns, totalRaised)
|
const matches = quadraticMatches(txns, totalRaised)
|
||||||
const numDonors = uniqBy(txns, (txn) => txn.fromId).length
|
const numDonors = uniqBy(txns, (txn) => txn.fromId).length
|
||||||
const mostRecentDonor = await getUser(txns[0].fromId)
|
const mostRecentDonor = txns[0] ? await getUser(txns[0].fromId) : null
|
||||||
const mostRecentCharity = txns[0].toId
|
const mostRecentCharity = txns[0]?.toId ?? ''
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
|
@ -94,8 +94,8 @@ export default function Charity(props: {
|
||||||
matches: { [charityId: string]: number }
|
matches: { [charityId: string]: number }
|
||||||
txns: Txn[]
|
txns: Txn[]
|
||||||
numDonors: number
|
numDonors: number
|
||||||
mostRecentDonor: User
|
mostRecentDonor?: User | null
|
||||||
mostRecentCharity: string
|
mostRecentCharity?: string
|
||||||
}) {
|
}) {
|
||||||
const {
|
const {
|
||||||
totalRaised,
|
totalRaised,
|
||||||
|
@ -159,8 +159,8 @@ export default function Charity(props: {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Most recent donor',
|
name: 'Most recent donor',
|
||||||
stat: mostRecentDonor.name ?? 'Nobody',
|
stat: mostRecentDonor?.name ?? 'Nobody',
|
||||||
url: `/${mostRecentDonor.username}`,
|
url: `/${mostRecentDonor?.username}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Most recent donation',
|
name: 'Most recent donation',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user