Merge branch 'main' into link-to-comments
This commit is contained in:
commit
f1d675af37
|
@ -1,21 +1,17 @@
|
|||
export const CATEGORIES = {
|
||||
politics: 'Politics',
|
||||
technology: 'Technology',
|
||||
sports: 'Sports',
|
||||
gaming: 'Gaming',
|
||||
manifold: 'Manifold',
|
||||
science: 'Science',
|
||||
world: 'World',
|
||||
fun: 'Fun',
|
||||
personal: 'Personal',
|
||||
sports: 'Sports',
|
||||
economics: 'Economics',
|
||||
personal: 'Personal',
|
||||
culture: 'Culture',
|
||||
manifold: 'Manifold',
|
||||
covid: 'Covid',
|
||||
crypto: 'Crypto',
|
||||
health: 'Health',
|
||||
// entertainment: 'Entertainment',
|
||||
// society: 'Society',
|
||||
// friends: 'Friends / Community',
|
||||
// business: 'Business',
|
||||
// charity: 'Charities / Non-profits',
|
||||
gaming: 'Gaming',
|
||||
fun: 'Fun',
|
||||
} as { [category: string]: string }
|
||||
|
||||
export const TO_CATEGORY = Object.fromEntries(
|
||||
|
|
|
@ -43,7 +43,7 @@ export const PROD_CONFIG: EnvConfig = {
|
|||
],
|
||||
visibility: 'PUBLIC',
|
||||
|
||||
moneyMoniker: 'M$',
|
||||
moneyMoniker: 'ϻ',
|
||||
navbarLogoPath: '',
|
||||
faviconPath: '/favicon.ico',
|
||||
newQuestionPlaceholders: [
|
||||
|
|
|
@ -35,8 +35,6 @@ export function getNewContract(
|
|||
? getBinaryCpmmProps(initialProb, ante) // getBinaryDpmProps(initialProb, ante)
|
||||
: getFreeAnswerProps(ante)
|
||||
|
||||
const volume = outcomeType === 'BINARY' ? 0 : ante
|
||||
|
||||
const contract: Contract = removeUndefinedProps({
|
||||
id,
|
||||
slug,
|
||||
|
@ -56,7 +54,7 @@ export function getNewContract(
|
|||
createdTime: Date.now(),
|
||||
closeTime,
|
||||
|
||||
volume,
|
||||
volume: 0,
|
||||
volume24Hours: 0,
|
||||
volume7Days: 0,
|
||||
|
||||
|
|
|
@ -35,4 +35,5 @@ export type PrivateUser = {
|
|||
unsubscribedFromGenericEmails?: boolean
|
||||
initialDeviceToken?: string
|
||||
initialIpAddress?: string
|
||||
apiKey?: string
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
export const randomString = (length = 12) =>
|
||||
Math.random()
|
||||
.toString(16)
|
||||
.substring(2, length + 2)
|
||||
// Returns a cryptographically random hexadecimal string of length `length`
|
||||
// (thus containing 4*`length` bits of entropy).
|
||||
export const randomString = (length = 12) => {
|
||||
const bytes = new Uint8Array(Math.ceil(length / 2))
|
||||
crypto.getRandomValues(bytes)
|
||||
const hex = bytes.reduce((s, b) => s + ('0' + b.toString(16)).slice(-2), '')
|
||||
return hex.substring(0, length)
|
||||
}
|
||||
|
||||
export function genHash(str: string) {
|
||||
// xmur3
|
||||
|
@ -42,8 +46,6 @@ export function createRNG(seed: string) {
|
|||
export const shuffle = (array: any[], rand: () => number) => {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const swapIndex = Math.floor(rand() * (array.length - i))
|
||||
const temp = array[i]
|
||||
array[i] = array[swapIndex]
|
||||
array[swapIndex] = temp
|
||||
;[array[i], array[swapIndex]] = [array[swapIndex], array[i]]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ service cloud.firestore {
|
|||
|
||||
match /private-users/{userId} {
|
||||
allow read: if resource.data.id == request.auth.uid || isAdmin();
|
||||
allow update: if (resource.data.id == request.auth.uid || isAdmin())
|
||||
&& request.resource.data.diff(resource.data).affectedKeys()
|
||||
.hasOnly(['apiKey']);
|
||||
}
|
||||
|
||||
match /private-users/{userId}/views/{viewId} {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { User } from 'common/user'
|
||||
import { removeUndefinedProps } from 'common/util/object'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { User } from '../../common/user'
|
||||
import { removeUndefinedProps } from '../../common/util/object'
|
||||
import { redeemShares } from './redeem-shares'
|
||||
import { getNewLiquidityProvision } from 'common/add-liquidity'
|
||||
import { getNewLiquidityProvision } from '../../common/add-liquidity'
|
||||
|
||||
export const addLiquidity = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||
async (
|
||||
|
|
|
@ -2,12 +2,12 @@ import * as functions from 'firebase-functions'
|
|||
import * as admin from 'firebase-admin'
|
||||
|
||||
import { getUser } from './utils'
|
||||
import { Contract } from 'common/contract'
|
||||
import { Comment } from 'common/comment'
|
||||
import { User } from 'common/user'
|
||||
import { cleanUsername } from 'common/util/clean-username'
|
||||
import { removeUndefinedProps } from 'common/util/object'
|
||||
import { Answer } from 'common/answer'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { Comment } from '../../common/comment'
|
||||
import { User } from '../../common/user'
|
||||
import { cleanUsername } from '../../common/util/clean-username'
|
||||
import { removeUndefinedProps } from '../../common/util/object'
|
||||
import { Answer } from '../../common/answer'
|
||||
|
||||
export const changeUserInfo = functions
|
||||
.runWith({ minInstances: 1 })
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
|
||||
import { Contract, DPM, FreeResponse, FullContract } from 'common/contract'
|
||||
import { User } from 'common/user'
|
||||
import { getNewMultiBetInfo } from 'common/new-bet'
|
||||
import { Answer, MAX_ANSWER_LENGTH } from 'common/answer'
|
||||
import {
|
||||
Contract,
|
||||
DPM,
|
||||
FreeResponse,
|
||||
FullContract,
|
||||
} from '../../common/contract'
|
||||
import { User } from '../../common/user'
|
||||
import { getNewMultiBetInfo } from '../../common/new-bet'
|
||||
import { Answer, MAX_ANSWER_LENGTH } from '../../common/answer'
|
||||
import { getContract, getValues } from './utils'
|
||||
import { sendNewAnswerEmail } from './emails'
|
||||
import { Bet } from '../../common/bet'
|
||||
|
|
|
@ -14,10 +14,10 @@ import {
|
|||
MAX_QUESTION_LENGTH,
|
||||
MAX_TAG_LENGTH,
|
||||
outcomeType,
|
||||
} from 'common/contract'
|
||||
import { slugify } from 'common/util/slugify'
|
||||
import { randomString } from 'common/util/random'
|
||||
import { getNewContract } from 'common/new-contract'
|
||||
} from '../../common/contract'
|
||||
import { slugify } from '../../common/util/slugify'
|
||||
import { randomString } from '../../common/util/random'
|
||||
import { getNewContract } from '../../common/new-contract'
|
||||
import {
|
||||
FIXED_ANTE,
|
||||
getAnteBets,
|
||||
|
@ -25,8 +25,8 @@ import {
|
|||
getFreeAnswerAnte,
|
||||
HOUSE_LIQUIDITY_PROVIDER_ID,
|
||||
MINIMUM_ANTE,
|
||||
} from 'common/antes'
|
||||
import { getNoneAnswer } from 'common/answer'
|
||||
} from '../../common/antes'
|
||||
import { getNoneAnswer } from '../../common/answer'
|
||||
|
||||
export const createContract = functions
|
||||
.runWith({ minInstances: 1 })
|
||||
|
|
|
@ -3,10 +3,10 @@ import * as admin from 'firebase-admin'
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import { getUser } from './utils'
|
||||
import { Contract } from 'common/contract'
|
||||
import { slugify } from 'common/util/slugify'
|
||||
import { randomString } from 'common/util/random'
|
||||
import { Fold } from 'common/fold'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { slugify } from '../../common/util/slugify'
|
||||
import { randomString } from '../../common/util/random'
|
||||
import { Fold } from '../../common/fold'
|
||||
|
||||
export const createFold = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||
async (
|
||||
|
|
|
@ -6,12 +6,15 @@ import {
|
|||
STARTING_BALANCE,
|
||||
SUS_STARTING_BALANCE,
|
||||
User,
|
||||
} from 'common/user'
|
||||
} from '../../common/user'
|
||||
import { getUser, getUserByUsername } from './utils'
|
||||
import { randomString } from 'common/util/random'
|
||||
import { cleanDisplayName, cleanUsername } from 'common/util/clean-username'
|
||||
import { randomString } from '../../common/util/random'
|
||||
import {
|
||||
cleanDisplayName,
|
||||
cleanUsername,
|
||||
} from '../../common/util/clean-username'
|
||||
import { sendWelcomeEmail } from './emails'
|
||||
import { isWhitelisted } from 'common/envs/constants'
|
||||
import { isWhitelisted } from '../../common/envs/constants'
|
||||
|
||||
export const createUser = functions
|
||||
.runWith({ minInstances: 1 })
|
||||
|
@ -39,8 +42,7 @@ export const createUser = functions
|
|||
const name = cleanDisplayName(rawName)
|
||||
let username = cleanUsername(name)
|
||||
|
||||
const sameNameUser = await getUserByUsername(username)
|
||||
if (sameNameUser) {
|
||||
while (await getUserByUsername(username)) {
|
||||
username += randomString(4)
|
||||
}
|
||||
|
||||
|
|
|
@ -302,7 +302,7 @@
|
|||
font-family: Arial, sans-serif;
|
||||
font-size: 18px;
|
||||
"
|
||||
>Best of luck with you forecasting!</span
|
||||
>Best of luck with your forecasting!</span
|
||||
>
|
||||
</p>
|
||||
<p
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import { DOMAIN, PROJECT_ID } from 'common/envs/constants'
|
||||
import { Answer } from 'common/answer'
|
||||
import { Bet } from 'common/bet'
|
||||
import { getProbability } from 'common/calculate'
|
||||
import { Comment } from 'common/comment'
|
||||
import { Contract, FreeResponseContract } from 'common/contract'
|
||||
import { DPM_CREATOR_FEE } from 'common/fees'
|
||||
import { PrivateUser, User } from 'common/user'
|
||||
import { formatMoney, formatPercent } from 'common/util/format'
|
||||
|
||||
import { DOMAIN, PROJECT_ID } from '../../common/envs/constants'
|
||||
import { Answer } from '../../common/answer'
|
||||
import { Bet } from '../../common/bet'
|
||||
import { getProbability } from '../../common/calculate'
|
||||
import { Comment } from '../../common/comment'
|
||||
import { Contract, FreeResponseContract } from '../../common/contract'
|
||||
import { DPM_CREATOR_FEE } from '../../common/fees'
|
||||
import { PrivateUser, User } from '../../common/user'
|
||||
import { formatMoney, formatPercent } from '../../common/util/format'
|
||||
import { sendTemplateEmail } from './send-email'
|
||||
import { getPrivateUser, getUser } from './utils'
|
||||
|
||||
|
|
|
@ -1,19 +1,5 @@
|
|||
/* This use of module-alias hackily simulates the Typescript base URL so that
|
||||
* the Firebase deploy machinery, which just uses the compiled Javascript in the
|
||||
* lib directory, will be able to do imports from the root directory
|
||||
* (i.e. "common/foo" instead of "../../../common/foo") just like we can in
|
||||
* Typescript-land.
|
||||
*
|
||||
* Note that per the module-alias docs, this need to come before any other
|
||||
* imports in order to work.
|
||||
*
|
||||
* Suggested by https://github.com/firebase/firebase-tools/issues/986 where many
|
||||
* people complain about this problem.
|
||||
*/
|
||||
import { addPath } from 'module-alias'
|
||||
addPath('./lib')
|
||||
|
||||
import * as admin from 'firebase-admin'
|
||||
|
||||
admin.initializeApp()
|
||||
|
||||
// export * from './keep-awake'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { getPrivateUser, getUserByUsername } from './utils'
|
||||
import { sendMarketCloseEmail } from './emails'
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as admin from 'firebase-admin'
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import { getContract } from './utils'
|
||||
import { Bet } from 'common/bet'
|
||||
import { Bet } from '../../common/bet'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@ import * as admin from 'firebase-admin'
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import { getContract, getUser, getValues } from './utils'
|
||||
import { Comment } from 'common/comment'
|
||||
import { Comment } from '../../common/comment'
|
||||
import { sendNewCommentEmail } from './emails'
|
||||
import { Bet } from 'common/bet'
|
||||
import { Answer } from 'common/answer'
|
||||
import { Bet } from '../../common/bet'
|
||||
import { Answer } from '../../common/answer'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
import { View } from 'common/tracking'
|
||||
import { View } from '../../common/tracking'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { User } from 'common/user'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { User } from '../../common/user'
|
||||
import {
|
||||
getNewBinaryCpmmBetInfo,
|
||||
getNewBinaryDpmBetInfo,
|
||||
getNewMultiBetInfo,
|
||||
} from 'common/new-bet'
|
||||
import { addObjects, removeUndefinedProps } from 'common/util/object'
|
||||
import { Bet } from 'common/bet'
|
||||
} from '../../common/new-bet'
|
||||
import { addObjects, removeUndefinedProps } from '../../common/util/object'
|
||||
import { Bet } from '../../common/bet'
|
||||
import { redeemShares } from './redeem-shares'
|
||||
import { Fees } from 'common/fees'
|
||||
import { hasUserHitManaLimit } from 'common/calculate'
|
||||
import { Fees } from '../../common/fees'
|
||||
import { hasUserHitManaLimit } from '../../common/calculate'
|
||||
|
||||
export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||
async (
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { Bet } from 'common/bet'
|
||||
import { getProbability } from 'common/calculate'
|
||||
import { Bet } from '../../common/bet'
|
||||
import { getProbability } from '../../common/calculate'
|
||||
|
||||
import { Binary, CPMM, FullContract } from 'common/contract'
|
||||
import { noFees } from 'common/fees'
|
||||
import { User } from 'common/user'
|
||||
import { Binary, CPMM, FullContract } from '../../common/contract'
|
||||
import { noFees } from '../../common/fees'
|
||||
import { User } from '../../common/user'
|
||||
|
||||
export const redeemShares = async (userId: string, contractId: string) => {
|
||||
return await firestore.runTransaction(async (transaction) => {
|
||||
|
|
|
@ -2,9 +2,9 @@ import * as functions from 'firebase-functions'
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { User } from 'common/user'
|
||||
import { Bet } from 'common/bet'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { User } from '../../common/user'
|
||||
import { Bet } from '../../common/bet'
|
||||
import { getUser, isProd, payUser } from './utils'
|
||||
import { sendMarketResolutionEmail } from './emails'
|
||||
import {
|
||||
|
@ -12,9 +12,9 @@ import {
|
|||
getPayouts,
|
||||
groupPayoutsByUser,
|
||||
Payout,
|
||||
} from 'common/payouts'
|
||||
import { removeUndefinedProps } from 'common/util/object'
|
||||
import { LiquidityProvision } from 'common/liquidity-provision'
|
||||
} from '../../common/payouts'
|
||||
import { removeUndefinedProps } from '../../common/util/object'
|
||||
import { LiquidityProvision } from '../../common/liquidity-provision'
|
||||
|
||||
export const resolveMarket = functions
|
||||
.runWith({ minInstances: 1 })
|
||||
|
|
|
@ -5,9 +5,9 @@ import { initAdmin } from './script-init'
|
|||
initAdmin()
|
||||
|
||||
import { getValues } from '../utils'
|
||||
import { View } from 'common/tracking'
|
||||
import { User } from 'common/user'
|
||||
import { batchedWaitAll } from 'common/util/promise'
|
||||
import { View } from '../../../common/tracking'
|
||||
import { User } from '../../../common/user'
|
||||
import { batchedWaitAll } from '../../../common/util/promise'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Bet } from 'common/bet'
|
||||
import { getDpmProbability } from 'common/calculate-dpm'
|
||||
import { Binary, Contract, DPM, FullContract } from 'common/contract'
|
||||
import { Bet } from '../../../common/bet'
|
||||
import { getDpmProbability } from '../../../common/calculate-dpm'
|
||||
import { Binary, Contract, DPM, FullContract } from '../../../common/contract'
|
||||
|
||||
type DocRef = admin.firestore.DocumentReference
|
||||
const firestore = admin.firestore()
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { PrivateUser, STARTING_BALANCE, User } from 'common/user'
|
||||
import { PrivateUser, STARTING_BALANCE, User } from '../../../common/user'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ import * as fs from 'fs'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Bet } from 'common/bet'
|
||||
import { Contract } from 'common/contract'
|
||||
import { Bet } from '../../../common/bet'
|
||||
import { Contract } from '../../../common/contract'
|
||||
import { getValues } from '../utils'
|
||||
import { Comment } from 'common/comment'
|
||||
import { Comment } from '../../../common/comment'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import { initAdmin } from './script-init'
|
|||
initAdmin()
|
||||
|
||||
import { getValues } from '../utils'
|
||||
import { Fold } from 'common/fold'
|
||||
import { Fold } from '../../../common/fold'
|
||||
|
||||
async function lowercaseFoldTags() {
|
||||
const firestore = admin.firestore()
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { Contract } from '../../../common/contract'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Bet } from 'common/bet'
|
||||
import { Contract } from 'common/contract'
|
||||
import { Bet } from '../../../common/bet'
|
||||
import { Contract } from '../../../common/contract'
|
||||
|
||||
type DocRef = admin.firestore.DocumentReference
|
||||
|
||||
|
|
|
@ -4,13 +4,22 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Binary, Contract, CPMM, DPM, FullContract } from 'common/contract'
|
||||
import { Bet } from 'common/bet'
|
||||
import { calculateDpmPayout, getDpmProbability } from 'common/calculate-dpm'
|
||||
import { User } from 'common/user'
|
||||
import { getCpmmInitialLiquidity } from 'common/antes'
|
||||
import { noFees } from 'common/fees'
|
||||
import { addObjects } from 'common/util/object'
|
||||
import {
|
||||
Binary,
|
||||
Contract,
|
||||
CPMM,
|
||||
DPM,
|
||||
FullContract,
|
||||
} from '../../../common/contract'
|
||||
import { Bet } from '../../../common/bet'
|
||||
import {
|
||||
calculateDpmPayout,
|
||||
getDpmProbability,
|
||||
} from '../../../common/calculate-dpm'
|
||||
import { User } from '../../../common/user'
|
||||
import { getCpmmInitialLiquidity } from '../../../common/antes'
|
||||
import { noFees } from '../../../common/fees'
|
||||
import { addObjects } from '../../../common/util/object'
|
||||
|
||||
type DocRef = admin.firestore.DocumentReference
|
||||
|
||||
|
|
|
@ -4,11 +4,14 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Binary, Contract, DPM, FullContract } from 'common/contract'
|
||||
import { Bet } from 'common/bet'
|
||||
import { calculateDpmShares, getDpmProbability } from 'common/calculate-dpm'
|
||||
import { getSellBetInfo } from 'common/sell-bet'
|
||||
import { User } from 'common/user'
|
||||
import { Binary, Contract, DPM, FullContract } from '../../../common/contract'
|
||||
import { Bet } from '../../../common/bet'
|
||||
import {
|
||||
calculateDpmShares,
|
||||
getDpmProbability,
|
||||
} from '../../../common/calculate-dpm'
|
||||
import { getSellBetInfo } from '../../../common/sell-bet'
|
||||
import { User } from '../../../common/user'
|
||||
|
||||
type DocRef = admin.firestore.DocumentReference
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Bet } from 'common/bet'
|
||||
import { Contract } from 'common/contract'
|
||||
import { getLoanPayouts, getPayouts } from 'common/payouts'
|
||||
import { filterDefined } from 'common/util/array'
|
||||
import { Bet } from '../../../common/bet'
|
||||
import { Contract } from '../../../common/contract'
|
||||
import { getLoanPayouts, getPayouts } from '../../../common/payouts'
|
||||
import { filterDefined } from '../../../common/util/array'
|
||||
|
||||
type DocRef = admin.firestore.DocumentReference
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Bet } from 'common/bet'
|
||||
import { Contract } from 'common/contract'
|
||||
import { Bet } from '../../../common/bet'
|
||||
import { Contract } from '../../../common/contract'
|
||||
|
||||
type DocRef = admin.firestore.DocumentReference
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Bet } from 'common/bet'
|
||||
import { Contract } from 'common/contract'
|
||||
import { Bet } from '../../../common/bet'
|
||||
import { Contract } from '../../../common/contract'
|
||||
import { getValues } from '../utils'
|
||||
|
||||
async function removeAnswerAnte() {
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { Contract } from '../../../common/contract'
|
||||
import { getValues } from '../utils'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
|
|
@ -4,8 +4,8 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { parseTags } from 'common/util/parse'
|
||||
import { Contract } from '../../../common/contract'
|
||||
import { parseTags } from '../../../common/util/parse'
|
||||
import { getValues } from '../utils'
|
||||
|
||||
async function updateContractTags() {
|
||||
|
|
|
@ -5,9 +5,9 @@ import { initAdmin } from './script-init'
|
|||
initAdmin()
|
||||
|
||||
import { getValues } from '../utils'
|
||||
import { User } from 'common/user'
|
||||
import { batchedWaitAll } from 'common/util/promise'
|
||||
import { Contract } from 'common/contract'
|
||||
import { User } from '../../../common/user'
|
||||
import { batchedWaitAll } from '../../../common/util/promise'
|
||||
import { Contract } from '../../../common/contract'
|
||||
import { updateWordScores } from '../update-recommendations'
|
||||
import { computeFeed } from '../update-feed'
|
||||
import { getFeedContracts, getTaggedContracts } from '../get-feed-data'
|
||||
|
|
|
@ -4,9 +4,9 @@ import * as _ from 'lodash'
|
|||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { Contract } from '../../../common/contract'
|
||||
import { getValues } from '../utils'
|
||||
import { Comment } from 'common/comment'
|
||||
import { Comment } from '../../../common/comment'
|
||||
|
||||
async function updateLastCommentTime() {
|
||||
const firestore = admin.firestore()
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as functions from 'firebase-functions'
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { User } from 'common/user'
|
||||
import { Bet } from 'common/bet'
|
||||
import { getSellBetInfo } from 'common/sell-bet'
|
||||
import { addObjects, removeUndefinedProps } from 'common/util/object'
|
||||
import { Fees } from 'common/fees'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { User } from '../../common/user'
|
||||
import { Bet } from '../../common/bet'
|
||||
import { getSellBetInfo } from '../../common/sell-bet'
|
||||
import { addObjects, removeUndefinedProps } from '../../common/util/object'
|
||||
import { Fees } from '../../common/fees'
|
||||
|
||||
export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||
async (
|
||||
|
|
|
@ -2,12 +2,12 @@ import * as _ from 'lodash'
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as functions from 'firebase-functions'
|
||||
|
||||
import { Binary, CPMM, FullContract } from 'common/contract'
|
||||
import { User } from 'common/user'
|
||||
import { getCpmmSellBetInfo } from 'common/sell-bet'
|
||||
import { addObjects, removeUndefinedProps } from 'common/util/object'
|
||||
import { Binary, CPMM, FullContract } from '../../common/contract'
|
||||
import { User } from '../../common/user'
|
||||
import { getCpmmSellBetInfo } from '../../common/sell-bet'
|
||||
import { addObjects, removeUndefinedProps } from '../../common/util/object'
|
||||
import { getValues } from './utils'
|
||||
import { Bet } from 'common/bet'
|
||||
import { Bet } from '../../common/bet'
|
||||
|
||||
export const sellShares = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||
async (
|
||||
|
|
|
@ -54,7 +54,7 @@ export const createCheckoutSession = functions
|
|||
}
|
||||
|
||||
const referrer =
|
||||
req.query.referer || req.headers.referer || 'https://mantic.markets'
|
||||
req.query.referer || req.headers.referer || 'https://manifold.markets'
|
||||
|
||||
const session = await stripe.checkout.sessions.create({
|
||||
metadata: {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
|
||||
import { User } from 'common/user'
|
||||
import { Txn } from 'common/txn'
|
||||
import { removeUndefinedProps } from 'common/util/object'
|
||||
import { User } from '../../common/user'
|
||||
import { Txn } from '../../common/txn'
|
||||
import { removeUndefinedProps } from '../../common/util/object'
|
||||
|
||||
export const transact = functions
|
||||
.runWith({ minInstances: 1 })
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as functions from 'firebase-functions'
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { getUser } from './utils'
|
||||
import { PrivateUser } from 'common/user'
|
||||
import { PrivateUser } from '../../common/user'
|
||||
|
||||
export const unsubscribe = functions
|
||||
.runWith({ minInstances: 1 })
|
||||
|
|
|
@ -3,9 +3,9 @@ import * as admin from 'firebase-admin'
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import { getValues } from './utils'
|
||||
import { Contract } from 'common/contract'
|
||||
import { Bet } from 'common/bet'
|
||||
import { batchedWaitAll } from 'common/util/promise'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { Bet } from '../../common/bet'
|
||||
import { batchedWaitAll } from '../../common/util/promise'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ import * as functions from 'firebase-functions'
|
|||
import * as admin from 'firebase-admin'
|
||||
|
||||
import { getValue, getValues } from './utils'
|
||||
import { Contract } from 'common/contract'
|
||||
import { logInterpolation } from 'common/util/math'
|
||||
import { DAY_MS } from 'common/util/time'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { logInterpolation } from '../../common/util/math'
|
||||
import { DAY_MS } from '../../common/util/time'
|
||||
import {
|
||||
getProbability,
|
||||
getOutcomeProbability,
|
||||
|
@ -15,7 +15,7 @@ import { User } from '../../common/user'
|
|||
import {
|
||||
getContractScore,
|
||||
MAX_FEED_CONTRACTS,
|
||||
} from 'common/recommended-contracts'
|
||||
} from '../../common/recommended-contracts'
|
||||
import { callCloudFunction } from './call-cloud-function'
|
||||
import {
|
||||
getFeedContracts,
|
||||
|
@ -26,18 +26,25 @@ import { CATEGORY_LIST } from '../../common/categories'
|
|||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
const BATCH_SIZE = 30
|
||||
const MAX_BATCHES = 50
|
||||
|
||||
const getUserBatches = async () => {
|
||||
const users = _.shuffle(await getValues<User>(firestore.collection('users')))
|
||||
let userBatches: User[][] = []
|
||||
for (let i = 0; i < users.length; i += BATCH_SIZE) {
|
||||
userBatches.push(users.slice(i, i + BATCH_SIZE))
|
||||
}
|
||||
|
||||
console.log('updating feed batches', MAX_BATCHES, 'of', userBatches.length)
|
||||
|
||||
return userBatches.slice(0, MAX_BATCHES)
|
||||
}
|
||||
|
||||
export const updateFeed = functions.pubsub
|
||||
.schedule('every 60 minutes')
|
||||
.schedule('every 5 minutes')
|
||||
.onRun(async () => {
|
||||
const users = await getValues<User>(firestore.collection('users'))
|
||||
|
||||
const batchSize = 100
|
||||
let userBatches: User[][] = []
|
||||
for (let i = 0; i < users.length; i += batchSize) {
|
||||
userBatches.push(users.slice(i, i + batchSize))
|
||||
}
|
||||
|
||||
console.log('updating feed batch')
|
||||
const userBatches = await getUserBatches()
|
||||
|
||||
await Promise.all(
|
||||
userBatches.map((users) =>
|
||||
|
@ -72,13 +79,7 @@ export const updateFeedBatch = functions.https.onCall(
|
|||
export const updateCategoryFeed = functions.https.onCall(
|
||||
async (data: { category: string }) => {
|
||||
const { category } = data
|
||||
const users = await getValues<User>(firestore.collection('users'))
|
||||
|
||||
const batchSize = 100
|
||||
const userBatches: User[][] = []
|
||||
for (let i = 0; i < users.length; i += batchSize) {
|
||||
userBatches.push(users.slice(i, i + batchSize))
|
||||
}
|
||||
const userBatches = await getUserBatches()
|
||||
|
||||
await Promise.all(
|
||||
userBatches.map(async (users) => {
|
||||
|
|
|
@ -3,12 +3,12 @@ import * as admin from 'firebase-admin'
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import { getValue, getValues } from './utils'
|
||||
import { Contract } from 'common/contract'
|
||||
import { Bet } from 'common/bet'
|
||||
import { User } from 'common/user'
|
||||
import { ClickEvent } from 'common/tracking'
|
||||
import { getWordScores } from 'common/recommended-contracts'
|
||||
import { batchedWaitAll } from 'common/util/promise'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { Bet } from '../../common/bet'
|
||||
import { User } from '../../common/user'
|
||||
import { ClickEvent } from '../../common/tracking'
|
||||
import { getWordScores } from '../../common/recommended-contracts'
|
||||
import { batchedWaitAll } from '../../common/util/promise'
|
||||
import { callCloudFunction } from './call-cloud-function'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
|
|
@ -3,11 +3,11 @@ import * as admin from 'firebase-admin'
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import { getValues } from './utils'
|
||||
import { Contract } from 'common/contract'
|
||||
import { Bet } from 'common/bet'
|
||||
import { User } from 'common/user'
|
||||
import { batchedWaitAll } from 'common/util/promise'
|
||||
import { calculatePayout } from 'common/calculate'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { Bet } from '../../common/bet'
|
||||
import { User } from '../../common/user'
|
||||
import { batchedWaitAll } from '../../common/util/promise'
|
||||
import { calculatePayout } from '../../common/calculate'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { PrivateUser, User } from 'common/user'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { PrivateUser, User } from '../../common/user'
|
||||
|
||||
export const isProd =
|
||||
admin.instanceId().app.options.projectId === 'mantic-markets'
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import clsx from 'clsx'
|
||||
import _ from 'lodash'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { XIcon } from '@heroicons/react/solid'
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import clsx from 'clsx'
|
||||
import _ from 'lodash'
|
||||
|
||||
import { Answer } from 'common/answer'
|
||||
import { DPM, FreeResponse, FullContract } from 'common/contract'
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import clsx from 'clsx'
|
||||
import _ from 'lodash'
|
||||
import { useState } from 'react'
|
||||
import Textarea from 'react-expanding-textarea'
|
||||
|
||||
|
|
|
@ -321,11 +321,11 @@ function BuyPanel(props: {
|
|||
<Col className="mt-3 w-full gap-3">
|
||||
<Row className="items-center justify-between text-sm">
|
||||
<div className="text-gray-500">Probability</div>
|
||||
<Row>
|
||||
<div>{formatPercent(initialProb)}</div>
|
||||
<div className="mx-2">→</div>
|
||||
<div>{formatPercent(resultProb)}</div>
|
||||
</Row>
|
||||
<div>
|
||||
{formatPercent(initialProb)}
|
||||
<span className="mx-2">→</span>
|
||||
{formatPercent(resultProb)}
|
||||
</div>
|
||||
</Row>
|
||||
|
||||
<Row className="items-center justify-between gap-2 text-sm">
|
||||
|
@ -350,12 +350,12 @@ function BuyPanel(props: {
|
|||
|
||||
{dpmTooltip && <InfoTooltip text={dpmTooltip} />}
|
||||
</Row>
|
||||
<Row className="flex-wrap items-end justify-end gap-2">
|
||||
<span className="whitespace-nowrap">
|
||||
<div>
|
||||
<span className="mr-2 whitespace-nowrap">
|
||||
{formatMoney(currentPayout)}
|
||||
</span>
|
||||
<span>(+{currentReturnPercent})</span>
|
||||
</Row>
|
||||
(+{currentReturnPercent})
|
||||
</div>
|
||||
</Row>
|
||||
</Col>
|
||||
|
||||
|
@ -459,11 +459,11 @@ export function SellPanel(props: {
|
|||
<Col className="mt-3 w-full gap-3">
|
||||
<Row className="items-center justify-between text-sm">
|
||||
<div className="text-gray-500">Probability</div>
|
||||
<Row>
|
||||
<div>{formatPercent(initialProb)}</div>
|
||||
<div className="mx-2">→</div>
|
||||
<div>{formatPercent(resultProb)}</div>
|
||||
</Row>
|
||||
<div>
|
||||
{formatPercent(initialProb)}
|
||||
<span className="mx-2">→</span>
|
||||
{formatPercent(resultProb)}
|
||||
</div>
|
||||
</Row>
|
||||
</Col>
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import { useState } from 'react'
|
|||
import clsx from 'clsx'
|
||||
|
||||
import { BetPanelSwitcher } from './bet-panel'
|
||||
import { Row } from './layout/row'
|
||||
import { YesNoSelector } from './yes-no-selector'
|
||||
import { Binary, CPMM, DPM, FullContract } from 'common/contract'
|
||||
import { Modal } from './layout/modal'
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
} from '../hooks/use-sort-and-query-params'
|
||||
import { ContractsGrid } from './contract/contracts-list'
|
||||
import { Row } from './layout/row'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Spacer } from './layout/spacer'
|
||||
import { useRouter } from 'next/router'
|
||||
import { ENV } from 'common/envs/constants'
|
||||
|
@ -143,7 +143,13 @@ export function ContractSearchInner(props: {
|
|||
setQuery(query)
|
||||
}, [query])
|
||||
|
||||
const isFirstRender = useRef(true)
|
||||
useEffect(() => {
|
||||
if (isFirstRender.current) {
|
||||
isFirstRender.current = false
|
||||
return
|
||||
}
|
||||
|
||||
const sort = index.split('contracts-')[1] as Sort
|
||||
if (sort) {
|
||||
setSort(sort)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import clsx from 'clsx'
|
||||
import Link from 'next/link'
|
||||
import _ from 'lodash'
|
||||
import { Row } from '../layout/row'
|
||||
import { formatPercent } from 'common/util/format'
|
||||
import {
|
||||
|
@ -9,7 +8,6 @@ import {
|
|||
getBinaryProbPercent,
|
||||
} from 'web/lib/firebase/contracts'
|
||||
import { Col } from '../layout/col'
|
||||
import { Spacer } from '../layout/spacer'
|
||||
import {
|
||||
Binary,
|
||||
CPMM,
|
||||
|
@ -25,6 +23,8 @@ import {
|
|||
} from '../outcome-label'
|
||||
import { getOutcomeProbability, getTopAnswer } from 'common/calculate'
|
||||
import { AbbrContractDetails } from './contract-details'
|
||||
import { TagsList } from '../tags-list'
|
||||
import { CATEGORY_LIST } from 'common/categories'
|
||||
|
||||
export function ContractCard(props: {
|
||||
contract: Contract
|
||||
|
@ -35,11 +35,16 @@ export function ContractCard(props: {
|
|||
const { contract, showHotVolume, showCloseTime, className } = props
|
||||
const { question, outcomeType, resolution } = contract
|
||||
|
||||
const { tags } = contract
|
||||
const categories = tags.filter((tag) =>
|
||||
CATEGORY_LIST.includes(tag.toLowerCase())
|
||||
)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
<Col
|
||||
className={clsx(
|
||||
'relative rounded-lg bg-white p-6 shadow-md hover:bg-gray-100',
|
||||
'relative gap-3 rounded-lg bg-white p-6 shadow-md hover:bg-gray-100',
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
@ -52,35 +57,39 @@ export function ContractCard(props: {
|
|||
showHotVolume={showHotVolume}
|
||||
showCloseTime={showCloseTime}
|
||||
/>
|
||||
<Spacer h={3} />
|
||||
|
||||
<Row
|
||||
className={clsx(
|
||||
'justify-between gap-4',
|
||||
outcomeType === 'FREE_RESPONSE' && 'flex-col items-start !gap-2'
|
||||
)}
|
||||
>
|
||||
<p
|
||||
className="break-words font-medium text-indigo-700"
|
||||
style={{ /* For iOS safari */ wordBreak: 'break-word' }}
|
||||
>
|
||||
{question}
|
||||
</p>
|
||||
<Row className={clsx('justify-between gap-4')}>
|
||||
<Col className="gap-3">
|
||||
<p
|
||||
className="break-words font-medium text-indigo-700"
|
||||
style={{ /* For iOS safari */ wordBreak: 'break-word' }}
|
||||
>
|
||||
{question}
|
||||
</p>
|
||||
{outcomeType !== 'FREE_RESPONSE' && categories.length > 0 && (
|
||||
<TagsList tags={categories} noLabel />
|
||||
)}
|
||||
</Col>
|
||||
{outcomeType === 'BINARY' && (
|
||||
<BinaryResolutionOrChance
|
||||
className="items-center"
|
||||
contract={contract}
|
||||
/>
|
||||
)}
|
||||
{outcomeType === 'FREE_RESPONSE' && (
|
||||
<FreeResponseResolutionOrChance
|
||||
className="self-end text-gray-600"
|
||||
contract={contract as FullContract<DPM, FreeResponse>}
|
||||
truncate="long"
|
||||
/>
|
||||
)}
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
{outcomeType === 'FREE_RESPONSE' && (
|
||||
<FreeResponseResolutionOrChance
|
||||
className="self-end text-gray-600"
|
||||
contract={contract as FullContract<DPM, FreeResponse>}
|
||||
truncate="long"
|
||||
/>
|
||||
)}
|
||||
|
||||
{outcomeType === 'FREE_RESPONSE' && categories.length > 0 && (
|
||||
<TagsList tags={categories} noLabel />
|
||||
)}
|
||||
</Col>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -39,7 +39,9 @@ export function ContractDescription(props: {
|
|||
if (!isCreator && !contract.description.trim()) return null
|
||||
|
||||
const { tags } = contract
|
||||
const category = tags.find((tag) => CATEGORY_LIST.includes(tag.toLowerCase()))
|
||||
const categories = tags.filter((tag) =>
|
||||
CATEGORY_LIST.includes(tag.toLowerCase())
|
||||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -50,9 +52,9 @@ export function ContractDescription(props: {
|
|||
>
|
||||
<Linkify text={contract.description} />
|
||||
|
||||
{category && (
|
||||
{categories.length > 0 && (
|
||||
<div className="mt-4">
|
||||
<TagsList tags={[category]} label="Category" />
|
||||
<TagsList tags={categories} noLabel />
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import clsx from 'clsx'
|
||||
import _ from 'lodash'
|
||||
import { ClockIcon, DatabaseIcon, PencilIcon } from '@heroicons/react/outline'
|
||||
import { TrendingUpIcon } from '@heroicons/react/solid'
|
||||
import { Row } from '../layout/row'
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import _ from 'lodash'
|
||||
|
||||
import { Contract } from '../../lib/firebase/contracts'
|
||||
import { User } from '../../lib/firebase/users'
|
||||
import { Col } from '../layout/col'
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import _ from 'lodash'
|
||||
|
||||
import { Contract } from 'web/lib/firebase/contracts'
|
||||
import { Comment } from 'web/lib/firebase/comments'
|
||||
import { Col } from '../layout/col'
|
||||
|
|
|
@ -1,51 +1,43 @@
|
|||
import clsx from 'clsx'
|
||||
import _ from 'lodash'
|
||||
|
||||
import { User } from '../../../common/user'
|
||||
import { Row } from '../layout/row'
|
||||
import { CATEGORIES, CATEGORY_LIST } from '../../../common/categories'
|
||||
import { updateUser } from '../../lib/firebase/users'
|
||||
|
||||
export function CategorySelector(props: {
|
||||
user: User | null | undefined
|
||||
category: string
|
||||
setCategory: (category: string) => void
|
||||
className?: string
|
||||
}) {
|
||||
const { className, user } = props
|
||||
|
||||
const followedCategories = user?.followedCategories ?? []
|
||||
const { className, user, category, setCategory } = props
|
||||
|
||||
return (
|
||||
<Row
|
||||
className={clsx(
|
||||
'mr-2 items-center space-x-2 space-y-2 overflow-x-scroll scroll-smooth pt-4 pb-4 sm:flex-wrap',
|
||||
'carousel mr-2 items-center space-x-2 space-y-2 overflow-x-scroll pt-4 pb-4 sm:flex-wrap',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div />
|
||||
<CategoryButton
|
||||
key={'all' + followedCategories.length}
|
||||
key="all"
|
||||
category="All"
|
||||
isFollowed={followedCategories.length === 0}
|
||||
isFollowed={category === 'all'}
|
||||
toggle={async () => {
|
||||
if (!user?.id) return
|
||||
|
||||
await updateUser(user.id, {
|
||||
followedCategories: [],
|
||||
})
|
||||
setCategory('all')
|
||||
}}
|
||||
/>
|
||||
|
||||
{CATEGORY_LIST.map((cat) => (
|
||||
<CategoryButton
|
||||
key={cat + followedCategories.length}
|
||||
key={cat}
|
||||
category={CATEGORIES[cat].split(' ')[0]}
|
||||
isFollowed={followedCategories.includes(cat)}
|
||||
isFollowed={cat === category}
|
||||
toggle={async () => {
|
||||
if (!user?.id) return
|
||||
|
||||
await updateUser(user.id, {
|
||||
followedCategories: [cat],
|
||||
})
|
||||
setCategory(cat)
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
@ -63,7 +55,7 @@ function CategoryButton(props: {
|
|||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'rounded-full border-2 px-4 py-1 shadow-md',
|
||||
'rounded-full border-2 px-4 py-1 shadow-md hover:bg-gray-200',
|
||||
'cursor-pointer select-none',
|
||||
isFollowed ? 'border-gray-300 bg-gray-300' : 'bg-white'
|
||||
)}
|
||||
|
|
|
@ -977,7 +977,7 @@ function FeedAnswerGroup(props: {
|
|||
<Col
|
||||
className={
|
||||
type === 'answer'
|
||||
? 'border-base-200 bg-base-200 flex-1 rounded-md p-3'
|
||||
? 'border-base-200 bg-base-200 flex-1 rounded-md px-2'
|
||||
: 'flex-1 gap-2'
|
||||
}
|
||||
>
|
||||
|
@ -991,6 +991,12 @@ function FeedAnswerGroup(props: {
|
|||
/>
|
||||
</Modal>
|
||||
|
||||
{type == 'answer' && (
|
||||
<div
|
||||
className="pointer-events-none absolute -mx-2 h-full rounded-tl-md bg-green-600 bg-opacity-10"
|
||||
style={{ width: `${100 * Math.max(prob, 0.01)}%` }}
|
||||
></div>
|
||||
)}
|
||||
<Row className="my-4 gap-3">
|
||||
<div className="px-1">
|
||||
<Avatar username={username} avatarUrl={avatarUrl} />
|
||||
|
@ -1023,9 +1029,7 @@ function FeedAnswerGroup(props: {
|
|||
<span
|
||||
className={clsx(
|
||||
'text-2xl',
|
||||
tradingAllowed(contract)
|
||||
? 'text-green-500'
|
||||
: 'text-gray-500'
|
||||
tradingAllowed(contract) ? 'text-primary' : 'text-gray-500'
|
||||
)}
|
||||
>
|
||||
{probPercent}
|
||||
|
|
|
@ -137,7 +137,7 @@ export function MobileSidebar(props: {
|
|||
</div>
|
||||
</Transition.Child>
|
||||
<div className="mx-2 mt-5 h-0 flex-1 overflow-y-auto">
|
||||
<Sidebar />
|
||||
<Sidebar className="pl-2" />
|
||||
</div>
|
||||
</div>
|
||||
</Transition.Child>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import Link from 'next/link'
|
||||
import { firebaseLogout, User } from 'web/lib/firebase/users'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
import { Avatar } from '../avatar'
|
||||
import { IS_PRIVATE_MANIFOLD } from 'common/envs/constants'
|
||||
import { Row } from '../layout/row'
|
||||
|
||||
export function getNavigationOptions(user?: User | null) {
|
||||
if (IS_PRIVATE_MANIFOLD) {
|
||||
|
@ -27,18 +27,18 @@ export function getNavigationOptions(user?: User | null) {
|
|||
]
|
||||
}
|
||||
|
||||
export function ProfileSummary(props: { user: User | undefined }) {
|
||||
export function ProfileSummary(props: { user: User }) {
|
||||
const { user } = props
|
||||
return (
|
||||
<Row className="group items-center gap-4 rounded-md py-3 text-gray-500 group-hover:bg-gray-100 group-hover:text-gray-700">
|
||||
<Avatar avatarUrl={user?.avatarUrl} username={user?.username} noLink />
|
||||
<Link href={`/${user.username}`}>
|
||||
<a className="group flex flex-row items-center gap-4 rounded-md py-3 text-gray-500 hover:bg-gray-100 hover:text-gray-700">
|
||||
<Avatar avatarUrl={user.avatarUrl} username={user.username} noLink />
|
||||
|
||||
<div className="truncate text-left">
|
||||
<div>{user?.name}</div>
|
||||
<div className="text-sm">
|
||||
{user ? formatMoney(Math.floor(user.balance)) : ' '}
|
||||
<div className="truncate">
|
||||
<div>{user.name}</div>
|
||||
<div className="text-sm">{formatMoney(Math.floor(user.balance))}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Row>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import {
|
||||
HomeIcon,
|
||||
UserGroupIcon,
|
||||
CakeIcon,
|
||||
SearchIcon,
|
||||
ChatIcon,
|
||||
BookOpenIcon,
|
||||
DotsHorizontalIcon,
|
||||
CashIcon,
|
||||
|
@ -110,7 +108,8 @@ function MoreButton() {
|
|||
)
|
||||
}
|
||||
|
||||
export default function Sidebar() {
|
||||
export default function Sidebar(props: { className?: string }) {
|
||||
const { className } = props
|
||||
const router = useRouter()
|
||||
const currentPage = router.pathname
|
||||
|
||||
|
@ -124,27 +123,15 @@ export default function Sidebar() {
|
|||
user === null ? signedOutMobileNavigation : mobileNavigation
|
||||
|
||||
return (
|
||||
<nav aria-label="Sidebar" className="sticky top-4 divide-gray-300 pl-2">
|
||||
<div className="space-y-1 pb-6">
|
||||
<ManifoldLogo twoLine />
|
||||
</div>
|
||||
|
||||
<nav aria-label="Sidebar" className={className}>
|
||||
<ManifoldLogo className="pb-6" twoLine />
|
||||
<div className="mb-2" style={{ minHeight: 80 }}>
|
||||
{user ? (
|
||||
<Link href={`/${user.username}`}>
|
||||
<a className="group">
|
||||
<ProfileSummary user={user} />
|
||||
</a>
|
||||
</Link>
|
||||
<ProfileSummary user={user} />
|
||||
) : user === null ? (
|
||||
<div className="py-6 text-center">
|
||||
<button
|
||||
className="btn btn-sm px-6 font-medium normal-case "
|
||||
style={{
|
||||
backgroundColor: 'white',
|
||||
border: '2px solid',
|
||||
color: '#3D4451',
|
||||
}}
|
||||
className="btn btn-sm border-2 bg-white px-6 font-medium normal-case text-gray-700"
|
||||
onClick={firebaseLogin}
|
||||
>
|
||||
Sign in
|
||||
|
|
|
@ -12,7 +12,7 @@ export function Page(props: {
|
|||
const { margin, assertUser, children, rightSidebar, suspend } = props
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<div
|
||||
className={clsx(
|
||||
'mx-auto w-full pb-14 lg:grid lg:grid-cols-12 lg:gap-8 lg:pt-6 xl:max-w-7xl',
|
||||
|
@ -20,9 +20,7 @@ export function Page(props: {
|
|||
)}
|
||||
style={suspend ? visuallyHiddenStyle : undefined}
|
||||
>
|
||||
<div className="hidden lg:col-span-2 lg:block">
|
||||
<Sidebar />
|
||||
</div>
|
||||
<Sidebar className="sticky top-4 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:block" />
|
||||
<main
|
||||
className={clsx(
|
||||
'lg:col-span-8',
|
||||
|
@ -40,7 +38,7 @@ export function Page(props: {
|
|||
</div>
|
||||
|
||||
<BottomNavBar />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import clsx from 'clsx'
|
|||
import React, { useEffect, useState } from 'react'
|
||||
|
||||
import { Col } from './layout/col'
|
||||
import { Title } from './title'
|
||||
import { User } from 'web/lib/firebase/users'
|
||||
import { YesNoCancelSelector } from './yes-no-selector'
|
||||
import { Spacer } from './layout/spacer'
|
||||
|
|
|
@ -13,6 +13,7 @@ export function ShareMarket(props: { contract: Contract; className?: string }) {
|
|||
<Row className="mb-6 items-center">
|
||||
<input
|
||||
className="input input-bordered flex-1 rounded-r-none text-gray-500"
|
||||
readOnly
|
||||
type="text"
|
||||
value={contractUrl(contract)}
|
||||
/>
|
||||
|
|
|
@ -10,8 +10,11 @@ import {
|
|||
getTopWeeklyContracts,
|
||||
} from 'web/lib/firebase/contracts'
|
||||
|
||||
export const useAlgoFeed = (user: User | null | undefined) => {
|
||||
const [feed, setFeed] = useState<feed>()
|
||||
export const useAlgoFeed = (
|
||||
user: User | null | undefined,
|
||||
category: string
|
||||
) => {
|
||||
const [allFeed, setAllFeed] = useState<feed>()
|
||||
const [categoryFeeds, setCategoryFeeds] = useState<Dictionary<feed>>()
|
||||
|
||||
const getTime = useTimeSinceFirstRender()
|
||||
|
@ -20,11 +23,11 @@ export const useAlgoFeed = (user: User | null | undefined) => {
|
|||
if (user) {
|
||||
getUserFeed(user.id).then((feed) => {
|
||||
if (feed.length === 0) {
|
||||
getDefaultFeed().then((feed) => setFeed(feed))
|
||||
} else setFeed(feed)
|
||||
getDefaultFeed().then((feed) => setAllFeed(feed))
|
||||
} else setAllFeed(feed)
|
||||
|
||||
trackLatency('feed', getTime())
|
||||
console.log('feed load time', getTime())
|
||||
console.log('"all" feed load time', getTime())
|
||||
})
|
||||
|
||||
getCategoryFeeds(user.id).then((feeds) => {
|
||||
|
@ -35,12 +38,9 @@ export const useAlgoFeed = (user: User | null | undefined) => {
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [user?.id])
|
||||
|
||||
const followedCategory = user?.followedCategories?.[0] ?? 'all'
|
||||
const feed = category === 'all' ? allFeed : categoryFeeds?.[category]
|
||||
|
||||
const followedFeed =
|
||||
followedCategory === 'all' ? feed : categoryFeeds?.[followedCategory]
|
||||
|
||||
return followedFeed
|
||||
return feed
|
||||
}
|
||||
|
||||
const getDefaultFeed = async () => {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { doc, collection, setDoc } from 'firebase/firestore'
|
||||
import _ from 'lodash'
|
||||
|
||||
import { db } from './init'
|
||||
import { ClickEvent, LatencyEvent, View } from 'common/tracking'
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { collection, query, where, orderBy } from 'firebase/firestore'
|
||||
import _ from 'lodash'
|
||||
import { Txn } from 'common/txn'
|
||||
|
||||
import { db } from './init'
|
||||
|
|
|
@ -55,6 +55,13 @@ export async function updateUser(userId: string, update: Partial<User>) {
|
|||
await updateDoc(doc(db, 'users', userId), { ...update })
|
||||
}
|
||||
|
||||
export async function updatePrivateUser(
|
||||
userId: string,
|
||||
update: Partial<PrivateUser>
|
||||
) {
|
||||
await updateDoc(doc(db, 'private-users', userId), { ...update })
|
||||
}
|
||||
|
||||
export function listenForUser(
|
||||
userId: string,
|
||||
setUser: (user: User | null) => void
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { db } from './init'
|
||||
import {
|
||||
getDoc,
|
||||
getDocs,
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"postbuild": "next-sitemap"
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/react": "1.5.0",
|
||||
"@headlessui/react": "1.6.1",
|
||||
"@heroicons/react": "1.0.5",
|
||||
"@nivo/core": "0.74.0",
|
||||
"@nivo/line": "0.74.0",
|
||||
|
|
|
@ -26,7 +26,7 @@ function printBuildInfo() {
|
|||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
usePreserveScroll()
|
||||
|
||||
useEffect(printBuildInfo)
|
||||
useEffect(printBuildInfo, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -39,6 +39,19 @@ function MyApp({ Component, pageProps }: AppProps) {
|
|||
gtag('config', 'G-SSFK1Q138D');
|
||||
`}
|
||||
</Script>
|
||||
{/* Hotjar Tracking Code for https://manifold.markets */}
|
||||
<Script id="hotjar">
|
||||
{`
|
||||
(function(h,o,t,j,a,r){
|
||||
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
|
||||
h._hjSettings={hjid:2968940,hjsv:6};
|
||||
a=o.getElementsByTagName('head')[0];
|
||||
r=o.createElement('script');r.async=1;
|
||||
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
|
||||
a.appendChild(r);
|
||||
})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
|
||||
`}
|
||||
</Script>
|
||||
<Head>
|
||||
<title>Manifold Markets — A market for every question</title>
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import { getDailyNewUsers } from 'web/lib/firebase/users'
|
|||
|
||||
export const getStaticProps = fromPropz(getStaticPropz)
|
||||
export async function getStaticPropz() {
|
||||
const numberOfDays = 90
|
||||
const numberOfDays = 45
|
||||
const today = dayjs(dayjs().format('YYYY-MM-DD'))
|
||||
const startDate = today.subtract(numberOfDays, 'day')
|
||||
|
||||
|
|
|
@ -13,14 +13,12 @@ import { InfoTooltip } from 'web/components/info-tooltip'
|
|||
import { Page } from 'web/components/page'
|
||||
import { Title } from 'web/components/title'
|
||||
import { ProbabilitySelector } from 'web/components/probability-selector'
|
||||
import { parseWordsAsTags } from 'common/util/parse'
|
||||
import { TagsList } from 'web/components/tags-list'
|
||||
import { Row } from 'web/components/layout/row'
|
||||
import { MAX_DESCRIPTION_LENGTH, outcomeType } from 'common/contract'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
import { useHasCreatedContractToday } from 'web/hooks/use-has-created-contract-today'
|
||||
import { removeUndefinedProps } from '../../common/util/object'
|
||||
import { CATEGORIES, CATEGORY_LIST, TO_CATEGORY } from 'common/categories'
|
||||
import { CATEGORIES } from 'common/categories'
|
||||
|
||||
export default function Create() {
|
||||
const [question, setQuestion] = useState('')
|
||||
|
@ -214,15 +212,13 @@ export function NewContract(props: { question: string; tag?: string }) {
|
|||
|
||||
<select
|
||||
className="select select-bordered w-full max-w-xs"
|
||||
onChange={(e) =>
|
||||
setCategory(TO_CATEGORY[e.currentTarget.value] ?? '')
|
||||
}
|
||||
value={category}
|
||||
onChange={(e) => setCategory(e.currentTarget.value ?? '')}
|
||||
>
|
||||
<option selected={category === ''}></option>
|
||||
|
||||
{CATEGORY_LIST.map((cat) => (
|
||||
<option selected={category === cat} value={CATEGORIES[cat]}>
|
||||
{CATEGORIES[cat]}
|
||||
<option value={''}></option>
|
||||
{Object.entries(CATEGORIES).map(([id, name]) => (
|
||||
<option key={id} value={id}>
|
||||
{name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import React, { useEffect } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Router, { useRouter } from 'next/router'
|
||||
import _ from 'lodash'
|
||||
|
||||
import { Page } from 'web/components/page'
|
||||
import { ActivityFeed } from 'web/components/feed/activity-feed'
|
||||
import FeedCreate from 'web/components/feed-create'
|
||||
|
@ -15,8 +13,9 @@ import { CategorySelector } from '../components/feed/category-selector'
|
|||
|
||||
const Home = () => {
|
||||
const user = useUser()
|
||||
const [category, setCategory] = useState<string>('all')
|
||||
|
||||
const feed = useAlgoFeed(user)
|
||||
const feed = useAlgoFeed(user, category)
|
||||
|
||||
const router = useRouter()
|
||||
const { u: username, s: slug } = router.query
|
||||
|
@ -40,27 +39,24 @@ const Home = () => {
|
|||
return (
|
||||
<>
|
||||
<Page assertUser="signed-in" suspend={!!contract}>
|
||||
<Col className="items-center">
|
||||
<Col className="w-full max-w-[700px]">
|
||||
<FeedCreate user={user ?? undefined} />
|
||||
<Spacer h={2} />
|
||||
|
||||
<CategorySelector user={user} />
|
||||
|
||||
<Spacer h={1} />
|
||||
|
||||
{feed ? (
|
||||
<ActivityFeed
|
||||
feed={feed}
|
||||
mode="only-recent"
|
||||
getContractPath={(c) =>
|
||||
`home?u=${c.creatorUsername}&s=${c.slug}`
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<LoadingIndicator className="mt-4" />
|
||||
)}
|
||||
</Col>
|
||||
<Col className="mx-auto w-full max-w-[700px]">
|
||||
<FeedCreate user={user ?? undefined} />
|
||||
<Spacer h={2} />
|
||||
<CategorySelector
|
||||
user={user}
|
||||
category={category}
|
||||
setCategory={setCategory}
|
||||
/>
|
||||
<Spacer h={1} />
|
||||
{feed ? (
|
||||
<ActivityFeed
|
||||
feed={feed}
|
||||
mode="only-recent"
|
||||
getContractPath={(c) => `home?u=${c.creatorUsername}&s=${c.slug}`}
|
||||
/>
|
||||
) : (
|
||||
<LoadingIndicator className="mt-4" />
|
||||
)}
|
||||
</Col>
|
||||
</Page>
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import _ from 'lodash'
|
||||
|
||||
import { Col } from 'web/components/layout/col'
|
||||
import { Leaderboard } from 'web/components/leaderboard'
|
||||
import { Page } from 'web/components/page'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { PencilIcon } from '@heroicons/react/outline'
|
||||
import { RefreshIcon } from '@heroicons/react/outline'
|
||||
import Router from 'next/router'
|
||||
|
||||
import { AddFundsButton } from 'web/components/add-funds-button'
|
||||
|
@ -14,7 +14,7 @@ import { uploadImage } from 'web/lib/firebase/storage'
|
|||
import { Col } from 'web/components/layout/col'
|
||||
import { Row } from 'web/components/layout/row'
|
||||
import { User } from 'common/user'
|
||||
import { updateUser } from 'web/lib/firebase/users'
|
||||
import { updateUser, updatePrivateUser } from 'web/lib/firebase/users'
|
||||
import { defaultBannerUrl } from 'web/components/user-page'
|
||||
import { SiteLink } from 'web/components/site-link'
|
||||
import Textarea from 'react-expanding-textarea'
|
||||
|
@ -64,6 +64,7 @@ export default function ProfilePage() {
|
|||
const [avatarLoading, setAvatarLoading] = useState(false)
|
||||
const [name, setName] = useState(user?.name || '')
|
||||
const [username, setUsername] = useState(user?.username || '')
|
||||
const [apiKey, setApiKey] = useState(privateUser?.apiKey || '')
|
||||
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
|
@ -73,6 +74,12 @@ export default function ProfilePage() {
|
|||
}
|
||||
}, [user])
|
||||
|
||||
useEffect(() => {
|
||||
if (privateUser) {
|
||||
setApiKey(privateUser.apiKey || '')
|
||||
}
|
||||
}, [privateUser])
|
||||
|
||||
const updateDisplayName = async () => {
|
||||
const newName = cleanDisplayName(name)
|
||||
|
||||
|
@ -104,6 +111,17 @@ export default function ProfilePage() {
|
|||
}
|
||||
}
|
||||
|
||||
const updateApiKey = async (e: React.MouseEvent) => {
|
||||
const newApiKey = crypto.randomUUID()
|
||||
if (user?.id != null) {
|
||||
setApiKey(newApiKey)
|
||||
await updatePrivateUser(user.id, { apiKey: newApiKey }).catch(() => {
|
||||
setApiKey(privateUser?.apiKey || '')
|
||||
})
|
||||
}
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
const fileHandler = async (event: any) => {
|
||||
const file = event.target.files[0]
|
||||
|
||||
|
@ -156,7 +174,6 @@ export default function ProfilePage() {
|
|||
|
||||
<div>
|
||||
<label className="label">Display name</label>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Display name"
|
||||
|
@ -169,7 +186,6 @@ export default function ProfilePage() {
|
|||
|
||||
<div>
|
||||
<label className="label">Username</label>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Username"
|
||||
|
@ -234,6 +250,25 @@ export default function ProfilePage() {
|
|||
<AddFundsButton />
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="label">API key</label>
|
||||
<div className="input-group w-full">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Click refresh to generate key"
|
||||
className="input input-bordered w-full"
|
||||
value={apiKey}
|
||||
readOnly
|
||||
/>
|
||||
<button
|
||||
className="btn btn-primary btn-square p-2"
|
||||
onClick={updateApiKey}
|
||||
>
|
||||
<RefreshIcon />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Col>
|
||||
</Page>
|
||||
|
|
12
yarn.lock
12
yarn.lock
|
@ -683,10 +683,10 @@
|
|||
protobufjs "^6.10.0"
|
||||
yargs "^16.2.0"
|
||||
|
||||
"@headlessui/react@1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.5.0.tgz#483b44ba2c8b8d4391e1d2c863898d7dd0cc0296"
|
||||
integrity sha512-aaRnYxBb3MU2FNJf3Ut9RMTUqqU3as0aI1lQhgo2n9Fa67wRu14iOGqx93xB+uMNVfNwZ5B3y/Ndm7qZGuFeMQ==
|
||||
"@headlessui/react@1.6.1":
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.6.1.tgz#d822792e589aac005462491dd62f86095e0c3bef"
|
||||
integrity sha512-gMd6uIs1U4Oz718Z5gFoV0o/vD43/4zvbyiJN9Dt7PK9Ubxn+TmJwTmYwyNJc5KxxU1t0CmgTNgwZX9+4NjCnQ==
|
||||
|
||||
"@heroicons/react@1.0.5":
|
||||
version "1.0.5"
|
||||
|
@ -958,7 +958,7 @@
|
|||
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
|
||||
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
|
||||
|
||||
"@react-query-firebase/firestore@^0.4.2":
|
||||
"@react-query-firebase/firestore@0.4.2":
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@react-query-firebase/firestore/-/firestore-0.4.2.tgz#6ae52768715aa0a5c0d903dd4fd953ed417ba635"
|
||||
integrity sha512-7eYp905+sfBRcBTdj7W7BAc3bI3V0D0kKca4/juOTnN4gyoNyaCNOCjLPY467dTq325hGs7BX0ol7Pw3JENdHA==
|
||||
|
@ -4754,7 +4754,7 @@ react-motion@^0.5.2:
|
|||
prop-types "^15.5.8"
|
||||
raf "^3.1.0"
|
||||
|
||||
react-query@^3.39.0:
|
||||
react-query@3.39.0:
|
||||
version "3.39.0"
|
||||
resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.39.0.tgz#0caca7b0da98e65008bbcd4df0d25618c2100050"
|
||||
integrity sha512-Od0IkSuS79WJOhzWBx/ys0x13+7wFqgnn64vBqqAAnZ9whocVhl/y1padD5uuZ6EIkXbFbInax0qvY7zGM0thA==
|
||||
|
|
Loading…
Reference in New Issue
Block a user