Migration Guide: SDK v8.0.0
This guide will help you migrate your application from SDK v7.x to v8.0.0.
Overview
SDK v8.0.0 depends on @azuro-org/toolkit v7.0.0 and carries its model change through the hooks: the
protocol resolves outcomes, not conditions. Within one condition, outcomes can independently be Won,
Lost, Canceled (voided) or still live — and the SDK now reports them that way.
- Removed:
useResolvedMarkets,BetOutcome.wonOutcomeIds,UseConditionsProps.onlyActiveOrStopped - Added:
includeHiddenonuseActiveConditionsanduseActiveMarkets, plus their own result typesUseActiveConditionsResult/UseActiveMarketsResult; the value types of the watched state maps are now exported too —ConditionsStateData,OutcomesStateData,OutcomeStateDataandConditionOutcomeData - Changed shape:
useActiveConditionsanduseActiveMarketsare no longer plainUseQueryResults and require the feed providers;useActiveConditionsno longer acceptsquery.select;OutcomesStateData.statesMapholds a different value type - Changed without a type error: which hooks filter
hiddenrows, when a hidden market is revealed, how far per-outcome state from the socket is trusted, voided combo legs, condition/outcome state fallbacks, and the key of the mapuseBetsSummaryBySelectionreturns
Read the “Behaviour changes with no compile error” section — it is the one that will bite you.
Several of these changes type-check perfectly and silently alter what your UI renders: the “active”
hooks drop hidden conditions and outcomes by default while useConditions keeps them, a hidden market
is now revealed only by an update that says so, per-outcome state is no longer read from every socket
message, a voided combo leg reports isWin: false instead of isWin: null, and
useBetsSummaryBySelection is keyed differently. A green tsc does not mean you are done.
Start with the Toolkit v7 Migration Guide — it explains the underlying
model (ConditionState reduced to Active | Stopped, MarketOutcome.isWon removed) that everything
below builds on.
Breaking Changes
1. useResolvedMarkets removed
The hook is deleted with no stub. It existed to answer “what were this game’s results?” by fetching the
conditions that had reached a Resolved state — a state that no longer exists.
Its replacement is the ordinary markets hook with includeHidden: true: once a game is finished, you want
everything the game offered, including the markets and outcomes that were hidden while it ran. Each
outcome then carries its own result in state.
Before (v7.x):
import { useResolvedMarkets } from '@azuro-org/sdk'
const { data: markets } = useResolvedMarkets({ gameId })After (v8.0.0):
import { useActiveMarkets } from '@azuro-org/sdk'
const { data: markets } = useActiveMarkets({ gameId, includeHidden: true })If you need the raw conditions rather than grouped markets:
import { useActiveConditions } from '@azuro-org/sdk'
const { data: conditions } = useActiveConditions({ gameId, includeHidden: true })includeHidden: true is what makes this the results view: it keeps the markets and outcomes that were
hidden while the game ran, which is where the settled and refunded outcomes are.
There is no longer a separate “active markets” view and “resolved markets” view to switch between. One grid serves both — see The recommended integration pattern below.
2. BetOutcome.wonOutcomeIds removed
useBets no longer returns wonOutcomeIds on a bet’s outcomes. It was a condition-level field used to
infer whether the bet’s leg won — which is exactly the inference that mispriced voided legs.
Before (v7.x):
type BetOutcome = {
selectionName: string
odds: number
marketName: string
game: GameData
wonOutcomeIds: string[] | null // removed
isLive: boolean
isWin: boolean | null
isLose: boolean | null
isCanceled: boolean
} & SelectionAfter (v8.0.0):
type BetOutcome = {
selectionName: string
odds: number
marketName: string
game: GameData
isLive: boolean
isWin: boolean | null
isLose: boolean | null
isCanceled: boolean
} & SelectionRead isWin / isLose / isCanceled — the SDK already derives them from the per-outcome result.
3. UseConditionsProps.onlyActiveOrStopped removed
The prop filtered conditions down to those whose state was Active or Stopped. Since ConditionState
is now exactly { Active, Stopped }, that predicate matches every condition — it had become a no-op.
Before (v7.x):
const { data: conditions } = useConditions({
gameId,
onlyActiveOrStopped: true,
})After (v8.0.0):
const { data: conditions } = useConditions({ gameId })Just delete the prop. If what you actually wanted was “the markets a bettor can act on right now”, that
is the default behaviour of useActiveConditions /
useActiveMarkets with includeHidden left off.
4. useActiveConditions / useActiveMarkets: new result type, feed providers required, no select
These two hooks now decide visibility themselves, on the live value from the feed, after subscribing to every condition of the game. Three consequences, two of which the compiler will point at.
They are no longer plain UseQueryResults. data is produced after the query, so it is typed
separately from the query’s own data:
type UseActiveConditionsResult = {
data: ConditionDetailedData[] | undefined
} & Omit<UseQueryResult<ConditionDetailedData[]>, 'data'>
type UseActiveMarketsResult = {
data: GameMarkets | undefined
} & Omit<UseQueryResult<ConditionDetailedData[]>, 'data'>isLoading, isFetching, isPlaceholderData, status, error and refetch are unchanged, and your
query options are still forwarded. Only annotations naming the old type break.
useActiveConditions no longer supports query.select, and UseActiveConditionsProps is no longer
generic. A select runs inside the query — before the visibility filter — so it would see exactly the
hidden rows the hook exists to remove, and its output would then be filtered as if it were still a
ConditionDetailedData[]. (useActiveMarkets never accepted a select: its query was already
QueryParameter<ConditionDetailedData[]> in v7, and QueryParameter omits select. Nothing changes
there.)
// Before (v7.x)
const { data } = useActiveConditions({
gameId,
query: { select: (conditions) => conditions.filter(myPredicate) },
})
// After (v8.0.0) - shape the raw data yourself
const { data: conditions } = useConditions({
gameId,
query: { select: (conditions) => conditions.filter(myPredicate) },
})They require FeedSocketProvider and ConditionUpdatesProvider. Both are already inside
AzuroSDKProvider, so nothing to do unless you compose the providers by
hand — but if you do and one is missing, this fails at runtime, not at compile time. Check your
provider tree before shipping.
5. OutcomesStateData.statesMap holds OutcomeStateData, not OutcomeUpdateData
useOutcomesState used to keep the raw socket message for each outcome. It now keeps its own view of the
outcome, and that view has its own type.
Before (v7.x):
type OutcomesStateData = {
states: Record<string, OutcomeState>
statesMap: Record<string, OutcomeUpdateData>
}After (v8.0.0):
import { type OutcomeStateData } from '@azuro-org/sdk'
type OutcomesStateData = {
states: Record<string, OutcomeState>
statesMap: Record<string, OutcomeStateData>
}
type OutcomeStateData = {
odds: number
turnover: string
/** `undefined` until an update that can be trusted for it, or a state read, has reported it */
state?: OutcomeState
/** `undefined` until the feed has reported it */
hidden?: boolean
}The entry lost conditionState, and its state and hidden became optional. conditionState says how
far the message it arrived on can be trusted — the hook applies that itself rather than handing it on,
which is behaviour change 4 below — and neither state nor hidden is known until something
authoritative has reported it. The wire message keeps the name OutcomeUpdateData and keeps
conditionState, so an annotation that meant the socket message is still correct; one that meant a map
entry has to move to OutcomeStateData.
OutcomesStateData is the hook’s internal state shape, not its return value: useOutcomesState returns
{ data, outcomesMap, isFetching }, where data is that states map and outcomesMap is that
statesMap. The same holds for ConditionsStateData and useConditionsState, which returns
{ data, conditionsMap, isFetching }.
Behaviour changes with no compile error
Everything in this section compiles unchanged and behaves differently at runtime. Walk through each one against your own screens.
1. hidden conditions and outcomes are dropped by default — in the “active” hooks
useActiveConditions and
useActiveMarkets now drop conditions flagged hidden, and
hidden outcomes inside the conditions they keep. A condition left with no visible outcome is dropped
entirely.
Previously the SDK returned everything and apps filtered at render time. If your app did that filtering itself, it now filters an already-filtered list — harmless, though you can delete it. The breakage is in the other direction: a view that relied on getting everything back now silently renders less.
// running game - hidden markets are not on offer, so the default is what you want
const { data: markets } = useActiveMarkets({ gameId })
// finished game - you want everything the game had, including what was hidden while it ran
const { data: allMarkets } = useActiveMarkets({ gameId, includeHidden: true })2. useConditions is a pure data hook, and the conditions query key changed
useConditions filters nothing: it returns everything the feed
has for the game, hidden conditions and outcomes included. Visibility can’t be decided there — the feed
sends no updates for a condition that was never subscribed, so a row dropped in the fetch could never be
revealed afterwards, however alive it turned out to be. That decision moved into the two “active” hooks,
which subscribe first and filter second.
If you used useConditions to render a bettor-facing grid, move to
useActiveConditions or
useActiveMarkets:
// Before - a grid built on raw feed data
const { data: conditions } = useConditions({ gameId })
// After - the conditions the game is actually offering
const { data: conditions } = useActiveConditions({ gameId })The conditions query key changed — it lost onlyActiveOrStopped and is now
[ 'conditions', chainId, gameId, extended ]. Nothing about visibility is part of it, so one cache entry
serves every view of a game instead of one per flag combination. Cached entries written by v7 don’t match
the new key: expect a refetch on first load after the upgrade, and update any manual
queryClient.setQueryData / invalidateQueries / getQueryData call that hard-codes the old shape.
3. A hidden market is revealed by an update that says so, not by any update arriving
hidden on useConditionState /
useConditionsState used to clear to false as soon as
any socket message arrived for the condition. It is now taken from the condition’s own hidden flag,
which the feed sends on every message.
The reason is that an update arriving proves nothing: 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. Expect fewer markets in the grid than before — deliberately.
Two related shape changes:
hiddenis nowboolean | undefinedinconditionsMap, andisHiddenisboolean | undefinedonuseConditionState.undefinedmeans “the feed has not reported it yet” — not “visible”, and specifically not “already revealed”. Only an explicitfalsecloses the latch; ifundefinedcounted as revealed, the latch would close before the feed had said anything. Test!hidden, nothidden === false.- Visibility is latched one way, at both levels. Once revealed, a condition or outcome stays in the result and is never hidden again. A market that stops stays in the grid, locked — a grid that reflows while a bettor is reading it, moving the market under their cursor, is worse than one that keeps a market slightly longer than it had to.
4. Per-outcome state and hidden are only read from updates whose condition is Active
useOutcomeState /
useOutcomesState used to take state and hidden from
every socket message. They now ignore both unless the message’s condition is Active.
An update for an inactive condition reports every one of its outcomes as Stopped, whatever they had
actually settled to — so trusting it un-settles won, lost and voided outcomes each time their condition is
suspended. Such a message now schedules a re-read from the state endpoint, which is authoritative for
per-outcome state, instead of being applied. odds and turnover are real in every message and are still
taken from all of them.
The consequence to design for: when a condition stops, there is a brief window — one state-endpoint
round trip — in which its outcomes still read their previous state. Condition-level locking is
unaffected and still immediate, so gate the bet on the condition’s state as well as the outcome’s, and
don’t treat a per-outcome Stopped as instantaneous.
The socket message type OutcomeUpdateData carries the new conditionState field if you fold these
messages into your own state — apply the same rule.
5. Outcome hidden is latched by the SDK — drop your own latch
Both outcome watch hooks now latch hidden one way themselves, on the socket path and on the
state-endpoint path. If your app keeps its own one-way isHidden latch on top of them to stop outcomes
flickering in and out as a condition is suspended and re-priced, delete it. Re-hiding no longer happens, by
design.
6. A voided combo leg is now isCanceled, not “pending”
Before (v7.x) a voided leg came back as:
{ isWin: null, isLose: null, isCanceled: false }— indistinguishable from a leg that simply hasn’t settled yet.
After (v8.0.0):
{ isWin: false, isLose: false, isCanceled: true }Won, lost, voided and pending are now mutually exclusive: a settled leg never reports null, and a leg
that is still pending reports isWin: null / isLose: null with isCanceled: false.
Any UI that branches on isWin === null to mean “pending” must check isCanceled first.
// Before - a voided leg fell into the "pending" branch
if (outcome.isWin === null) {
return <Pending />
}
// After
if (outcome.isCanceled) {
return <Refunded />
}
if (outcome.isWin === null) {
return <Pending />
}
return outcome.isWin ? <Won /> : <Lost />7. Combo totalOdds, possibleWin and payout change for every unredeemed combo
Two separate corrections land on these four figures. Neither is an API change — nothing to update — but screenshots, snapshots and any figures you cache or reconcile against will move.
A voided leg no longer multiplies into the odds. It is refunded, so useBets excludes it. If you are
coming from v7.6 or later this already happened there; from earlier, combos containing a voided leg
now report lower, correct figures.
A combo is re-priced, voided leg or not. This is new in v8. The feed applies its fee to every outcome’s odds, and a combo is priced by removing that fee per leg and applying it once to the product. The subgraph records the plain product instead, compounding the fee once per leg — so for an unredeemed combo the four figures now report higher, correct values, by more the more legs the bet has. See Combo pricing.
Three shapes are deliberately unchanged: a redeemed bet (its recorded payout is what was actually
paid), a combo placed before MARGIN_APPLIED_AT (its leg odds are raw, so the plain product is already
right), and a cashed-out bet (paid at the price the bettor took — read cashout). Singles are
unaffected either way.
If you reconstruct any of these yourself, use
calcComboOdds and pass the bet’s real createdAt — the same
legs price differently either side of the fee’s start date.
A combo whose every leg was voided has odds of 1: the stake is simply returned. The same holds for any
bet the protocol canceled outright, single or combo — totalOdds is 1 for it, and possibleWin is the
stake. Before, a canceled single kept the odds it was placed at.
8. useConditionState / useConditionsState fall back to Stopped
When a condition is absent from the feed, these hooks used to report the removed ConditionState.Removed.
They now report ConditionState.Stopped.
// Before
const isMissing = state === ConditionState.Removed
// After - "not in the feed" and "temporarily not taking bets" are the same state now
const isNotBettable = state === ConditionState.StoppedIf you rendered Removed conditions differently from Stopped ones — hiding the first, greying out the
second — use isHidden from the hook (fed by condition.hidden) to make that distinction instead.
9. useOutcomeState / useOutcomesState fall back to Stopped
Same change one level down: an outcome absent from the feed used to read as OutcomeState.Canceled and
now reads as OutcomeState.Stopped.
OutcomeState.Canceled now strictly means voided — with money attached.
If you treated Canceled as “this outcome isn’t in the feed” (a rendering concern), you must stop: it
now means the protocol voided the outcome and refunded bets on it. Showing “Refunded” for an outcome that
is merely missing, or hiding an outcome that was actually voided, are both wrong.
// Before - Canceled was overloaded
if (state === OutcomeState.Canceled) {
return null // "not in feed, don't render"
}
// After
if (state === OutcomeState.Canceled) {
return <Refunded /> // voided, stake returned
}
if (state === OutcomeState.Stopped) {
return <Disabled /> // not offered right now, or not in the feed
}10. useActiveMarket skips fully settled markets
useActiveMarket — the watch hook that picks which market tab to show and moves off it when it goes
inactive — no longer selects a market whose condition is Active but all of whose outcomes are settled.
Such a market has nothing left to bet on, so the hook advances to the next one.
If you relied on the previously-selected tab staying put after a market finished, pin the selection yourself rather than reading it from the hook.
11. The single-item watch hooks re-seed when pointed elsewhere
useConditionState and
useOutcomeState now re-seed from their props when
conditionId / outcomeId change, instead of keeping what they held for the item that has gone. Reusing
one component instance across conditions or outcomes is therefore safe.
It matters most for isHidden: visibility is latched, so a reveal the previous item had earned used to
carry over to the new one permanently. If your app worked around that — a key to force a remount, or a
reset of your own — you can drop it.
12. useBetsSummaryBySelection is keyed by condition and outcome
The map useBetsSummaryBySelection returns was keyed
by outcomeId alone. It is now keyed by `${conditionId}-${outcomeId}`.
An outcome is identified by its condition and its outcomeId — that pair is what the protocol keys an
outcome on. On its own an outcomeId is not unique across a game, for two independent reasons:
v5markets number their outcomes per condition, from1up. Everyv5condition therefore carries the same low ids, so outcome1of one condition and outcome1of another are unrelated selections — and both collide with the outcome1alegacymarket takes from the shared dictionaries namespace.legacymarkets draw their ids from that dictionary, so an id there always denotes the same selection. But a market that is suspended and re-offered comes back as a second condition carrying the same outcomes, so one game still shows the id twice.
Keyed by outcomeId alone, every one of these shared a single entry: their profit and loss were summed
together and each of them read the total back — the wrong figure on all of them, on the results view of a
finished game.
Before (v7.x):
<Outcome summary={betsSummary?.[outcome.outcomeId]} />After (v8.0.0):
<Outcome summary={betsSummary?.[`${outcome.conditionId}-${outcome.outcomeId}`]} />This does not fail to compile. The map is Record<string, string> before and after, so the old
lookup type-checks, misses, and yields undefined — the summary just stops rendering. Grep for every
read of this hook’s result rather than waiting for tsc to find them.
This is the same key useOutcomesState and
useOdds already use, so one helper can address all three maps:
import { type MarketOutcome } from '@azuro-org/toolkit'
export const getOutcomeKey = ({ conditionId, outcomeId }: Pick<MarketOutcome, 'conditionId' | 'outcomeId'>) => (
`${conditionId}-${outcomeId}`
)New: includeHidden
// UseActiveConditionsProps
{
gameId: string | string[]
includeHidden?: boolean // default: false
extended?: boolean
chainId?: ChainId
query?: QueryParameter<UseConditionsQueryFnData> // no `select`
}Available on useActiveConditions and
useActiveMarkets — the hooks that decide visibility.
Defaults to false, i.e. hidden conditions and outcomes are dropped.
useConditions has no such prop: it always returns everything.
The rule to apply is simple and it is the only thing in the markets grid that should depend on game state:
While a game is active,
hiddenconditions and outcomes stay hidden. Once the game is finished, they are shown.
import { useActiveMarkets, useGameState } from '@azuro-org/sdk'
import { GameState } from '@azuro-org/toolkit'
const { data: gameState } = useGameState({ gameId, initialState: game.state })
const { data: markets } = useActiveMarkets({
gameId,
includeHidden: gameState === GameState.Finished,
})The recommended integration pattern
Do not gate the whole market grid on game state. There is no longer an “is this game over?” switch that flips the page between a betting view and a results view — because outcomes settle independently, a game can have finished markets and live markets on screen at the same time.
Render one grid, in which each outcome shows its own state:
import { useActiveMarkets, useGameState } from '@azuro-org/sdk'
import { GameState, isOutcomeSettled, OutcomeState, type MarketOutcome } from '@azuro-org/toolkit'
const Markets: React.FC<{ gameId: string, initialGameState: GameState }> = (props) => {
const { gameId, initialGameState } = props
const { data: gameState } = useGameState({ gameId, initialState: initialGameState })
// the one thing that depends on game state
const { data: markets } = useActiveMarkets({
gameId,
includeHidden: gameState === GameState.Finished,
})
return (
<>
{
markets?.map(market => (
market.conditions.map(condition => (
condition.outcomes.map(outcome => (
<Outcome key={`${outcome.conditionId}-${outcome.outcomeId}`} outcome={outcome} />
))
))
))
}
</>
)
}
const Outcome: React.FC<{ outcome: MarketOutcome }> = ({ outcome }) => {
if (!isOutcomeSettled(outcome.state)) {
// still bettable - disabled while Stopped
return (
<button disabled={outcome.state === OutcomeState.Stopped}>
{outcome.selectionName} {outcome.odds}
</button>
)
}
if (outcome.state === OutcomeState.Won) {
return <div>{outcome.selectionName} — Won</div>
}
if (outcome.state === OutcomeState.Canceled) {
return <div>{outcome.selectionName} — Refunded</div>
}
return <div>{outcome.selectionName} — Lost</div>
}Use useOutcomeState or
useOutcomesState to keep each outcome’s state live over
the socket, so an outcome flips to Won / Lost / Refunded in place while the rest of the grid keeps taking
bets.
Migration Steps
Step 1: Update dependencies
npm install @azuro-org/sdk@^8 @azuro-org/toolkit@^7
# or
yarn add @azuro-org/sdk@^8 @azuro-org/toolkit@^7
# or
pnpm add @azuro-org/sdk@^8 @azuro-org/toolkit@^7Step 2: Grep your call sites
Everything above the divider produces a compile error. The rest are silent, so search for them:
# --- these fail to compile ---
# removed hook and its types
grep -rn "useResolvedMarkets\|UseResolvedMarketsProps\|UseResolvedMarkets\b" src/
# removed prop - now a no-op, just delete it
grep -rn "onlyActiveOrStopped" src/
# removed field on BetOutcome, and removed enum members
grep -rn "wonOutcomeIds\|ConditionState.Removed\|ConditionState.Resolved\|ConditionState.Canceled" src/
# a `select` passed to useActiveConditions, and annotations naming the old result type
grep -rn "select:" src/
grep -rn "UseQueryResult" src/
# --- these compile fine and change behaviour ---
# "pending" branches that a voided leg now falls out of
grep -rn "isWin === null\|isLose === null\|isWin == null" src/
# Canceled used as "missing from the feed"
grep -rn "OutcomeState.Canceled" src/
# every call that may need includeHidden: true, and every grid still built on raw feed data
grep -rn "useConditions(\|useActiveConditions(\|useActiveMarkets(" src/
# your own visibility filters and latches - the SDK owns these now
grep -rn "isHidden\|conditionsMap\|outcomesMap\|\.hidden" src/
# hard-coded TanStack Query keys for conditions - the shape changed
grep -rn "'conditions'" src/
# a hand-composed provider tree that may be missing the feed providers
grep -rn "ConditionUpdatesProvider\|FeedSocketProvider" src/
# condition-level result derivation, removed in toolkit v7
grep -rn "isWon" src/
# every read of the useBetsSummaryBySelection map - its key gained the conditionId
grep -rn "useBetsSummaryBySelection" src/Step 3: Fix the useResolvedMarkets call sites
Replace each with useActiveMarkets({ gameId, includeHidden: true }), then delete the “resolved markets”
view: fold it into the single grid described above.
Step 4: Audit every useConditions / useActiveConditions / useActiveMarkets call
First, pick the right hook. A bettor-facing grid belongs on useActiveConditions / useActiveMarkets;
useConditions is for raw feed data, a custom select, prefetching, or a view that deliberately wants the
hidden rows.
Then, for each “active” call, decide what the screen should show:
- a running game → leave
includeHiddenoff (the new default) - a finished game, a results view, or anything that must reflect everything the game offered →
pass
includeHidden: true - unsure? Drive it off game state:
includeHidden: gameState === GameState.Finished
Finally, delete the visibility filtering you were doing at render time — the hook has already done it, and
on a better value: yours reads the hidden the fetch reported, the hook’s reads the live one. A row can
legitimately come back with hidden: true on it after the feed has revealed it, so re-filtering will hide
markets that are on offer.
Step 5: Fix the pending / voided branches
Search results from isWin === null are the dangerous ones. In every such branch, add an isCanceled
check before the null check.
Step 6: Re-check anything that reconciles combo payouts
totalOdds and possibleWin returned different values for combos with a voided leg from v7.6 on. If you compare
those against your own backend figures, snapshot tests, or cached values, refresh them.
Step 7: Re-key every read of useBetsSummaryBySelection
Trace the map this hook returns down through your component tree — it is usually passed as a prop several
levels before anything indexes it — and replace map[outcomeId] with
map[`${conditionId}-${outcomeId}`]. Nothing here fails to compile, and a missed site renders no
summary at all rather than a wrong one, so the grep is the only thing that will find them.
Step 8: Test
- A live game’s market grid — hidden markets should be absent
- A finished game — with
includeHidden: true, every market is back, each outcome labelled Won / Lost / Refunded - A game with mixed settlement — some markets settled while others still take bets, on one screen
- A market that stops while you watch it — it should stay in the grid, locked, and not disappear or reflow the list
- A market that was hidden on load and comes back on offer — it should appear once the feed says
hidden: false - A settled outcome whose condition keeps sending updates — it must stay Won / Lost / Refunded and not flip back to Stopped
- A combo bet with a voided leg — the leg reads “Refunded”, and
totalOdds/possibleWinexclude it - A pending bet — still reads as pending, not as refunded
- A component instance reused across outcomes or conditions — it must show the new item’s lock and visibility, never the previous one’s
- A finished game you have settled bets on — every bet’s profit or loss appears on the selection it was
placed on, and on no other. Two markets of the same game that share an
outcomeIdmust show their own figures, not each other’s sum
Migration Checklist
-
npm install @azuro-org/sdk@^8 @azuro-org/toolkit@^7 - Follow the Toolkit v7 Migration Guide first
- Replace
useResolvedMarketswithuseActiveMarkets({ includeHidden: true }) - Delete every
onlyActiveOrStoppedprop - Stop reading
BetOutcome.wonOutcomeIds - Move bettor-facing grids off
useConditionsontouseActiveConditions/useActiveMarkets - Add
includeHidden: trueto every finished-game / results view - Drop
query.selectfromuseActiveConditionscalls — useuseConditionsfor that - Replace annotations naming the old
UseQueryResultshape withUseActiveConditionsResult/UseActiveMarketsResult - Re-point annotations of an
outcomesMapentry fromOutcomeUpdateDatatoOutcomeStateData— the entry no longer carriesconditionState - Confirm
FeedSocketProvider+ConditionUpdatesProviderare in your provider tree (free withAzuroSDKProvider) — the active hooks fail at runtime without them - Update manual TanStack Query cache reads of the
conditionskey — its shape changed - Delete render-time visibility filtering on top of the active hooks, and any hand-rolled one-way
isHiddenlatch - Drop any
key-remount or manual reset that stoppeduseConditionState/useOutcomeStatecarrying state across items — they re-seed themselves now - Test
!hiddenrather thanhidden === false—undefinedmeans “not reported yet” - Stop reading per-outcome
statefrom your own socket handling of inactive conditions - Check
isCanceledbeforeisWin === nulleverywhere - Stop treating
OutcomeState.Canceledas “missing from feed” - Stop treating
ConditionState.Stoppedas identical to the oldRemovedfor hiding — useisHidden - Re-key every read of the
useBetsSummaryBySelectionmap to`${conditionId}-${outcomeId}` - Re-verify combo
totalOdds/possibleWinagainst your own figures - Collapse separate “active” and “resolved” market views into one per-outcome grid
Need Help?
- Check the SDK Documentation
- Read the Toolkit v7 Migration Guide
- Check the SDK GitHub repository for known issues