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 | 97 // BSC Testnet | 56 // BSC type QueryResult = { bets: Bet[], nextPage: number | undefined, } import { type Address } from 'viem'
ℹ️

BetType → BetStatusFilter

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' import { type Address, type Hex } from 'viem' import { type BetOrderState, type GraphBetStatus } from '@azuro-org/toolkit' 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 = { orderId: string // bettorAddressLowerCase_nonce actor: Address // bettor address affiliate: Address // affiliate address tokenId: string // id of the bet's NFT freebetId: string | null // id of the freebet, `null` for a bet funded by the bettor isFreebetAmountReturnable: boolean | null // decides a freebet's share of a win (see below); null counts as returnable paymaster: Address | null // freebet contract address, `null` for a bet funded by the bettor totalOdds: number // total odds as the subgraph records them (up to 12 decimals) - settled odds leave a voided leg out, a canceled bet has 1 coreAddress: Address // core contract address lpAddress: Address // lp contract address outcomes: BetOutcome[] // bet's outcomes list txHash: Hex | null // bet's transaction hash redeemedTxHash: Hex | null // redeem transaction hash orderState: BetOrderState // order state, derived from the subgraph status status: GraphBetStatus | null // subgraph bet status rejectedErrorCode: string | null // contract error code of a rejected order amount: string // bet's amount in the bet token possibleWin: number // potential payout as recorded - for a freebet, the bettor's share; a lost bet keeps the missed win payout: number | null // claimable amount - `null` unless the bet won or was canceled, is redeemable and not cashed out; for a freebet, the bettor's share; gates a redeem action settledPayout: number | null // payout as recorded once the bet is settled (0 if lost), the amount actually paid once redeemed; `null` before settlement; for a freebet, the bettor's share createdAt: number // created date, unix seconds resolvedAt: number | null // resolved date, unix seconds redeemedAt?: number | null // redeemed date, unix seconds cashout?: string // cashout amount in the bet token, set only on a cashed-out bet 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 isRejected: boolean // flag indicates whether the order was rejected 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.

A leg is voided exactly when the subgraph records its selection result as Canceled, even when its outcome settles won or lost (a leg rejected from a combo).

ℹ️

Figures are read as the bets subgraph records them. totalOdds, possibleWin, payout and settledPayout come straight from the subgraph, already priced by the protocol’s rule; nothing is re-priced on the client. totalOdds carries the subgraph’s precision (up to 12 decimals), so format it for display.

StatetotalOddspossibleWinpayoutsettledPayout
pendingthe placed oddsthe potential payoutnullnull
wonthe settled oddsthe potential payoutthe payout while redeemablethe payout
lostthe placed oddsthe potential payout - the win the bettor missednull0
canceled1the stake (0 for a freebet)the stake (0 for a freebet) while redeemablethe stake (0 for a freebet)
cashed outthe settled odds, else the placed oddsthe potential payoutnullthe recorded payout once settled

For a freebet, every money figure is the bettor’s share (see below). Settled odds leave a voided leg out. A redeemed bet’s settledPayout is the amount actually paid. For a cashed-out bet read cashout for what it paid: its settledPayout is the recorded payout, not the cash-out amount.

These figures and the freebet rule below describe bets from useBets. Bets from useLegacyBets keep the v2 figures.

⚠️

A freebet’s money figures are the bettor’s share. The liquidity pool pays a freebet’s whole payout to the freebet contract, which splits it between the bettor and the freebet fund. possibleWin, payout and settledPayout of a freebet are what the bettor receives:

  • payout no greater than the stake (a lost freebet, a canceled one): 0;
  • the freebet’s amount is returnable: payout minus the stake;
  • isFreebetAmountReturnable is false: the whole payout.

A freebet with no flag (null) counts as returnable. For example, a returnable freebet of 1.00 won at 1.50 has possibleWin, payout and settledPayout of 0.50; a non-returnable one has 1.50; a canceled freebet has 0. This is the same rule the toolkit exports as calcFreebetBettorShare. The gross payout of the pool is not on Bet. Real-money bets are unchanged.

Changed in SDK v8.2.0: a freebet’s payout and settledPayout used to be the pool’s whole payout (the type is unchanged).

ℹ️

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 the payout the subgraph recorded: 0 for a lost bet, the stake for a canceled one, and once redeemed the amount actually paid. payout also needs the bet not to be cashed out. For a freebet both are the bettor’s share, and a won freebet whose share is 0 has payout 0, not null.

A redeem through useRedeemBet sets the bet’s payout to null in the cached list as soon as the transaction is confirmed, along with isRedeemed and isRedeemable, without waiting for the next read.