Skip to Content

useBets

The useBets hook is used to fetch betting history of a specific bettor.

⚠️

If you need to get older bets from v2 Azuro Protocol use useLegacyBets

ℹ️

Hook represents a logic wrapper over TanStack Query’s useInfiniteQuery hook. Explore TanStack Query docs  to understand what data the hook returns.

Usage

import { useBets } from '@azuro-org/sdk' const { data, hasNextPage, isFetching, fetchNextPage } = useBets(props) const { pages } = data || {} // render pages <> { pages?.map(({ bets, nextPage }) => { return ( <React.Fragment key={`${nextPage}`}> { bets.map(bet => ( <BetComponent key={`${bet.createdAt}-${bet.tokenId}`} bet={bet} /> )) } </React.Fragment> ) }) } <>

Props

{ filter: BetsFilter chainId?: ChainId itemsPerPage?: number query?: InfiniteQueryParameters<QueryResult> }
⚠️

useBets does not accept orderBy / orderDir — those are useLegacyBets-only props, kept there because the legacy v2 subgraph is queried directly. useBets always orders by creation time descending.

type BetsFilter = { bettor: Address // bettor address affiliate?: Address // affiliate address status?: BetStatusFilter // lifecycle preset - narrows both the bet list and its report kind?: BetKind // single (Ordinar) vs combo (Express) createdFrom?: number // inclusive lower bound, unix seconds (matches `Bet.createdAt`) createdTo?: number // inclusive upper bound, unix seconds isFreebet?: boolean // `true` = freebet-funded only, `false` = own-funds only, omit = both /** @deprecated renamed to `status` - when both are set, `status` wins */ type?: BetStatusFilter } enum BetStatusFilter { Unredeemed = 'unredeemed', // ready to redeem bets Pending = 'pending', // not yet accepted on-chain Accepted = 'accepted', // accepted, not yet resolved Settled = 'settled', // resolved bets CashedOut = 'cashedOut', // cashed out bets } enum BetKind { Single = 'single', Combo = 'combo', } type ChainId = | 100 // Gnosis | 137 // Polygon | 80002 // Polygon Amoy | 88888 // Chiliz | 88882 // Chiliz Spicy | 8453 // Base | 84532 // Base Sepolia type QueryResult = { bets: Bet[], nextPage: number | undefined, } import { type Address } from 'viem'
ℹ️

BetTypeBetStatusFilter

The enum previously used for filter.type has been renamed to BetStatusFilter (these are lifecycle statuses, not bet types — for single/combo use the new filter.kind with BetKind). filter.type is now deprecated in favour of filter.status; when both are set, status wins. BetType is kept as a working alias of the very same enum object — BetType.Accepted === BetStatusFilter.Accepted — so it type-checks and behaves identically. No migration is required of existing code that imports BetType or sets filter.type.

⚠️

BetStatusFilter.Pending has no representation in the subgraph this hook queries — orders that aren’t yet confirmed on-chain simply aren’t in that data set. Passing status: BetStatusFilter.Pending (or the deprecated type: BetType.Pending) is therefore intentionally unhandled: it adds no status constraint at all, rather than narrowing the result down to pending bets.

Return Value

UseInfiniteQueryResult<QueryResult>
import { type UseInfiniteQueryResult } from '@tanstack/react-query' type Selection = { conditionId: string outcomeId: string } type BetOutcome = { selectionName: string odds: number marketName: string game: GameData // game on which the bet is placed isLive: boolean isWin: boolean | null // true = won, false = settled but not won, null = still pending isLose: boolean | null // true = lost, false = settled but not lost, null = still pending isCanceled: boolean // true = voided, stake refunded for this leg } & Selection type Bet = { affiliate: string // affiliate address tokenId: string // id of the bet's NFT freebetId?: string | null // id of the freebet's NFT freebetContractAddress?: Address // freebet contract address totalOdds: number // total odds of the bet - voided legs are excluded from the product coreAddress: Address // core contract address lpAddress: Address // lp contract address outcomes: BetOutcome[] // bet's outcomes list txHash: string // bet's transaction hash status: BetStatus // subgraph bet status amount: string // bet's amount in USDT possibleWin: number // possible win amount in USDT - excludes voided legs payout: number | null // claimable amount - `null` once the bet is redeemed or cashed out; gates a redeem action settledPayout: number | null // what the bet actually returned - stays populated after redemption; use for historical/aggregate views cashout: string | null // cashout amount in USDT createdAt: number // created date isWin: boolean // flag indicates the bet's win isLose: boolean // flag indicates the bet's lose isRedeemable: boolean // flag indicates the possibility of redeeming the bet isRedeemed: boolean // flag indicates whether the bet has been redeemed isCanceled: boolean // flag indicates whether the bet has been canceled isLive: boolean // flag indicates whether the bet is live isCashedOut: boolean // flag indicates whether the bet is cashed out }
⚠️

A voided leg is isCanceled, not “pending”.

Settlement is per-outcome: within one condition, one outcome can win, another lose and a third be voided (refunded). A voided leg of a bet now reports { isWin: false, isLose: false, isCanceled: true }. It used to report { isWin: null, isLose: null, isCanceled: false } — indistinguishable from a leg that hadn’t settled yet.

Check isCanceled before treating isWin === null as “pending”:

if (outcome.isCanceled) { return <Refunded /> } if (outcome.isWin === null) { return <Pending /> } return outcome.isWin ? <Won /> : <Lost />

Won, lost, voided and pending are mutually exclusive: a settled leg never reports null, and a pending leg reports isWin: null / isLose: null with isCanceled: false.

ℹ️

Voided legs are excluded from combo odds. A refunded leg no longer multiplies into a combo’s totalOdds, so totalOdds and possibleWin for a combo containing a voided leg are lower — and correct — than they were before. A combo whose every leg was voided has totalOdds of 1: the stake is simply returned.

⚠️

Combo odds are re-priced, so their values change. 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 — which is what calcComboOdds does. The subgraph records the plain product instead, compounding the fee once per leg, so totalOdds, possibleWin, payout and settledPayout for an unredeemed combo now report higher figures than before, by more the more legs the bet has. They are the correct ones.

This applies to every unredeemed combo, not only one with a voided leg.

Two shapes are deliberately left as they were: a combo placed before the fee existed (its leg odds are raw, so the plain product is already right), and a bet that has been redeemed (its recorded payout is the amount actually paid on chain). A cashed-out bet is never re-priced either — it was paid at the price the bettor took, so read cashout for what it returned.

ℹ️

payout vs settledPayout

payout is gated on redeemability — it answers “is there money to claim?” and becomes null once the bet is redeemed. settledPayout answers “what did this bet return?” and stays populated after redemption. Use settledPayout for historical and aggregate views; use payout only to gate a redeem action.

Both are read from the protocol’s recorded payout, with one exception: a winning combo that has not been redeemed yet. Its recorded payout compounds the feed’s fee once per leg, and still credits any voided leg as if it had won; both figures are rebuilt from the surviving legs instead, at the same totalOdds this hook already reports. Once redeemed, the recorded payout is the amount actually paid and is used as is.