Adding Live. Step 2: Live Data Retrieval
Here, we'll explain how to display live games and their markets. You can find more undercover details in the related documentation: Live Data Retrieval.
The data structure is nearly identical to the one used in the main Subgraph for prematch core contracts.
Key differences in the entities structure comparing to prematch subgraphs:
- Removed all entities and events related to bets (bets, freebets, expresses) and contracts (cores, liquidity pools).
- Removed
selection
entity and its relations. - Entity
condition
doesn't have anisExpressForbidden
field. - Event
GameShifted
changed toGameUpdated
(triggers by changing game status and/or start time). - Event
ConditionShifted
completely removed.
Load live games
If you've utilized fields excluded from the Live subgraph, we recommend splitting data fetching into games
and conditions
.
This allows you to reuse game/sport queries for both Prematch and Live requests.
Here's an example of a universal hook to retrieve events from both Prematch and Live feeds:
import { universalGamesQuery } from './query'
export const useGames = (props) => {
const {
startsAt,
isLive,
...yourRestVariablesLikeSportSlug,
} = props
const { prematchClient, liveClient } = useApolloClients()
const client = isLive ? liveClient! : prematchClient!
const variables = {
...yourRestVariablesLikeSportSlug,
}
if (isLive) {
// LIVE: _lt suffix
variables.where.startsAt_lt = startsAt
}
else {
// PREMATCH: _gt suffix + LP filter
variables.where.startsAt_gt = startsAt
variables.where.liquidityPool = _lp_contract_address.toLowerCase()
}
return useQuery(universalGamesQuery, {
variables,
client,
})
}
Apply this condition tweak to every fetching event data query.
Check out the SDK implementation of event fetching hooks for both Prematch and Live feeds:
- Sports navigation: https://github.com/Azuro-protocol/sdk/blob/v3.1.0/src/hooks/useSportsNavigation.ts (opens in a new tab)
- Events: https://github.com/Azuro-protocol/sdk/blob/v3.1.0/src/hooks/useSports.ts (opens in a new tab)
- Games: https://github.com/Azuro-protocol/sdk/blob/v3.1.0/src/hooks/useGames.ts (opens in a new tab)
- Game: https://github.com/Azuro-protocol/sdk/blob/v3.1.0/src/hooks/useGame.ts (opens in a new tab)
Load markets
Because of the difference between Live and Prematch condition
entities,
it's not possible to reuse the Prematch query. You'll need to create a new one.
Take a look at the source code of the SDK's useGameMarkets (opens in a new tab) hook. It utilizes useConditions (opens in a new tab) hook to fetch conditions from the Live or Prematch feed depending on a game status, and then combines them in markets. To streamline the handling of both Prematch and Live conditions in the SDK, we're modifying these entities to have the same fields.
Let's examine the key changes in the SDK hooks for fetching prematch and live conditions:
See full code: https://github.com/Azuro-protocol/sdk/blob/v3.1.0/src/hooks/useGameMarkets.ts (opens in a new tab)
/* ... */
const groupMarkets = (conditions: ConditionsQuery['conditions'], gameId: string, lpAddress: Address): GameMarkets => {
const outcomesByMarkets: OutcomesByMarkets = {}
const result: OutcomeRowsByMarket = {}
const sportId = conditions[0]!.game.sport.sportId
conditions.forEach((condition) => {
const { conditionId, outcomes: rawOutcomes, status } = condition
const coreAddress = (condition as PrematchConditionsQuery['conditions'][0]).core?.address || liveHostAddress
const isExpressForbidden = (condition as PrematchConditionsQuery['conditions'][0]).isExpressForbidden ?? true
rawOutcomes.forEach((rawOutcome) => {
const { outcomeId } = rawOutcome
const odds = (rawOutcome as PrematchConditionsQuery['conditions'][0]['outcomes'][0]).odds
const betTypeOdd = dictionaries.outcomes[outcomeId]
if (!betTypeOdd) {
console.warn(`betTypeOdd not found for "outcomeId: ${outcomeId}"`)
return
}
const marketKey = getMarketKey(outcomeId)
const marketName = getMarketName({ outcomeId })
const marketDescription = getMarketDescription({ outcomeId })
const selectionName = getSelectionName({ outcomeId, withPoint: true })
const outcome: MarketOutcome = {
coreAddress: coreAddress,
lpAddress: lpAddress,
conditionId,
outcomeId,
selectionName,
status,
gameId,
isExpressForbidden,
}
if (odds) {
outcome.odds = +odds
}
/* ... */
})
})
/* ... */
}
export const useGameMarkets = (props: Props) => {
const { gameId, gameStatus, filter } = props
const { contracts } = useChain()
const { loading, conditions, error } = useConditions({
gameId,
filter,
isLive: gameStatus === GameStatus.Live,
livePollInterval: 2000,
})
/* ... */
}
/* see full code: https://github.com/Azuro-protocol/sdk/blob/v3.1.0/src/hooks/useGameMarkets.ts */
Check out the SDK's implementation of the game markets fetching hook for both Prematch and Live feeds:
- useGameMarkets: https://github.com/Azuro-protocol/sdk/blob/v3.1.0/src/hooks/useGameMarkets.ts (opens in a new tab)
- useConditions (used inside useGameMarkets): https://github.com/Azuro-protocol/sdk/blob/v3.1.0/src/hooks/useConditions.ts (opens in a new tab)