Add market liquidity addition events to bets feed (#578)
* Add liquidity events to bets feed * Use larger avatar for liquidity feed items
This commit is contained in:
parent
0067bee94b
commit
3b6ba76db6
|
@ -8,15 +8,17 @@ import { Spacer } from '../layout/spacer'
|
|||
import { Tabs } from '../layout/tabs'
|
||||
import { Col } from '../layout/col'
|
||||
import { CommentTipMap } from 'web/hooks/use-tip-txns'
|
||||
import { LiquidityProvision } from 'common/liquidity-provision'
|
||||
|
||||
export function ContractTabs(props: {
|
||||
contract: Contract
|
||||
user: User | null | undefined
|
||||
bets: Bet[]
|
||||
liquidityProvisions: LiquidityProvision[]
|
||||
comments: Comment[]
|
||||
tips: CommentTipMap
|
||||
}) {
|
||||
const { contract, user, bets, comments, tips } = props
|
||||
const { contract, user, bets, comments, tips, liquidityProvisions } = props
|
||||
const { outcomeType } = contract
|
||||
|
||||
const userBets = user && bets.filter((bet) => bet.userId === user.id)
|
||||
|
@ -25,6 +27,7 @@ export function ContractTabs(props: {
|
|||
<ContractActivity
|
||||
contract={contract}
|
||||
bets={bets}
|
||||
liquidityProvisions={liquidityProvisions}
|
||||
comments={comments}
|
||||
tips={tips}
|
||||
user={user}
|
||||
|
@ -38,6 +41,7 @@ export function ContractTabs(props: {
|
|||
<ContractActivity
|
||||
contract={contract}
|
||||
bets={bets}
|
||||
liquidityProvisions={liquidityProvisions}
|
||||
comments={comments}
|
||||
tips={tips}
|
||||
user={user}
|
||||
|
@ -55,6 +59,7 @@ export function ContractTabs(props: {
|
|||
<ContractActivity
|
||||
contract={contract}
|
||||
bets={bets}
|
||||
liquidityProvisions={liquidityProvisions}
|
||||
comments={comments}
|
||||
tips={tips}
|
||||
user={user}
|
||||
|
|
|
@ -7,6 +7,7 @@ import { Comment } from 'common/comment'
|
|||
import { Contract, FreeResponseContract } from 'common/contract'
|
||||
import { User } from 'common/user'
|
||||
import { CommentTipMap } from 'web/hooks/use-tip-txns'
|
||||
import { LiquidityProvision } from 'common/liquidity-provision'
|
||||
|
||||
export type ActivityItem =
|
||||
| DescriptionItem
|
||||
|
@ -17,6 +18,7 @@ export type ActivityItem =
|
|||
| ResolveItem
|
||||
| CommentInputItem
|
||||
| CommentThreadItem
|
||||
| LiquidityItem
|
||||
|
||||
type BaseActivityItem = {
|
||||
id: string
|
||||
|
@ -72,6 +74,14 @@ export type ResolveItem = BaseActivityItem & {
|
|||
type: 'resolve'
|
||||
}
|
||||
|
||||
export type LiquidityItem = BaseActivityItem & {
|
||||
type: 'liquidity'
|
||||
liquidity: LiquidityProvision
|
||||
hideOutcome: boolean
|
||||
smallAvatar: boolean
|
||||
hideComment?: boolean
|
||||
}
|
||||
|
||||
function getAnswerAndCommentInputGroups(
|
||||
contract: FreeResponseContract,
|
||||
bets: Bet[],
|
||||
|
@ -139,6 +149,7 @@ export function getSpecificContractActivityItems(
|
|||
contract: Contract,
|
||||
bets: Bet[],
|
||||
comments: Comment[],
|
||||
liquidityProvisions: LiquidityProvision[],
|
||||
tips: CommentTipMap,
|
||||
user: User | null | undefined,
|
||||
options: {
|
||||
|
@ -146,7 +157,7 @@ export function getSpecificContractActivityItems(
|
|||
}
|
||||
) {
|
||||
const { mode } = options
|
||||
const items = [] as ActivityItem[]
|
||||
let items = [] as ActivityItem[]
|
||||
|
||||
switch (mode) {
|
||||
case 'bets':
|
||||
|
@ -163,6 +174,23 @@ export function getSpecificContractActivityItems(
|
|||
hideComment: true,
|
||||
}))
|
||||
)
|
||||
items.push(
|
||||
...liquidityProvisions.map((liquidity) => ({
|
||||
type: 'liquidity' as const,
|
||||
id: liquidity.id,
|
||||
contract,
|
||||
liquidity,
|
||||
hideOutcome: false,
|
||||
smallAvatar: false,
|
||||
}))
|
||||
)
|
||||
items = sortBy(items, (item) =>
|
||||
item.type === 'bet'
|
||||
? item.bet.createdTime
|
||||
: item.type === 'liquidity'
|
||||
? item.liquidity.createdTime
|
||||
: undefined
|
||||
)
|
||||
break
|
||||
|
||||
case 'comments': {
|
||||
|
|
|
@ -8,11 +8,13 @@ import { FeedItems } from './feed-items'
|
|||
import { User } from 'common/user'
|
||||
import { useContractWithPreload } from 'web/hooks/use-contract'
|
||||
import { CommentTipMap } from 'web/hooks/use-tip-txns'
|
||||
import { LiquidityProvision } from 'common/liquidity-provision'
|
||||
|
||||
export function ContractActivity(props: {
|
||||
contract: Contract
|
||||
bets: Bet[]
|
||||
comments: Comment[]
|
||||
liquidityProvisions: LiquidityProvision[]
|
||||
tips: CommentTipMap
|
||||
user: User | null | undefined
|
||||
mode: 'comments' | 'bets' | 'free-response-comment-answer-groups'
|
||||
|
@ -20,7 +22,8 @@ export function ContractActivity(props: {
|
|||
className?: string
|
||||
betRowClassName?: string
|
||||
}) {
|
||||
const { user, mode, tips, className, betRowClassName } = props
|
||||
const { user, mode, tips, className, betRowClassName, liquidityProvisions } =
|
||||
props
|
||||
|
||||
const contract = useContractWithPreload(props.contract) ?? props.contract
|
||||
|
||||
|
@ -33,6 +36,7 @@ export function ContractActivity(props: {
|
|||
contract,
|
||||
bets,
|
||||
comments,
|
||||
liquidityProvisions,
|
||||
tips,
|
||||
user,
|
||||
{ mode }
|
||||
|
|
|
@ -35,6 +35,7 @@ import {
|
|||
} from 'web/components/feed/feed-comments'
|
||||
import { FeedBet } from 'web/components/feed/feed-bets'
|
||||
import { NumericContract } from 'common/contract'
|
||||
import { FeedLiquidity } from './feed-liquidity'
|
||||
|
||||
export function FeedItems(props: {
|
||||
contract: Contract
|
||||
|
@ -83,6 +84,8 @@ export function FeedItem(props: { item: ActivityItem }) {
|
|||
return <FeedDescription {...item} />
|
||||
case 'bet':
|
||||
return <FeedBet {...item} />
|
||||
case 'liquidity':
|
||||
return <FeedLiquidity {...item} />
|
||||
case 'answergroup':
|
||||
return <FeedAnswerCommentGroup {...item} />
|
||||
case 'close':
|
||||
|
|
85
web/components/feed/feed-liquidity.tsx
Normal file
85
web/components/feed/feed-liquidity.tsx
Normal file
|
@ -0,0 +1,85 @@
|
|||
import dayjs from 'dayjs'
|
||||
import { User } from 'common/user'
|
||||
import { useUser, useUserById } from 'web/hooks/use-user'
|
||||
import { Row } from 'web/components/layout/row'
|
||||
import { Avatar, EmptyAvatar } from 'web/components/avatar'
|
||||
import clsx from 'clsx'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
import { RelativeTimestamp } from 'web/components/relative-timestamp'
|
||||
import React from 'react'
|
||||
import { UserLink } from '../user-page'
|
||||
import { LiquidityProvision } from 'common/liquidity-provision'
|
||||
|
||||
export function FeedLiquidity(props: {
|
||||
liquidity: LiquidityProvision
|
||||
smallAvatar: boolean
|
||||
}) {
|
||||
const { liquidity, smallAvatar } = props
|
||||
const { userId, createdTime } = liquidity
|
||||
|
||||
const isBeforeJune2022 = dayjs(createdTime).isBefore('2022-06-01')
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const bettor = isBeforeJune2022 ? undefined : useUserById(userId)
|
||||
|
||||
const user = useUser()
|
||||
const isSelf = user?.id === userId
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row className={'flex w-full gap-2 pt-3'}>
|
||||
{isSelf ? (
|
||||
<Avatar
|
||||
className={clsx(smallAvatar && 'ml-1')}
|
||||
size={smallAvatar ? 'sm' : undefined}
|
||||
avatarUrl={user.avatarUrl}
|
||||
username={user.username}
|
||||
/>
|
||||
) : bettor ? (
|
||||
<Avatar
|
||||
className={clsx(smallAvatar && 'ml-1')}
|
||||
size={smallAvatar ? 'sm' : undefined}
|
||||
avatarUrl={bettor.avatarUrl}
|
||||
username={bettor.username}
|
||||
/>
|
||||
) : (
|
||||
<div className="relative px-1">
|
||||
<EmptyAvatar />
|
||||
</div>
|
||||
)}
|
||||
<div className={'min-w-0 flex-1 py-1.5'}>
|
||||
<LiquidityStatusText
|
||||
liquidity={liquidity}
|
||||
isSelf={isSelf}
|
||||
bettor={bettor}
|
||||
/>
|
||||
</div>
|
||||
</Row>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function LiquidityStatusText(props: {
|
||||
liquidity: LiquidityProvision
|
||||
isSelf: boolean
|
||||
bettor?: User
|
||||
}) {
|
||||
const { liquidity, bettor, isSelf } = props
|
||||
const { amount, createdTime } = liquidity
|
||||
|
||||
// TODO: Withdrawn liquidity will never be shown, since liquidity amounts currently are zeroed out upon withdrawal.
|
||||
const bought = amount >= 0 ? 'added' : 'withdrew'
|
||||
const money = formatMoney(Math.abs(amount))
|
||||
|
||||
return (
|
||||
<div className="text-sm text-gray-500">
|
||||
{bettor ? (
|
||||
<UserLink name={bettor.name} username={bettor.username} />
|
||||
) : (
|
||||
<span>{isSelf ? 'You' : 'A trader'}</span>
|
||||
)}{' '}
|
||||
{bought} {money}
|
||||
{' of liquidity'}
|
||||
<RelativeTimestamp time={createdTime} />
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -42,6 +42,7 @@ import { useBets } from 'web/hooks/use-bets'
|
|||
import { AlertBox } from 'web/components/alert-box'
|
||||
import { useTracking } from 'web/hooks/use-tracking'
|
||||
import { CommentTipMap, useTipTxns } from 'web/hooks/use-tip-txns'
|
||||
import { useLiquidity } from 'web/hooks/use-liquidity'
|
||||
|
||||
export const getStaticProps = fromPropz(getStaticPropz)
|
||||
export async function getStaticPropz(props: {
|
||||
|
@ -117,6 +118,8 @@ export function ContractPageContent(
|
|||
})
|
||||
|
||||
const bets = useBets(contract.id) ?? props.bets
|
||||
const liquidityProvisions =
|
||||
useLiquidity(contract.id)?.filter((l) => !l.isAnte && l.amount > 0) ?? []
|
||||
// Sort for now to see if bug is fixed.
|
||||
comments.sort((c1, c2) => c1.createdTime - c2.createdTime)
|
||||
|
||||
|
@ -233,6 +236,7 @@ export function ContractPageContent(
|
|||
<ContractTabs
|
||||
contract={contract}
|
||||
user={user}
|
||||
liquidityProvisions={liquidityProvisions}
|
||||
bets={bets}
|
||||
tips={tips}
|
||||
comments={comments}
|
||||
|
|
Loading…
Reference in New Issue
Block a user