Skip to content

v7.0.0

Latest

Choose a tag to compare

@on47sky on47sky released this 31 Aug 20:24
· 1 commit to main since this release

@azuro-org/toolkit v7.0.0

Per-outcome resolution. The protocol no longer resolves conditions — it resolves outcomes. Within
one condition, outcomes can independently be Won, Lost, Canceled (voided, stake refunded) or still taking
bets, all at the same time. The old condition-level model could not express that, and everything in this
release follows from removing it.

⚠️ This is a breaking release, and one of its changes produces no compile error. Combo totalOdds
and every figure derived from them change value for every unredeemed combo. A green tsc does not mean
the migration is done.

📖 Toolkit v7 Migration Guide — full before/after
for every item below, plus a grep-your-call-sites section.


Breaking changes

1. ConditionState is now exactly { Active, Stopped }

Canceled, Removed and Resolved are removed. A condition only ever says whether it is taking bets;
won / lost / voided is per outcome now.

// Before
condition.state === ConditionState.Resolved

// After — ask the outcome, not the condition
isOutcomeSettled(outcome.state)

If you used Removed to mean "absent from the feed" and Stopped to mean "temporarily suspended", those
are one state now. Use the condition's hidden flag to make that distinction instead.

2. MarketOutcome.isWon is removed

No alias, no deprecation. It was derived from condition-level wonOutcomeIds and was undefined whenever
those were absent — so !isWon silently rendered every outcome as lost.

// Before
outcome.isWon

// After
outcome.state === OutcomeState.Won

3. BetsReportEntry.createdAt is now required

Only affects code that builds entries itself and calls calcBetsReport directly —
getBetsReport fills it in for you.

It is required rather than optional because no default is safe: a combo is priced by the rules in force
when it was placed, so defaulting the timestamp either way silently mis-prices one era of bets.

4. BetMetaData.selections[].outcome.condition.outcomes[].result is retyped

SelectionResultOutcomeResult. The old type had no way to express a void.


New

  • calcComboOdds({ odds, createdAt }) — a combo's total odds, priced the way the protocol prices them,
    for the rules in force when the bet was placed. This is now the one place that decision lives; use it
    instead of multiplying leg odds, or calling calcMinOdds for a bet that already exists. Pass the bet's
    real createdAt — the same legs price differently either side of the fee's start date. A voided leg must
    be left out by the caller; an empty list prices at 1, so a bet with nothing left standing returns its
    stake.
  • isOutcomeSettled(state)true for Won | Lost | Canceled, false for Active | Stopped.
  • MARGIN_APPLIED_AT — unix seconds, the moment the feed started applying its fee to every outcome's
    odds. Exported because reconstructing any historical combo figure needs it. The switch was global and
    happened at one moment on every chain, so one constant covers all of them.
  • OutcomeResult (Won | Lost | Canceled) is now exported from the package root.
  • BetFragment / BetsQuery: selections[].outcome now includes result?: OutcomeResult | null — the
    authoritative per-outcome settlement signal for a bet.

Changed behaviour — no compile error

Combo odds are re-priced. The feed applies its fee to every outcome's odds, so a combo is priced by
removing that fee per leg and applying it once to the product. The subgraph records the plain product
instead, which compounds the fee once per leg:

ceil(1.5 / 0.99) * ceil(2 / 0.99) * 0.99  =  3.05   ← what the protocol pays
1.5 * 2                                   =  3.00   ← the plain product

calcBetsReport and getBetsReport now price combos the first way, so every unredeemed combo reports
higher, correct figures — by more the more legs the bet has.

Three shapes are deliberately unchanged: a redeemed bet (its recorded payout is the amount 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). Singles are unaffected either way.

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.

If you compare these figures against your own backend, snapshot tests or cached values, refresh them.


Unchanged — worth stating

OutcomeState and GameState are untouched. So is ConditionStatus / BetConditionStatus, which is a
different enum from the bets subgraph (Created | Resolved | Canceled | Paused), not the feed's
ConditionState — do not migrate it by mistake. Condition-level wonOutcomeIds is still served by the feed.


Install

npm install @azuro-org/toolkit@^7

Pairs with @azuro-org/sdk v8.0.0, which carries this
model change through the React hooks.

Full Changelog: v6.5.0...v7.0.0