useActiveConditions
The useActiveConditions hook is a wrapper over useConditions that returns the conditions a game is actually offering right now.
useConditions returns everything the feed has, hidden rows included. useActiveConditions is where visibility is decided: it subscribes to every condition of the game, then drops the ones the feed is not offering.
Usage
import { useActiveConditions } from '@azuro-org/sdk'
const { data, isFetching, error } = useActiveConditions(props)This hook needs a live feed connection. It requires the FeedSocketProvider and
ConditionUpdatesProvider — both are already included in
AzuroSDKProvider, so there is nothing to do unless you compose the
providers by hand. If you do, and one of them is missing, the hook fails at runtime, not at compile
time:
import {
ChainProvider,
FeedSocketProvider,
ConditionUpdatesProvider,
} from '@azuro-org/sdk'
import { polygonAmoy } from 'viem/chains'
function Providers(props: { children: React.ReactNode }) {
const { children } = props
return (
<ChainProvider initialChainId={polygonAmoy.id}>
<FeedSocketProvider>
<ConditionUpdatesProvider>
{children}
</ConditionUpdatesProvider>
</FeedSocketProvider>
</ChainProvider>
)
}Props
{
gameId: string | string[] // single game ID or array of game IDs
includeHidden?: boolean // keep `hidden` conditions and outcomes in the result; default false
extended?: boolean // opt-in: include new conditions/markets not present in the dictionaries package
chainId?: ChainId
query?: QueryParameter<UseConditionsQueryFnData> // useQuery params, without `select`
}query.select is not supported here, and UseActiveConditionsProps is not generic. A select
runs inside the query, which is before the visibility filter — so it would see the hidden rows the
hook exists to remove, and its output would then be filtered as if it were still a
ConditionDetailedData[].
Every other useQuery option is forwarded as usual (refetchInterval, enabled, placeholderData, …).
If you need a select, call useConditions and shape the
data yourself.
gameId property is not the same as id. Each game fetched using useGames hook contains the gameId:
import { useGames } from '@azuro-org/sdk'
const { data } = useGames()
const gameId = data?.games[0]?.gameIdWhen to enable extended
Optional, defaults to false. When true, the API additionally returns new-generation conditions and outcomes alongside the standard set. Detect a new condition by its first character: conditionId[0] === '5'.
Titles are returned directly in the response. Each condition exposes title (the market name), and each outcome exposes its own title — ConditionDetailedData.title and OutcomeData.title. The toolkit and SDK already handle grouping, sorting, and rendering of new markets out of the box.
- If your app reads market/outcome metadata only from these hooks’ / utility’s response (no direct use of
@azuro-org/dictionaries), enabling the flag is safe — new markets will appear automatically. - If your app reads from
@azuro-org/dictionariesdirectly, note that new markets are not in the dictionaries package — their titles live only on the API. Use the title fields returned here.
If you only have a conditionId later (e.g. in a betslip, history, or activity feed) and need its market title, call getConditionsState — its ConditionStateData now exposes title for the condition and each outcome. The SDK’s useConditionsState wraps that endpoint.
For new bets, titles also are present in the subgraph.
hidden conditions and outcomes are dropped by default.
Three rules, all of them skipped when includeHidden: true:
- a condition currently flagged
hiddenis dropped; - inside a condition that is kept, outcomes flagged
hiddenare dropped; - a condition left with no visible outcome is dropped too — it has nothing left to offer.
The product rule to apply: while a game is running, hidden conditions and outcomes are not being offered, so they stay out of the grid; once the game is over, they are part of what the bettor should see — that is where the refunds and the settled markets are.
import { GameState } from '@azuro-org/toolkit'
const { data } = useActiveConditions({
gameId,
includeHidden: gameState === GameState.Finished,
})How visibility is decided
Understanding this matters if you build your own grid, or wonder why a market appeared a few seconds late.
- Visibility is read from the live feed, not from the fetch. The hook fetches every condition of the
game through
useConditions, subscribes to all of them viauseConditionsStateanduseOutcomesState, and only then filters. It has to be this way round: the feed sends no updates for a condition that was never subscribed, so a condition dropped before subscription could never be shown again, however alive it turned out to be. - A hidden condition is revealed by an update reporting
hidden: false— not by an update merely arriving. A market the provider has parked keeps streaming odds for the rest of its life, so “it sent something” is not evidence that it is being offered. - Visibility is latched one way. Once a condition or an outcome has been reported visible the filter
keeps it, locked if it is no longer taking bets, and never hides it again. A list that reflows while
a bettor is reading it — markets vanishing and returning as the provider suspends and re-prices them —
is worse than one that keeps a market slightly longer than it had to. The latch governs the filter, not
the query: a refetch that stops returning the condition drops the row itself. Use
useConditionState/useOutcomeStateto render that lock.
Settlement is per-outcome. ConditionState is only ever Active or Stopped — a condition carries
no result. Within a single condition, outcomes settle independently: Won, Lost, Canceled (voided,
stake refunded) or still Active. Read OutcomeData.state, or
isOutcomeSettled, for a result.
Return Value
The hook is no longer a plain UseQueryResult: data is produced after the query, so it is typed
separately from the query’s own data.
UseActiveConditionsResultimport { type UseQueryResult } from '@tanstack/react-query'
type UseActiveConditionsResult = {
data: ConditionDetailedData[] | undefined
} & Omit<UseQueryResult<ConditionDetailedData[]>, 'data'>Everything else behaves as it does on useQuery — isLoading, isFetching, isPlaceholderData,
status, error and refetch all come from the underlying query untouched.
type ConditionDetailedData = {
id: string
conditionId: string
state: ConditionState
title: string // market title
isExpressForbidden: boolean
isPrematchEnabled: boolean
isLiveEnabled: boolean
/** true for a condition the provider has taken off the grid; optional - the feed doesn't always report it */
hidden?: boolean
margin: string
outcomes: OutcomeData[]
category: ConditionCategory
game: {
gameId: string
sport: {
sportId: string
}
}
/** win-only, condition-level list. NOT the per-outcome source of truth - read `OutcomeData.state` */
wonOutcomeIds: string[]
sort: `${number}`
/** Modern ("5...") conditions only: used for market grouping */
marketId?: string | null
marketVarietyId?: string | null
}
type OutcomeData = {
title: string // outcome title
outcomeId: string
odds: string
sort: `${number}`
/** Modern ("5...") conditions only: numeric handicap/line value, e.g. "-2.5" / "+2.5" */
point?: string | null
hidden: boolean
state: OutcomeState
}
enum ConditionState {
Active = 'Active',
Stopped = 'Stopped',
}
enum OutcomeState {
Active = 'Active',
Canceled = 'Canceled',
Stopped = 'Stopped',
Won = 'Won',
Lost = 'Lost'
}
type ConditionCategory =
| 'correct_score'
| 'handicap'
| 'handicap_3_way'
| 'odd_even'
| 'participant_and_total'
| 'participant_and_yes_no'
| 'participant_slash_participant'
| 'players'
| 'result'
| 'result_or_neither'
| 'total'
| 'total_3_way'
| 'winner'
| 'yes_no'
| string // extensible — new categories may appear; null when unset
| nullhidden on the returned rows is the value the fetch reported. It is not the value the filter used —
that one is live, and latched. A row can therefore be present with hidden: true on it, meaning it was
hidden when fetched and has since been reported visible by the feed. Don’t re-filter on it.