Simple bet fill notification
This commit is contained in:
parent
e2e59b5726
commit
9e7b3c0887
|
@ -62,3 +62,4 @@ export type notification_reason_types =
|
||||||
| 'unique_bettors_on_your_contract'
|
| 'unique_bettors_on_your_contract'
|
||||||
| 'on_group_you_are_member_of'
|
| 'on_group_you_are_member_of'
|
||||||
| 'tip_received'
|
| 'tip_received'
|
||||||
|
| 'bet_fill'
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { Contract } from '../../common/contract'
|
||||||
import { getUserByUsername, getValues } from './utils'
|
import { getUserByUsername, getValues } from './utils'
|
||||||
import { Comment } from '../../common/comment'
|
import { Comment } from '../../common/comment'
|
||||||
import { uniq } from 'lodash'
|
import { uniq } from 'lodash'
|
||||||
import { Bet } from '../../common/bet'
|
import { Bet, LimitBet } from '../../common/bet'
|
||||||
import { Answer } from '../../common/answer'
|
import { Answer } from '../../common/answer'
|
||||||
import { getContractBetMetrics } from '../../common/calculate'
|
import { getContractBetMetrics } from '../../common/calculate'
|
||||||
import { removeUndefinedProps } from '../../common/util/object'
|
import { removeUndefinedProps } from '../../common/util/object'
|
||||||
|
@ -382,3 +382,37 @@ export const createTipNotification = async (
|
||||||
}
|
}
|
||||||
return await notificationRef.set(removeUndefinedProps(notification))
|
return await notificationRef.set(removeUndefinedProps(notification))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const createBetFillNotification = async (
|
||||||
|
fromUser: User,
|
||||||
|
toUser: User,
|
||||||
|
bet: Bet,
|
||||||
|
userBet: LimitBet,
|
||||||
|
contract: Contract,
|
||||||
|
idempotencyKey: string
|
||||||
|
) => {
|
||||||
|
const fill = userBet.fills.find((fill) => fill.matchedBetId === bet.id)
|
||||||
|
const fillAmount = fill?.amount ?? 0
|
||||||
|
|
||||||
|
const notificationRef = firestore
|
||||||
|
.collection(`/users/${toUser.id}/notifications`)
|
||||||
|
.doc(idempotencyKey)
|
||||||
|
const notification: Notification = {
|
||||||
|
id: idempotencyKey,
|
||||||
|
userId: toUser.id,
|
||||||
|
reason: 'bet_fill',
|
||||||
|
createdTime: Date.now(),
|
||||||
|
isSeen: false,
|
||||||
|
sourceId: userBet.id,
|
||||||
|
sourceType: 'bet',
|
||||||
|
sourceUpdateType: 'updated',
|
||||||
|
sourceUserName: fromUser.name,
|
||||||
|
sourceUserUsername: fromUser.username,
|
||||||
|
sourceUserAvatarUrl: fromUser.avatarUrl,
|
||||||
|
sourceText: fillAmount.toString(),
|
||||||
|
sourceContractCreatorUsername: contract.creatorUsername,
|
||||||
|
sourceContractTitle: contract.question,
|
||||||
|
sourceContractSlug: contract.slug,
|
||||||
|
}
|
||||||
|
return await notificationRef.set(removeUndefinedProps(notification))
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import * as functions from 'firebase-functions'
|
import * as functions from 'firebase-functions'
|
||||||
import * as admin from 'firebase-admin'
|
import * as admin from 'firebase-admin'
|
||||||
|
import { keyBy } from 'lodash'
|
||||||
|
|
||||||
import { Bet } from '../../common/bet'
|
import { Bet, LimitBet } from '../../common/bet'
|
||||||
|
import { getContract, getUser, getValues } from './utils'
|
||||||
|
import { createBetFillNotification } from './create-notification'
|
||||||
|
import { filterDefined } from '../../common/util/array'
|
||||||
|
|
||||||
const firestore = admin.firestore()
|
const firestore = admin.firestore()
|
||||||
|
|
||||||
|
@ -11,6 +15,8 @@ export const onCreateBet = functions.firestore
|
||||||
const { contractId } = context.params as {
|
const { contractId } = context.params as {
|
||||||
contractId: string
|
contractId: string
|
||||||
}
|
}
|
||||||
|
const { eventId } = context
|
||||||
|
|
||||||
const bet = change.data() as Bet
|
const bet = change.data() as Bet
|
||||||
const lastBetTime = bet.createdTime
|
const lastBetTime = bet.createdTime
|
||||||
|
|
||||||
|
@ -18,4 +24,47 @@ export const onCreateBet = functions.firestore
|
||||||
.collection('contracts')
|
.collection('contracts')
|
||||||
.doc(contractId)
|
.doc(contractId)
|
||||||
.update({ lastBetTime, lastUpdatedTime: Date.now() })
|
.update({ lastBetTime, lastUpdatedTime: Date.now() })
|
||||||
|
|
||||||
|
await notifyFills(bet, contractId, eventId)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const notifyFills = async (bet: Bet, contractId: string, eventId: string) => {
|
||||||
|
if (!bet.fills) return
|
||||||
|
|
||||||
|
const user = await getUser(bet.userId)
|
||||||
|
if (!user) return
|
||||||
|
const contract = await getContract(contractId)
|
||||||
|
if (!contract) return
|
||||||
|
|
||||||
|
const matchedFills = bet.fills.filter((fill) => fill.matchedBetId !== null)
|
||||||
|
const matchedBets = (
|
||||||
|
await Promise.all(
|
||||||
|
matchedFills.map((fill) =>
|
||||||
|
getValues<LimitBet>(
|
||||||
|
firestore.collectionGroup('bets').where('id', '==', fill.matchedBetId)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).flat()
|
||||||
|
|
||||||
|
const betUsers = await Promise.all(
|
||||||
|
matchedBets.map((bet) => getUser(bet.userId))
|
||||||
|
)
|
||||||
|
const betUsersById = keyBy(filterDefined(betUsers), 'id')
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
matchedBets.map((matchedBet) => {
|
||||||
|
const matchedUser = betUsersById[matchedBet.userId]
|
||||||
|
if (!matchedUser) return
|
||||||
|
|
||||||
|
return createBetFillNotification(
|
||||||
|
user,
|
||||||
|
matchedUser,
|
||||||
|
bet,
|
||||||
|
matchedBet,
|
||||||
|
contract,
|
||||||
|
eventId
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -795,6 +795,8 @@ function getSourceIdForLinkComponent(
|
||||||
return sourceId
|
return sourceId
|
||||||
case 'contract':
|
case 'contract':
|
||||||
return ''
|
return ''
|
||||||
|
case 'bet':
|
||||||
|
return ''
|
||||||
default:
|
default:
|
||||||
return sourceId
|
return sourceId
|
||||||
}
|
}
|
||||||
|
@ -861,8 +863,17 @@ function NotificationTextLabel(props: {
|
||||||
{'+' + formatMoney(parseInt(sourceText))}
|
{'+' + formatMoney(parseInt(sourceText))}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
|
} else if (sourceType === 'bet' && sourceText) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
Filled{' '}
|
||||||
|
<span className="text-primary">
|
||||||
|
{formatMoney(parseInt(sourceText))}
|
||||||
|
</span>{' '}
|
||||||
|
<span>of your limit bet</span>
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// return default text
|
|
||||||
return (
|
return (
|
||||||
<div className={className ? className : 'line-clamp-4 whitespace-pre-line'}>
|
<div className={className ? className : 'line-clamp-4 whitespace-pre-line'}>
|
||||||
<Linkify text={defaultText} />
|
<Linkify text={defaultText} />
|
||||||
|
@ -913,6 +924,9 @@ function getReasonForShowingNotification(
|
||||||
else if (sourceSlug) reasonText = 'joined because you shared'
|
else if (sourceSlug) reasonText = 'joined because you shared'
|
||||||
else reasonText = 'joined because of you'
|
else reasonText = 'joined because of you'
|
||||||
break
|
break
|
||||||
|
case 'bet':
|
||||||
|
reasonText = 'bet against you'
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
reasonText = ''
|
reasonText = ''
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user