Skip to Content
Developer HubGuides & Tutorials

Adding Live. Step 3: Realtime market updates

Add WebSocket

As for prematch games, live game’s markets are constantly updated:

  • Market can be stopped and unstopped.
  • Outcomes odds can be changed.

To receive updates, utilize the Socket API. Begin by creating a new socket instance.

The simplest approach is to utilize or duplicate the SocketContext from the SDK:
https://github.com/Azuro-protocol/sdk/blob/v3.1.0/src/contexts/socket.tsx 

The main components here are the event-emitters:

These events are triggered by the prematch contract event listeners  and the socket message handler:

socket.current.onmessage = (message: MessageEvent<SocketData>) => { JSON.parse(message.data.toString()).forEach((data: SocketData[0]) => { const { id: conditionId, reinforcement, margin, winningOutcomesCount } = data if (data.outcomes) { const eventData: OddsChangedData = { conditionId: conditionId, reinforcement: +reinforcement, margin: +margin, winningOutcomesCount: +winningOutcomesCount, outcomes: {}, } eventData.outcomes = data.outcomes.reduce((acc, { id, odds, clearOdds, maxStake }) => { acc[id] = { odds, clearOdds, maxBet: maxStake, } return acc }, {} as Record<number, OddsChangedData['outcomes'][0]>) oddsWatcher.dispatch(conditionId, eventData) } if (data.state) { conditionStatusWatcher.dispatch(conditionId, data.state) } }) }

Use Created WebSocket Context

You can subscribe to updates by providing condition IDs to listen to.

Here’s how it’s implemented in the SDK:

  • useSelection : Used in outcome buttons within the market selection UI, including event lists and details pages.
  • useStatuses : Utilized in the betslip for user selected outcomes.
  • useOdds : Employed in the betslip for user selected outcomes.
part of useSelection.ts
import { isLiveEntity } from '@/config' export const useSelection = ({ selection, initialOdds, initialStatus }: Props) => { const { coreAddress, conditionId, outcomeId } = selection const { contracts } = useChain() const { prematchClient } = useApolloClients() const { isSocketReady, subscribeToUpdates, unsubscribeToUpdates } = useSocket() const isLive = isLiveEntity(selection) useEffect(() => { if (!isLive || !isSocketReady) { return } subscribeToUpdates([ conditionId ]) return () => { unsubscribeToUpdates([ conditionId ]) } }, [ isSocketReady ]) useEffect(() => { const unsubscribe = oddsWatcher.subscribe(`${conditionId}`, `${outcomeId}`, async (oddsData?: OddsChangedData) => { let odds: string | number | undefined = oddsData?.outcomes?.[String(outcomeId)]?.odds if (!odds) { const rawOdds = await publicClient!.readContract({ address: contracts.prematchCore.address, abi: contracts.prematchCore.abi, functionName: 'calcOdds', args: [ BigInt(conditionId), BigInt(1), BigInt(outcomeId), ], }) odds = formatUnits(rawOdds, ODDS_DECIMALS) } else { setOddsFetching(false) } setOdds(+odds) }) return () => { unsubscribe() } }, [ publicClient ]) useEffect(() => { const unsubscribe = conditionStatusWatcher.subscribe(`${conditionId}`, (newStatus: ConditionStatus) => { setStatusFetching(false) setStatus(newStatus) }) return () => { unsubscribe() } }, []) /* ... */ /* See full code https://github.com/Azuro-protocol/sdk/blob/v3.1.0/src/hooks/useSelection.ts */
Last updated on