Usage
Adapters mapping real Mr. Doge SDK responses onto mrdoge-ui component props.
Small, pure functions from a real @mrdoge/protocol response to a
component's plain props: type-checked, so a schema change fails to
compile instead of silently going stale. They live in
lib/mrdoge-adapters/, named for this specific integration, and are the
ones used throughout every example on this site. Integrating a different
data provider? Your own lib/<provider>-adapters/ directory, following
the same pattern, is the way. A new page here too, PRs welcome.
See Installation for setting up
@mrdoge/react, the hooks package that feeds these adapters real data.
Match Card
Maps a real matches.get() response (plus a
market from odds.list()) onto
Match Card's props.
pnpm dlx shadcn@latest add https://mrdoge.co/r/mrdoge-match-card-adapter.jsonmovementById is optional throughout: pass
useOddsMovement(market)'s result to
color options as prices change (green/red), or omit it and options render
without any color change.
Match Highlight
matchToMatchHighlightProps maps a real
matches.get()/matches.subscribe() response
onto Match Highlight's props,
including the minute/stoppage/elapsedSeconds/referenceTime fields
that drive its live ticking clock. Cards and corners are soccer-specific;
other sports get no stats row rather than misleading zeros.
matchesToCompetitionMatches is separate: a pure mapping from a
matches.list({ competitionIds, date })
response onto competitionMatches, excluding the match you're already
viewing and sorting by kickoff time. Running that query lazily (only once
the dropdown first opens) is the caller's job, same as fetching itself;
see The competition dropdown.
pnpm dlx shadcn@latest add https://mrdoge.co/r/mrdoge-match-highlight-adapter.jsonMatch Timeline
Maps a real matches.get()/matches.subscribe()
response onto Match Timeline's
entries prop, filtered to goals, cards, penalties, and half/full-time,
most-recent-first. Full-time is synthesized from
match.status/stats rather than a specific timeline event, since
there's no single event that reliably marks a match as truly over once
extra time is possible.
pnpm dlx shadcn@latest add https://mrdoge.co/r/mrdoge-match-timeline-adapter.jsonStats List
statsToStatsListEntries maps match.stats onto
Stats List's entries prop.
MatchStats is a discriminated union per sport, so this switches on
stats.sport: soccer has the richest set (possession, shots, corners,
cards, tackles, throw-ins, goal kicks, woodwork hits, penalty kicks,
...); american football, baseball, ice hockey, and handball currently
have no comparable home/away stats in the protocol beyond score and
clock, so those return an empty array.
matchToPlayerStatsListEntries is separate: the top player per side
(soccer only) for shots, shots on target, and woodwork hits, from
match.stats's per-player arrays. Returns empty unless match.timeline
has at least one player-attributed event, a proxy for "this match has
player-level tracking at all."
pnpm dlx shadcn@latest add https://mrdoge.co/r/mrdoge-stats-list-adapter.jsonOdds Selector
SOCCER_UNDER_OVER posts one market per threshold (0.5, 1.5, 2.5, ...)
instead of one market total. toOddsLines pairs each into a row, sorted
by threshold, for Odds Selector's
lines prop. pickMostBalancedMarket picks the closest-to-even
Over/Under pair as a single representative line, e.g. for the Odds Board
example, instead of an arbitrary, often lopsided, first market.
pnpm dlx shadcn@latest add https://mrdoge.co/r/mrdoge-odds-selector-adapter.jsonBet Slip
Builds a BetSlipPick directly from a real match, one of its markets,
and a selected line id. A pick is basically a selected odds line. For
Bet Slip's picks. Also populates
home/away from the match's teams, so BetSlipPickRow can render team
crests.
pnpm dlx shadcn@latest add https://mrdoge.co/r/mrdoge-bet-slip-adapter.jsonConflicts
Some selections are mutually exclusive on the same match: any Match
Result pick rules out the entire Double Chance market, Over 4.5 rules
out Under 1.5 in Total Goals, and so on. getConflictingIds checks a set of
selections against every available candidate and returns the ids
incompatible with at least one of them; getConflictingPickIds does the
same directly against an existing BetSlipPick[], for consumers without
live Market data on hand (e.g. picks loaded from storage).
What to do with a conflicting id is entirely up to you: feed it into
Odds Selector's disabledIds to
block the click before it happens, or into
Bet Slip's conflictingPickIds to flag
an already-added pick instead. The adapter only tells you what conflicts,
never what to do about it.
pnpm dlx shadcn@latest add https://mrdoge.co/r/mrdoge-conflict-adapter.jsonThree rule families, scoped to the same match:
- Match Result ↔ Double Chance: Double Chance is just two of Match Result's three outcomes combined, so the two markets describe overlapping information about the same result rather than independent events. Any Match Result selection blocks the entire Double Chance market, and vice versa, not just the specific pairs that are outright impossible.
- Over/Under threshold overlap: Over-at-
T1and Under-at-T2in the same Totals market conflict onceT1 >= T2(Under 1.5 + Over 4.5 can never both be true; Over 1.5 + Under 4.5 can). Same-side pairs at different thresholds conflict too, e.g. Over 1.5 + Over 2.5: the higher threshold winning always means the lower one wins too, so it's never a genuinely new combination. - Both Teams to Score ↔ low Totals: BTTS "Yes" conflicts with Under 1.5 goals or lower (scoring twice needs at least 2 goals).