Skip to content

Commit

Permalink
Broadcast metric updates
Browse files Browse the repository at this point in the history
  • Loading branch information
IanPhilips committed Oct 10, 2024
1 parent a042c0c commit 61f2fda
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 90 deletions.
54 changes: 29 additions & 25 deletions backend/api/src/multi-sell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const multiSellMain: APIHandler<'multi-sell'> = async (props, auth) => {
const user = await getUser(uid)
if (!user) throw new APIError(401, 'Your account was not found')

const { bets, contract } = await runShortTrans(async (pgTrans) => {
const results = await runShortTrans(async (pgTrans) => {
const contract = await getContract(pgTrans, contractId)
if (!contract) throw new APIError(404, 'Contract not found')
const { closeTime, isResolved, mechanism } = contract
Expand Down Expand Up @@ -95,7 +95,6 @@ const multiSellMain: APIHandler<'multi-sell'> = async (props, auth) => {
`You specified an answer to sell in which you have 0 shares.`
)

const betGroupId = crypto.randomBytes(12).toString('hex')
const betResults = getCpmmMultiSellSharesInfo(
contract,
answers,
Expand All @@ -104,52 +103,57 @@ const multiSellMain: APIHandler<'multi-sell'> = async (props, auth) => {
balancesByUserId,
loanAmountByAnswerId
)
const results = []
log(`Calculated new bet information for ${user.username} - auth ${uid}.`)
const bets = await Promise.all(
betResults.map((newBetResult) =>
executeNewBetResult(
pgTrans,
newBetResult,
contract,
user,
isApi,
contractMetrics,
undefined,
betGroupId,
deterministic,
false
)
const betGroupId = crypto.randomBytes(12).toString('hex')
for (const newBetResult of betResults) {
const result = await executeNewBetResult(
pgTrans,
newBetResult,
contract,
user,
isApi,
contractMetrics,
undefined,
betGroupId,
deterministic,
false
)
)
results.push(result)
}
const bets = results.flatMap((r) => r.fullBets)
const loanPaid = sum(Object.values(loanAmountByAnswerId))
if (loanPaid > 0 && bets.length > 0) {
await incrementBalance(pgTrans, uid, {
balance: -loanPaid,
})
}
return { bets, contract }
return results
})

log(`Main transaction finished - auth ${uid}.`)

const continuation = async () => {
const fullBets = bets.flatMap((result) => result.fullBets)
const allOrdersToCancel = bets.flatMap((result) => result.allOrdersToCancel)
const makers = bets.flatMap((result) => result.makers ?? [])
const user = bets[0].user
const fullBets = results.flatMap((result) => result.fullBets)
const allOrdersToCancel = results.flatMap(
(result) => result.allOrdersToCancel
)
const makers = results.flatMap((result) => result.makers ?? [])
const user = results[0].user
await onCreateBets(
fullBets,
contract,
results[0].contract,
user,
allOrdersToCancel,
makers,
bets.some((b) => b.streakIncremented),
results.some((b) => b.streakIncremented),
undefined,
undefined
)
}

return {
result: bets.map((result) => ({
result: results.map((result) => ({
...result.newBet,
betId: result.betId,
betGroupId: result.betGroupId,
Expand Down
21 changes: 19 additions & 2 deletions backend/api/src/on-create-bet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,14 @@ import {
addHouseSubsidyToAnswer,
} from 'shared/helpers/add-house-subsidy'
import { debounce } from 'api/helpers/debounce'
import { broadcastNewBets, broadcastOrders } from 'shared/websockets/helpers'
import {
broadcastNewBets,
broadcastOrders,
broadcastUpdatedMetrics,
} from 'shared/websockets/helpers'
import { followContractInternal } from 'api/follow-contract'
import { ContractMetric } from 'common/contract-metric'
import { getContractMetrics } from 'shared/helpers/user-contract-metrics'

export const onCreateBets = async (
bets: Bet[],
Expand All @@ -54,10 +60,21 @@ export const onCreateBets = async (
ordersToCancel: LimitBet[] | undefined,
makers: maker[] | undefined,
streakIncremented: boolean,
txn: UniqueBettorBonusTxn | undefined
txn: UniqueBettorBonusTxn | undefined,
updatedMetrics: ContractMetric[] | undefined
) => {
const pg = createSupabaseDirectClient()
broadcastNewBets(contract.id, contract.visibility, bets)
if (!updatedMetrics) {
updatedMetrics = await getContractMetrics(
pg,
[originalBettor.id],
contract.id,
[],
true
)
}
broadcastUpdatedMetrics(updatedMetrics)
debouncedContractUpdates(contract)
const matchedBetIds = filterDefined(
bets.flatMap((b) => b.fills?.map((f) => f.matchedBetId) ?? [])
Expand Down
31 changes: 17 additions & 14 deletions backend/api/src/place-bet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,21 +218,22 @@ export const placeBetMain = async (
)
const { updatedMetrics } = result
log('Redeeming shares for bettor', user.username, user.id)
const { bets: redemptionBets } = await redeemShares(
pgTrans,
[user.id],
contract,
[
{
...newBetResult.newBet,
userId: user.id,
},
],
updatedMetrics
)
const { bets: redemptionBets, updatedMetrics: redemptionUpdatedMetrics } =
await redeemShares(
pgTrans,
[user.id],
contract,
[
{
...newBetResult.newBet,
userId: user.id,
},
],
updatedMetrics
)
result.fullBets.push(...redemptionBets)
log('Share redemption transaction finished.')
return result
return { ...result, updatedMetrics: redemptionUpdatedMetrics }
})

const {
Expand All @@ -244,6 +245,7 @@ export const placeBetMain = async (
betGroupId,
streakIncremented,
bonuxTxn,
updatedMetrics,
} = result

log(`Main transaction finished - auth ${uid}.`)
Expand All @@ -257,7 +259,8 @@ export const placeBetMain = async (
allOrdersToCancel,
makers,
streakIncremented,
bonuxTxn
bonuxTxn,
updatedMetrics
)
}

Expand Down
3 changes: 2 additions & 1 deletion backend/api/src/place-multi-bet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ export const placeMultiBetMain = async (
allOrdersToCancel,
makers,
results.some((r) => r.streakIncremented),
results.find((r) => r.bonuxTxn)?.bonuxTxn
results.find((r) => r.bonuxTxn)?.bonuxTxn,
undefined
)
}

Expand Down
4 changes: 3 additions & 1 deletion backend/api/src/sell-shares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ const sellSharesMain: APIHandler<'market/:contractId/sell'> = async (
fullBets,
allOrdersToCancel,
streakIncremented,
updatedMetrics,
} = result

const continuation = async () => {
Expand All @@ -307,7 +308,8 @@ const sellSharesMain: APIHandler<'market/:contractId/sell'> = async (
allOrdersToCancel,
makers,
streakIncremented,
undefined
undefined,
updatedMetrics
)
}
return { result: { ...newBet, betId }, continue: continuation }
Expand Down
13 changes: 13 additions & 0 deletions backend/shared/src/websockets/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { ContractComment } from 'common/comment'
import { User } from 'common/user'
import { Answer } from 'common/answer'
import { ChartAnnotation } from 'common/supabase/chart-annotations'
import { ContractMetric } from 'common/contract-metric'
import { groupBy } from 'lodash'

export function broadcastUpdatedPrivateUser(userId: string) {
// don't send private user info because it's private and anyone can listen
Expand Down Expand Up @@ -37,6 +39,17 @@ export function broadcastOrders(bets: LimitBet[]) {
broadcast(`contract/${contractId}/orders`, { bets })
}

export function broadcastUpdatedMetrics(metrics: ContractMetric[]) {
if (metrics.length === 0) return
const { contractId } = metrics[0]
const metricsByUser = groupBy(metrics, (m) => m.userId)
for (const userMetrics of Object.values(metricsByUser)) {
broadcast(`contract/${contractId}/user-metrics/${userMetrics[0].userId}`, {
metrics: userMetrics,
})
}
}

export function broadcastNewComment(
contractId: string,
visibility: Visibility,
Expand Down
7 changes: 5 additions & 2 deletions web/components/answers/numeric-bet-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -445,10 +445,13 @@ export const MultiNumericDistributionChart = (props: {
height,
} = props
const { min, max } = contract
const data = useMemo(() => getExpectedValuesArray(contract), [contract])
const data = useMemo(
() => getExpectedValuesArray(contract),
[contract.answers]
)
const otherData = useMemo(
() => (updatedContract ? getExpectedValuesArray(updatedContract) : []),
[updatedContract]
[updatedContract?.answers]
)
const maxY = Math.max(...data.map((d) => d.y))
const otherMaxY = Math.max(...otherData.map((d) => d.y))
Expand Down
50 changes: 5 additions & 45 deletions web/hooks/use-saved-contract-metrics.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import { ContractMetric } from 'common/contract-metric'
import { Contract } from 'common/contract'
import { useUser } from './use-user'
import { uniqBy } from 'lodash'
import { getTopContractMetrics } from 'common/supabase/contract-metrics'
import { db } from 'web/lib/supabase/db'
import { useEffect, useState } from 'react'
import { usePersistentLocalState } from './use-persistent-local-state'
import { useEvent } from 'web/hooks/use-event'
import { useApiSubscription } from 'web/hooks/use-api-subscription'
import { Bet } from 'common/bet'
import {
calculateProfitMetricsWithProb,
calculateAnswerMetricsWithNewBetsOnly,
getDefaultMetric,
applyMetricToSummary,
} from 'common/calculate-metrics'
Expand All @@ -23,13 +20,9 @@ export const useSavedContractMetrics = (
answerId?: string
) => {
const user = useUser()
const [newBets, setNewBets] = useState<Bet[]>([])
const [savedMetrics, setSavedMetrics] = usePersistentLocalState<
ContractMetric[] | undefined
>(undefined, `contract-metrics-${contract.id}-${answerId}-saved`)
const [newMetric, setNewMetric] = usePersistentLocalState<
ContractMetric | undefined
>(undefined, `contract-metrics-${contract.id}-new-${answerId}-new`)

const updateMetricsWithNewProbs = (metrics: ContractMetric[]) => {
if (!user) return metrics
Expand Down Expand Up @@ -64,56 +57,23 @@ export const useSavedContractMetrics = (
)
if (!metrics.length) return
setSavedMetrics(updateMetricsWithNewProbs(metrics))
setNewMetric(undefined)
})

useEffect(() => {
refreshMyMetrics()
}, [user?.id, contract.id, answerId])

useApiSubscription({
topics: [`contract/${contract.id}/new-bet`],
topics: [`contract/${contract.id}/user-metrics/${user?.id}`],
onBroadcast: (msg) => {
const myNewBets = (msg.data.bets as Bet[]).filter(
(bet) =>
bet.userId === user?.id &&
(answerId ? bet.answerId === answerId : true)
)
setNewBets((prevBets) =>
uniqBy([...prevBets, ...myNewBets], (bet) => bet.id)
)
const metrics = msg.data.metrics as ContractMetric[]
setSavedMetrics(metrics)
},
enabled: !!user?.id,
})

useEffect(() => {
if (!newBets.length) return
const metrics = savedMetrics ?? []
const metricsWithNewBets = calculateAnswerMetricsWithNewBetsOnly(
newBets,
metrics,
contract.id,
contract.mechanism === 'cpmm-multi-1'
)

const updatedMetrics = [
...metricsWithNewBets,
...metrics.filter(
(m) => !metricsWithNewBets.some((um) => um.answerId == m.answerId)
),
] as ContractMetric[]
const newestMetrics = updateMetricsWithNewProbs(updatedMetrics)
const newestMetric = newestMetrics.find((m) =>
answerId ? m.answerId === answerId : m.answerId == null
)
setNewMetric(newestMetric)
}, [newBets.length, contract.lastBetTime])

return (
newMetric ??
savedMetrics?.find((m) =>
answerId ? m.answerId === answerId : m.answerId == null
)
return savedMetrics?.find((m) =>
answerId ? m.answerId === answerId : m.answerId == null
)
}

Expand Down

0 comments on commit 61f2fda

Please sign in to comment.