Weekly entries cover everything that shipped across the platform, including
API and data-pipeline work. Version entries are the published
@agg-build packages — those four are version-linked, so a release usually
bumps them together, and the tags show which ones shipped.
Subscribe via RSS.Patchui
- Positions whose shares Agg has no purchase record for — bought directly on
Polymarket or Hyperliquid, or transferred in — no longer render a fabricated
entry price and profit. When the venue has no acquisition price we can
reconcile, the API marks the outcome
costBasisUnknownand the profile now shows ”—” for entry price, amount traded and P&L instead of 0¢ and a 100% gain. Quantity and current value are known and still shown.
Patchhooksuiauth
-
Show the Kalshi balance as a row inside the profile Balance card instead of a separate card, and remove it from the header and profile menu. The
kalshiBalanceprop onAuthConnectButtonViewis removed, and the defaultuserProfile.balance.availableBalancelabel is now “Balance”. -
hooks, ui: Reworked the Connect Kalshi modal to match the design. It now opens scrolled to its header
(the API Key ID input is focused explicitly rather than racing Radix for it), renders the
Kalshi logo at 60px on desktop and 40px inline with the title on mobile, and drops the
non-interactive “Having trouble?” help links. Below
mdit lays out as a bottom sheet with left-aligned copy and a sticky Cancel / Verify Connection footer; the success confirmation uses the narrower 480px card with a tinted success mark and a secondary Done action.Modal.Containeraccepts anonOpenAutoFocushandler so a modal can place initial focus itself instead of competing with Radix’s default. The now-unusedonboarding.connectKalshiModal.helplabels have been removed. - hooks, ui: When the user has no Kalshi account connected, Smart Routing now selects the next best route instead of Kalshi, and the Kalshi route card shows a warning icon with “Requires Kalshi account”. Kalshi stays selectable; choosing it still prompts the user to connect, and that button now reads “Connect Kalshi to trade”.
-
hooks, ui: Show the side and the live price on open limit orders. The outcome pill now reads “Buy Yes” / “Sell Yes” instead of the bare outcome, and the limit price carries the current market price beneath it (“now 25¢”). The mark is matched at the outcome level from
GET /midpoints, so the two sides of one market show their own prices; an order whose outcome has no live book keeps the limit price alone rather than showing a guessed mark. - ui: Honor the Closed bucket for resolved Kalshi winners and display their Won result on desktop and mobile rows.
- ui: Settlement: list every cluster venue on each key difference and under Full rules by venue, drop differences whose venues all say the same thing, stop repeating the question in the body when the description restates it, hide the cross-venue differences section for single-venue clusters, and scope the venue-rule hover state to its toggle.
- ui: Remove the average-price liquidity warning banner from the order panel while preserving regional restrictions, fee disclosures, and footer spacing.
Patchsdk
-
Ignore funding fields with
skipQuoteallowedSourceChainIdsandchainBalancesare now ignored whenskipQuoteis set, instead of returning 400. AskipQuoteorder is always funded on the venue’s own chain.
Minorsdkhooksui
-
Support
PT30MandPT4Hrecurring crypto cadencesRecurringCryptoDurationnow includesPT30MandPT4Halongside the existingPT5M,PT15M,PT1H, andP1D. The API can now return recurring crypto up/down markets on these cadences (Hyperliquid sub-daily windows), and the SDK, hooks (slug/aggKey parsing, canonical window polling), and UI (recurring cadence labels) recognize them end to end.RECURRENCE_CADENCES— the cadence list behind therecurrencefilter onlistVenueEvents/useVenueEvents— gains the same two entries, so filtering venue events by them type-checks. -
sdk: Add
skipQuote,skipBalanceandpricetoPlaceOrderParamsPOST /execution/orderscan now skip the smart-route solver (skipQuote) and, on buys, the balance check (skipBalance) to send one order straight to predict or hyperliquid.pricesets the trade price for askipQuoteorder. These optional fields let a TypeScript partner pass them without a cast. -
sdk: Document
skipQuoteon novig and prophetxPlaceOrderBody.skipQuotenow lists novig and prophetx alongside predict and hyperliquid.priceis ignored on prophetx, which prices the order itself withinslipCapBps.
Minorsdkhooks
-
Expose
minOrderSizeandtickSizeon venue markets Limit orders are placed without a quote, so nothing validated size or price before the request.GET /venue-markets(and the markets embedded in venue events) now carryminOrderSizeandtickSize.minOrderSizeis populated for Polymarket (the market’s own floor, the exact valuePOST /execution/limit-ordersvalidatessizeRawagainst) and PRED (0.001). Elsewhere it isnull, which means no value was ingested — not that the market has no minimum; other venues enforce floors this field does not carry. AlignlimitPriceRawto the runtime-inferredtickfrom the orderbook endpoints where one is available;tickSizeis the ingestion-time seed and the live grid can be finer.
Patchsdk
- Expose source-chain restrictions and per-chain funding budgets on direct order requests.
Patchsdk
-
Discovery outcomes now include
payoutPerShare. Events, markets, and outcomes responses return each outcome’s settled per-share payout alongsidewinner. It is set when a market pays more than one outcome — a Polymarket 50/50 pays 0.5 on each side, a Novig void refunds each side at its price — and isnullotherwise, in which casewinner ? 1/winnerCount : 0still applies.
Minorsdkui
-
sdk:
placeLimitOrderacceptsfundingAddressesfor self-custody limit buys. Pass other wallets linked to the same account alongsidesigningAddress. Their balances can fund the buy by bridging in, the same way a self-custody market fill funds from several wallets. On the venue’s own chain only the signing wallet’s balance is used. -
ui: Paper-mode and card interaction fixes.
PlaceOrderno longer asks a user to connect Kalshi when the app is in paper mode. Paper fills are simulated and never use venue keys, matching how the shared KYC prompt is already skipped for paper orders.EventListItemDetailsis only clickable when anonClickis passed. It previously always attached a click handler, so the event hero showed a pointer cursor with nothing to click.Cardonly lifts on hover (hover:shadow-agg-card-hover) when it is interactive (onClickorhref). Static cards keep their resting shadow.
Minorui
-
Add
labelandshowWhenAuthenticatedprops toPaperTradingBadge.labeloverrides the pill text for one placement (defaults tolabels.paperTrading.badge).showWhenAuthenticatedkeeps the mobilebrandpill visible for signed-in users, which is hidden by default because the full label does not fit beside the wallet chip. Both are optional; existing usage renders exactly as before.
Patchui
- Group order book rows to the nearest 0.1¢. Venues that quote finer than 0.1¢ (Hyperliquid, PRED, ProphetX) produced several order book rows that all displayed the same price, e.g. three “8.5¢” rows. Levels are now grouped to the nearest 0.1¢ — the precision the order book renders — with shares and venue breakdown summed into one row, including across venues. Total still sums each level’s real price × size, and spread and midpoint use the real best bid and ask. This is display-only: quotes and execution use the ungrouped venue books.
- Show ProphetX and Novig in the profile modal’s Trading access tab. The tab lists venues from a fixed set that did not include ProphetX or Novig, so enabling either venue for an app never added its row. Both now appear alongside the other venues and follow the same app-config and geo-block rules.
Patchsdk
-
Type
client.verify()for Privy sign-in.client.verify({ kind: "privy", privyToken })already worked at runtime, butAggAuthVerifyBodyonly allowed{ message, signature }, so TypeScript callers got a compile error.AggAuthVerifyBodyis now a union matchingPOST /auth/verify:The two branches are also exported asAggAuthWalletVerifyBodyandAggAuthPrivyVerifyBody. Existing wallet callers need no changes.
Minorsdk
-
Accept a Privy access token at
POST /auth/verify. Partner apps that use Privy as their wallet provider can let users sign in with a token minted by that same Privy app, alongside the existing OAuth, email, and wallet-signature methods. There is no separate Auth-tab setting: saving Privy under Settings → Wallet Provider turns it on.VerifyBodybecomes a union discriminated onkind:Existing callers keep working. Every wallet caller predates the discriminator, sokindis optional on that branch and existing payloads still validate. Code that readsbody.messageoff aVerifyBodyvalue without narrowing will need akindcheck. This extends the existing endpoint rather than adding a new one: how identity is proven is the only thing that differs between the two. Principal creation, the early-access gate, user creation, and token issuing are shared, so the branch lives in the auth strategy and the route is unchanged. Privy auth stores no extra configuration: access tokens are ES256 JWTs verified against Privy’s published public keys, using the Privy app ID from the wallet provider credentials. Every failure is a 401 with a message.
Minorsdk
- Expose the linked signing wallet and signing quote ID for self-custody limit orders, and accept a fresh cancellation signature without changing existing managed-order calls. Support Hyperliquid GTC/ALO self-custody limit buys and sells, with client-held EOA or agent signing and signed cancellation payloads.
Patchsdkui
- sdk: Add
settlementFeeto smart-route buy fills and document thatestimatedPayoutis net of it.settlementFeeis what the venue takes from a leg’s $1 payout if the outcome wins — today only Hyperliquid HIP-4’s close fee — and is not a cost at fill. - ui: Show and rank net payout in the place-order panel: buy routes use estimated payout after settlement fees, and sell routes show proceeds after fill fees. Keep solo routes from distinct outcomes on the same venue visible.
Patchsdk
- Document
SmartRouteBridgeStep.amountandSmartRouteBridgeStep.cost.costis the delivery margin sent on top of a lane’s allocations, not the expected bridge fee — readfeeBreakdown.bridgeFeesfor that.
Patchui
- Fee breakdown: fold the builder fee into the Venue row instead of listing it separately, and render a partner’s non-zero app fee as a dollar amount on the agg.market row. The 0% fee badge and the 0% platform fees trust line now appear only when the app fee really is zero, and the app fee is counted in the estimated-fees total.
Minorsdkhooksui
- sdk, hooks: Remove the
categoryIdsfilter fromgetVenueMarkets/useVenueMarkets. Category is an event-level attribute, so filtering markets by it made Postgres rank every market under every event in the category — enough to trip the API’s statement timeout on a large category. Prod request logs showed no callers using it: every real category filter already went through/venue-events. Filter events by category instead —getVenueEvents({ categoryIds, status })— then fetch that event’s markets withgetVenueMarkets({ venueEventId }). - Report the builder fee as its own line in the quote fee breakdown. It was previously folded into venueFees, which labelled a partner’s own charge as the venue’s. Fee totals are unchanged; the builder slice is now visible separately on the route breakdown, on each per-venue breakdown, and on every fill. Also surfaces the partner app fee on quotes that are not executable and on per-venue quotes, where it was reserved from the budget but never reported.
Minorsdkhooksui
-
Add PRED (
pred.app) as the distinctpredvenue across SDK request and response types. PRED is unrelated to Predict.fun (predict) and settles through a per-user Safe on Base. PRED custody uses the existingcustodyKind: "DEPOSIT_WALLET"discriminator, qualified byvenue: "pred"and its custody address. Existing venues’ source shapes remain unchanged. Hooks and UI add the corresponding PRED labels, filters and logo. PRED is default-hidden for existing and newly created apps until an app explicitly removespredfrom itsdisabledVenueslist.
Patchsdkui
- Use Clearinghouse executable prices and normalized amounts on ProphetX tickets. Preserve the reviewed spend and output limits during refresh, and show quote failures before order execution starts.
Patchui
- Verify that ProphetX fixed-input quotes show no execution-reserve amount or held-funds tooltip. ProphetX quote sizing uses the available book without CH surcharge, speculative commission, or slippage reserve; other venues retain their existing behavior.
Minorsdkhooksui
-
sdk, hooks: App config is now cached per App and refreshed on a bounded schedule.
AggClientexposes a publicappIdgetter, anduseAppConfig/useCachedAppConfigkey their React Query entry as["agg", "app-config", appId]instead of the previously global["agg", "app-config"]. Two clients for different Apps sharing oneQueryClientno longer read each other’s config — which matters now that the response carries the app-leveltradingModethat every execution surface renders from. Admin-key-only clients get a"__no-app__"scope. Use the exportedappConfigQueryKey(appId)to seed or invalidate the entry yourself. The query keeps its existing 5-minutestaleTimeand adds a matchingrefetchInterval, so a tab parked on one screen still picks up an App being flipped between paper and live instead of needing a reload. Nothing else about its refresh behaviour changes:refetchOnWindowFocusandrefetchOnReconnectare left at the hostQueryClient’s settings rather than forced. The interval is skipped entirely while a tab is unfocused, so a background tab costs nothing. A staletradingModeis cosmetic in any case — the API resolves mode from the App on every request, so a client holding the old value renders the wrong chrome but cannot execute in the wrong mode. - Integrate shared clearinghouse KYC for Novig and ProphetX using authoritative wallet status, skip repeat verification for approved wallets, and remove the Kalshi v2 KYC prompt while retaining account connection. Add user-scoped status queries, pending-decision handling, and protection against duplicate or stale verification actions.
- Separate clearing-house execution reserves from estimated quote fees. Preview-only slippage tolerance no longer inflates Novig or ProphetX funding reserves; actual execution reserves and spend-cap checks remain enforced. Quotes expose an optional executionReserve amount and the trading panel explains it separately from fees.
- sdk: Mark ProphetX as an active, Solana-settled venue while retaining the existing per-app default-disabled rollout gate. Staging apps can be explicitly enabled for managed-wallet market execution once the clearing-house identifier resolver is deployed.
- hooks: Keep live managed balance queries refreshed every five seconds while the page is visible. This lets the shared provider and balance hook recover when a fill notification arrives before the settled balance snapshot. Existing post-trade invalidation remains immediate; paper balances retain their event-driven behavior.
- hooks, ui: Keep temporarily unavailable venue quotes visible as disabled comparison cards, including ProphetX when clearing-house readiness fails. Preserve available price previews and support a customizable availability label.
-
ui: Paper trading UI, gated so live apps render exactly as they do today.
An app is paper or live at the App level (
tradingModeonGET /app/config), and the components resolve it throughuseResolvedExecutionModefrom@agg-build/hooks. In a paper app the library now renders a “Paper trading” header pill, a three-step onboarding modal, and Buying Power / Earnings cards on the profile, and it hides the surfaces that have no paper equivalent — deposit, withdraw, venue cash balances, and the Limit order tab. Nothing here changes how a live app renders. Every layout change this feature needed is behind the paper branch, including the ones that would otherwise have been global:Headerkeeps its 24px mobile inset and no brand-group gap unless abrandAccessoryis supplied.- The sign-in button keeps the
largepreset at every breakpoint; the tighter 79x28 mobile size is paper-only, and the signed-out control is no longer wrapped in an extra flex box. - The profile summary grid keeps its
1fr / 300–420pxcolumns and 32px gap; the wider 626px column is paper-only. - Profile summary cards keep 20px padding and wrapping labels; the compact 16px padding and single-line label are paper-only.
- A card that supplies no
captionrenders its value exactly as before, with no extra row wrapper.
Headergains an optionalbrandAccessoryslot, rendered after the logo inside the brand group. Supplying it also opts that header into the brand-group gap and the 16px mobile inset the accessory layout is drawn against — so pass it conditionally rather than handing it a child that hides itself, since the header cannot see that the element it was given renderednull.Modal.Containergains acenterclass slot for overriding the default bottom-sheet positioning belowmd.
Patchsdk
fillSelfCustodynow follows thepollAfterMsthe server sends on each/execution/statusresponse instead of sleeping a fixed 2s, and takes a short first poll rather than burning a full interval before its first read. The API asks for 1s today, so a parked signature is found in roughly half the time.SELF_CUSTODY_POLL_INTERVAL_MSis unchanged and is still the fallback when the server does not send the field. Server values are clamped to 250ms–30s.- Add
venueMarketOutcomeIdtoVenueSoloQuote. A venue can list the same matched outcome more than once (two Hyperliquid deployers on one game), sovenuealone does not identify a solo card. Key onvenueplusvenueMarketOutcomeIdwhen tracking a selected route.
Minorsdk
- Self-custody fills can now be funded from a legacy Polymarket Safe — the Gnosis Safe
Polymarket deployed for a user before they joined this platform — at any venue, not just
Polymarket. Nothing changes for wallets that never had one.
SignatureRequestTypegains"safe_tx". The payload is the Safe transaction as EIP-712 typed data, but the wallet mustpersonal_signthe RAW 32 bytes ofhashTypedData(payload)(viem:signMessage({ message: { raw: hash } }); MetaMask:personal_signwith the hex hash). The wallet shows a hash rather than a structured prompt — that is the only shape Polymarket’s relayer accepts, so a plainsignTypedDataover the same struct is rejected.payload.safeTxHashcarries the digest for convenience; the server recomputes it and never trusts the copy. As with every request type, throwing from your signer is not a rejection: the request expires and the fill fails.SmartRouteAllocation.custodyKindgains"POLYMARKET_LEGACY", withcustodyAddressset to the Safe. Signers that switch oncustodyKindshould treat it as a source the user does not hold directly.
Patchsdkhooksui
-
sdk: Correct what
approveModesays about cost. Thesponsoreddocblock said the gas is paid for you and that later bridges on a delegated chain are then free. The first half described only the one-time ERC-20 approve, and the second was wrong: Relay’s fee is deducted from the amount delivered on every bridge, and one-time costs such as a Hyperliquid first-deposit activation still apply. A partner reading it would have told their users bridging was free and left them to discover the shortfall in the delivered amount. The wording now describes what each mode does to the wallet — whether it is asked for gas — without implying anything about the total cost of a bridge, and points atfeeBreakdown.bridgeFeesandfeeBreakdown.setupCostson adeepEstimatequote as the figures to actually read. Documentation only; no behaviour changes. This supersedes the cost claim in the v4.6.0 entry, which stands as the record of what that release said. -
sdk, ui: Surface Hyperliquid’s one-time address activation fee as a setup cost.
Hyperliquid charges 1 USDC to activate an address on its first deposit. Deep-estimate quotes
(
deepEstimate=true) now carry it as afeeBreakdown.setupCostsline withkind: "hyperliquidActivation",alreadyPaid: trueonce the address exists on Hyperliquid, and it counts towardsetupCostsTotalandtotalCost. The fee is deducted inside the bridge leg rather than run as its own step, so the execution progress view does not render a setup step for it. -
sdk, hooks: Fix two EIP-4361 conformance bugs that made SIWE sign-in fail with a misleading
Invalid SIWE signature401.buildSiweMessagenow keeps the empty statement slot when no statement is given. The ABNF isaddress LF LF [statement] LF LF, so omitting the blank line produced a message no conforming parser accepts.buildSiweMessagenow applies the EIP-55 checksum itself, in any input casing, instead of building a message the server rejects before it ever checks the signature. wagmi users were unaffected because its connectors already normalise; partners bringing their own wallet were not. The SDK stays dependency-free: it carries a self-contained Keccak-256 for this (toChecksumAddressis exported for partners who want it directly).
Patchhooksui
-
Add ProphetX to the Venue enum. Discovery only for now, so the venue is in
INACTIVE_VENUES and hidden behind PROPHET_X_DATA_VISIBLE; it renders with the
neutral venue icon until brand artwork lands.
Add ProphetX to the event list venue tabs. The tab follows the same per-app
gate as every other venue, so it is hidden for any app whose
/app/configlists prophetx indisabledVenues. -
ui: Fix duplicate cards on the sports market detail page.
- Group decomposed N-way legs (halftime result, second-half result, first to score, NRFI) into one card with a pill per leg instead of one card per leg, unioning the venues that offer each leg. A bucket that cannot render as a decomposition splits back to one card per market, so no market is ever hidden.
- Collapse whole-number line rungs onto the same ladder as half-step ones. The aggKey encoder writes 8.5 as 8p5 but 8 as a bare integer, so integer rungs used to strand themselves in their own card.
- Parse the signed leg token in a spread aggKey. Spread keys now carry m/p on the line, so the previous pattern matched nothing and the signed ladder axis was inert, collapsing both halves of a symmetric spread onto one stop.
- Read the favoured and underdog roles off that leg token rather than assuming outcome 0 is always the favourite, which mislabelled every underdog-leg rung.
- Head each period section when a tab spans more than one period, so two cards that share a title are distinguishable.
- ui: Render a sports line ladder as a ladder, never one pill per rung. Every rung of a line ladder is its own Yes/No market with its own question, which by shape alone is indistinguishable from a decomposed N-way leg. A seven-rung team total therefore rendered seven pills on top of the rail that already selects between them. A leg is an outcome of one question and a rung is a line of one market, so a group carrying any lineValue now renders as a ladder and its pills are the active rung’s two outcomes.
Patchui
- Fix limit-order sells on matched (multi-venue) markets.
- The sell venue picker no longer offers venues the user holds no shares on. The automatic pick sorts on price alone, so on a matched cluster it could choose a venue with no position — the API then rejected the order with “Insufficient available position size”.
- The “max shares” figure now matches positions across the whole matched cluster
instead of only the selected venue market. Limit mode has no smart-route quote
to fall back on, so a position held on another venue of the cluster read as
0 shares.
Patchui
- Hide default-disabled venues (Novig today) in the event list tabs while
/app/configis loading, so a partner-opt-in venue no longer flashes in and out for apps that disable it.
Minorsdkhooks
- Market lists for an event now cover its whole matched cluster by default.
-
getVenueMarkets({ venueEventId })anduseVenueMarkets({ venueEventId })return every venue’s markets for that real-world event, not just the markets belonging to the one event you named. Matched siblings are folded into a single anchor row rather than repeated, and each row still carries its cross-venue counterparts inmatchedVenueMarkets[]. Naming any member of a cluster returns the same page in the same order, so you no longer need to know which event id is the anchor. This is the only way to reach markets that trade on a single venue and therefore have no cross-venue counterpart — previously they were unreachable unless you happened to ask for the exact event that carried them. -
New
clusteroption on both, plusgetVenueEventByIdanduseVenueEvent. Passcluster: falsefor the previous behaviour: only the named event’s own markets. If you render a market list from an event’sidand rely on it matching that one venue’s markets exactly, passcluster: falseto keep today’s output. -
marketCountand the rolled-upvolumeongetVenueEventById/useVenueEventnow cover the whole cluster to match.marketCountis the number of rows the market list returns for that event (open markets, matched siblings folded into their anchor), so it can be paged to exactly — passstatus: ["open"]to the market list to see the same set, since an unfiltered list also returns closed and resolved markets.volumesums every open and closed market in the cluster, including the siblings folded out of the list, so it is deliberately not a total over those rows. The embedded (deprecated)venueMarketsarray is unchanged — always the one event’s own markets. Pass the sameclustervalue to the event and market calls so the count agrees with the list you render.
-
Minorsdk
-
Self-custody fills take a new optional
approveModeonfillSelfCustody(), for wallets that cannot sign a raw-digest EIP-7702 authorization. Omit it and nothing changes: the fill stays sponsored, we pay the gas for the ERC-20 approve, and your signer may be asked for theeip7702_authorizationrequest as before — an EOA already delegated to Calibur skips that step. Pass"user_broadcast"when you know your wallet cannot produce that signature. The approve comes back as atransactionrequest instead — the user sends it themselves and pays its gas. Only your client can make this call, because whether the signature is possible is a property of the wallet software, not of the address or the chain, so we cannot detect it from our side. Worth surfacing in your UI:"user_broadcast"never establishes the delegation, so the user pays gas on every bridge. Sponsored costs one signature once per chain and is free from then on. Reach for"user_broadcast"as a fallback, not a default. -
Self-custody users can now fund a trade from their own wallet, not just from money already sitting in their Polymarket deposit wallet.
SignerFnmay now return{ txHash: string }as well as a signature string. Returning a string keeps working exactly as before — this is additive, and existing signers need no change. The object form is for the newtransactionrequests, where the wallet broadcasts and you hand back the hash. Return it immediately, without awaiting the receipt; the server watches for the mined receipt itself.SignatureRequestTypegains"eip7702_authorization". Its payload is{ contractAddress, chainId, nonce }and it is signed over a raw EIP-7702 digest — not EIP-191, not EIP-712. Many wallets do not expose this. Throwing from your signer is not a fallback — nothing reads it as a rejection, so the request expires and the fill dies. If your wallet cannot sign it, sendapproveMode: "user_broadcast"on the fill and the ERC-20 approve is requested as atransactionthe user broadcasts themselves. Handling the authorization is what makes the funding step gasless. -
Add a
signeroption andfillSelfCustody()for self-custodial fills. Supply asignerfunction and the wallet that will sign, and the SDK drives the sign-and-resume round trip; the key never leaves your process.
Minorsdkhooks
-
Expose wallet account linking (SIWE/SIWS), matching the API that shipped in
feat(auth): link an external wallet to an existing account.AggLinkAccountBodygains{ provider: "siwe" | "siws"; address: string }, andAggLinkAccountResultgains{ type: "wallet_challenge"; message: string }.linkAccountConfirm()/useLinkAccount().confirmLink()now accept either the existinglink_confirm_tokenstring (OAuth/email) or{ kind: "wallet_signature"; message; signature }(wallet). Pass themessagereturned by/startverbatim — the server compares it byte-for-byte, so any client-side reconstruction fails.
Minorhooksui
-
hooks: Add
useSportsLiveanduseRecurringCryptoMarkets, and harden execution progress reporting.useSportsLivepolls live sports scores and exposesSportsLiveStatewith participant scores and game status. ShipssportsLiveQueryKey,sportsLiveRefetchIntervaland theSPORTS_LIVE_POLL_INTERVAL_MS/SPORTS_SCHEDULED_POLL_INTERVAL_MSconstants so callers can align their own cache with the poll cadence.useRecurringCryptoMarketsresolves the rolling window of a recurring crypto market — current instance, timeline and identity — alongsidefetchRecurringCryptoMarkets,mergeRecurringCryptoWindows,resolveRecurringCryptoIdentity,resolveRecurringCryptoTimelineandrecurringCryptoTransitionPollIntervalfor callers driving their own polling.- Execution progress recovers from failed DAG steps more predictably, and now exports the
ExecutionStepProgressandExecutionRawStepProgresstypes. - Limit orders accept fractional sizes, and venue quotes surface a slippage warning.
- Novig added to the exhaustive frontend venue maps.
- New
sportsLiveand recurring-market label keys, all defaulted.AggUiLabelsInputremains a deep partial, so existing label overrides are unaffected.
-
ui: Add live sports scores and recurring-market navigation to event views, and fix a batch of
order-flow issues.
- New sports live-score display, exported from
@agg-build/ui/events, showing participant scores and game status on event items and market details. - Event item details gain recurring-market navigation — window selector, countdown and a
“go to live” affordance — driven by the new optional
recurringMarketsprop. - Order-placement fixes from QA, covering state clearing between orders and slippage presentation in the place-order flow.
- Balance management fixes, including raising the default refill maximum to 1000 USDC.
- Live scores removed from the event list; they remain on detail views.
- New sports live-score display, exported from
Minorsdk
-
Add
placeOrder()for direct single-venue order entry viaPOST /execution/orders, and surface the partnerexternalIdon order reads, webhooks and order events. -
Kalshi is now a fully active venue.
isVenueActive("kalshi")returnstrue,INACTIVE_VENUESis empty, andgetEffectiveDisabledVenues()no longer adds Kalshi to the disabled set by default. Apps that relied on Kalshi being filtered out automatically should add it to their owndisabledVenuesif they still want it hidden.isVenueExecutablehas been removed. Every active venue is executable, soisVenueActiveis the single predicate — replace anyisVenueExecutable(v, override)call withisVenueActive(v). It was never exported from the partner-facing entry point, so this only affects internal consumers. -
getEffectiveDisabledVenuesnow treats an app’s venue list as authoritative instead of merging it with the platform’s default-hidden set. Previously the two were unioned, so the result always included every not-yet-launched venue no matter what the app passed. Now:getEffectiveDisabledVenues(undefined)— no app context — returns the platform defaults, as before.getEffectiveDisabledVenues([])returns[]. An app that disables nothing excludes nothing.getEffectiveDisabledVenues(["kalshi"])returns["kalshi"], not["kalshi", ...defaults].
undefinedand[]is new and load-bearing:undefinedmeans “no app configuration exists”,[]means “this app has opted into everything”. Passing?? []where you mean “no context” will now reveal default-hidden venues, so pass the value through unchanged. This matters because venue visibility is moving from a compile-time constant to per-app configuration. Read your effective list from/app/config(disabledVenues), which already resolves this for you — that is unchanged and remains the recommended source.isVenueActive,isVenueInactive,INACTIVE_VENUESandACTIVE_VENUESare unchanged. -
Add
deployerVenueto the orderbook batch types.MatchedOrderbookMarket.deployerVenuenames which Hyperliquid HIP-4 deployer a cluster member belongs to, andVenueOrderbookEntry.deployerVenuenames which deployer’s book the published entry carries —venueOrderbooksis keyed by bare venue name, so it holds at most one Hyperliquid book even when a cluster has several deployer members. Both arenullfor every other venue. Mirrors fields already present on the API contract and the published OpenAPI spec.
Minorui
-
Add Novig to the canonical event-list venue tabs, and stop inactive-venue tabs
flashing while
/app/configloads.getDefaultEventListTabsnow emits a Novig tab. It renders only where Novig is data-visible — the venue sits inINACTIVE_VENUES, so/app/configreports it underdisabledVenuesunless the API setsNOVIG_DATA_VISIBLE=true, anduseEventListTabsdrops disabled venues before render. Partners on an environment without that flag see no change.useEventListTabspreviously special-cased Kalshi when deciding whether to treat an unresolved app config as hidden. Any compile-time-inactive venue has the same problem — its tab is “available” until the config resolves, so it appears and then vanishes on first paint. The check now uses the sharedisVenueInactivehelper and covers Novig too.
Minorsdk
-
Export the
QuoteErrorCode/QuoteErrortypes, and add aquote_min_order_sizecode./execution/fillpreviously rejected a quote minted withstatus: "min_order_size_violated"as the genericquote_unfillable, which named neither the cause nor the fix. It now returnsquote_min_order_size, and the accompanyingmessagenames the venue minimum. Both the paper and live fill paths derive the code from the cached quote’s status.QuoteErrorCodewas previously unexported, soAggApiError.codecould only be compared as a bare string. Branch on it with autocomplete instead:Checkingstatus === "ok"on the smart-route response before calling/execution/fillavoids the round-trip entirely.
Patchsdkhooks
-
Fix READMEs left stale by v4.
Both packages still documented
quoteManaged/useQuoteManaged, which were removed in v4 — the npm pages described methods that no longer exist. Replaced with thegetSmartRoute()→executeManaged()flow (useSmartRoute→useExecuteManagedin React) and a note explaining the removal. The SDK’s “Peer dependencies” section also claimed the package “bundles its own clients forviem,ethers@5,@polymarket/clob-clientand@polymarket/builder-signing-sdk”. That was never accurate — those were declared as runtime dependencies but no code path imported them, and none were bundled. It now states the truth: zero runtime dependencies,node:cryptothe only imported module, bring your own signer. Also documentsAggApiError/isAggApiError, added in v4 but missing from the exports table.
Majorsdkhooksuiauth
-
sdk, hooks: Remove
quoteManagedanduseQuoteManaged, along with theQuoteManagedParams,QuoteManagedResponse,QuoteManagedStep,QuoteManagedSplitandUseQuoteManagedOptionstypes. Their endpoint,POST /execution/quote, does not exist on the API — the call has only ever returned 404, so no working integration can depend on it. Nothing in the SDK, hooks, UI library or demo app used them. To quote and fill a managed trade:The React equivalents areuseSmartRouteanduseExecuteManaged. -
sdk: Export
AggApiErrorandisAggApiError. Every non-2xx API response has always been thrown withstatus,code,retryableanderrorsattached, but the thrown value was an untypedError, so consumers had no way to reach those fields without matching on message text. The class and type guard are now exported; runtime behaviour is unchanged. -
sdk: Remove four unused runtime dependencies (
ethers,viem,@polymarket/clob-client,@polymarket/builder-signing-sdk). None were imported by any code path — the SDK’s only external import isnode:crypto. This cuts roughly 65 MB from a fresh install and removes the corresponding bundler traversal, which was the single largest install-size contributor for React Native consumers.
Majorsdkhooksuiauth
- sdk, hooks: Remove
yesPricefromsortByonlistVenueMarkets/useVenueMarkets. The cross-event browse sort by price had no consumer and its dedicated index was one of the largest on the table. Markets listed under an event still order by price where the event’s structure calls for it, and theminYesPrice/maxYesPricefilters are unchanged. Callers passingsortBy: "yesPrice"should drop the option.
Minorsdk
- Add display metadata to execution status steps:
orderIds,kind,groupId,groupStatus,label, andbridgedetails, so clients can render per-leg execution progress without classifying raw DAG step types. - Add
getVenueGeoPolicy()— returns the per-venue blocked-country lists (ISO 3166-1 alpha-2) fromGET /app/venue-geo-policy. This is the raw venue policy, not per-user eligibility; keep using the quote’swarningsarray to gate a fill.
Patchsdk
-
Add the missing
slippagefield toSmartRouteResponse. The API has always returned route slippage metrics on the smart-route response (SmartRouteResponseTB.slippagein the contract:vwap,refMidpoint,slippage,slippageBps), but the SDK’s hand-mirrored interface never declared it.@agg-build/hooksreadsslippage.slippageBpsto flag thin liquidity, so that code — and its test — could not typecheck against the published type. Purely additive: the field is optional, so no existing consumer changes behaviour. The newSmartRouteSlippageinterface is exported alongside it.
Patchsdk
- Widen
WithdrawalSourceTokenSymbolto includeUSD1. BNB USD1 (Myriad settlement inventory) can now fund a withdrawal, so it can appear in a withdrawal’ssources[]. It is a source-only token —WithdrawTokenSymbol(the request/destination union) is unchanged, same aspUSD.
Minorhooksui
-
Add
config.formatting.formatPriceso partners can override how prices render.formatPercentalready governed probability rendering on discovery surfaces, but every cents surface formatted prices with a hardcoded formatter. Partners using a non-percentage odds convention (decimal, fractional, moneyline) ended up with converted probabilities on discovery pages and unconverted cents everywhere else.formatPricereceives the same0..1probability asformatPercentand now governs the order book, event page outcome chips, place-order, and positions. Set both to the same function to apply one odds convention app-wide. The positions view model also honorsformatCurrency, which it previously ignored.formatPriceis optional and unset by default, so every surface keeps its current rendering until a partner opts in. The order book spread and position PnL percentages stay on the built-in formatters by design — neither is a price.
Patchui
- Scope the order-book view for a selected outcome to that market’s own matched set. The label fallback in
collectEligibleVenueOutcomesno longer merges same-label outcomes from other markets that are on the opposite semantic side: a second same-venue market with a different question (a decomposed per-team sibling leg or a same-family total) and markets of a different framing shape (bare Yes/No leg vs team-titled single) are excluded when the user’s exact outcome is known. Fixes the unmatched kalshi moneyline leg’s No view showing polymarket rows the router can never fill on, and the crossed book / negative spread produced by merging opposite-side books.
Patchhooksui
- Event detail page: load every market instead of only the first page of 20.
useVenueMarketsgains afetchAlloption that eagerly fetches remaining cursor pages until exhausted;MarketDetailsListanduseEnrichedVenueEventnow use it with a 100-row page size, so events with many markets (e.g. 80+ open markets) render their full market list instead of a silently truncated one. - ui: Sports moneyline card: when a bare Yes/No leg and a cross-venue titled single collide on one aggKey (venue mis-keys a leg with the event base), keep the titled single — it renders one pill per team and carries the cluster — instead of first-wins evicting it.
Patchui
- Sports game-detail page: fix period tab ordering and add a sport-aware gate so a market never surfaces a nonsense tab for its sport. first_N_innings tabs now sort together, numerically by N (5 Innings no longer sorts before 3 Innings). A period family implausible for the events sport (e.g. a Sets period on a baseball event) demotes to the Other tab instead of rendering its own tab, closing the gap left by an upstream Rust classification fix. The gate fails open: unknown or unlisted sports keep every existing tab.
Minorhooksui
- Sports game-detail tabs are now derived from the game’s own markets instead of a fixed, soccer-shaped list. A baseball game renders Game Lines / 5 Innings / Home Runs / Strikeouts rather than Game Lines / Halves / Other. Three tab kinds are derived per game: Game Lines (full-game moneyline, spreads and totals, plus team props and specials such as the first-inning-run and extra-innings markets), one tab per period family that has lines (1h and 2h collapse into a single Halves tab as before, while first_5_innings reads as 5 Innings), and one tab per player-prop stat, labelled from the market subtype. Soccer Corners / Goals / Assists / Shots tabs are unchanged and still resolve their labels through the existing cornersTab / goalsTab / assistsTab / shotsTab ui-config keys, so partner overrides keep working. Three new overridable label keys are added: quartersTab, setsTab and playerPropsTab. The Game Lines tab no longer filters to regular time. Period-scoped markets now have their own tabs, and that filter had been hiding the period-scoped game props which belong on Game Lines.
- ui: Sports moneyline card: drop decomposed per-team legs as a set once their merged single is present, instead of only the legs carrying a match edge. The matcher routinely pairs just some of a game’s legs, which left an orphan leg beside the anchor and still rendered the whole matchup question as a pill.
-
ui: Trade panel: stop presenting an unaffordable primary route as a dead end when
the same quote carries an executable solo. Solo route cards with their own
quoteId no longer inherit the primary’s
insufficient_balancestatus/error, and the default card selection prefers the executable solo when the primary is blocked on funding — a Kalshi-funded user with no on-chain balance now lands on a submittable Kalshi route instead of a blocking “Insufficient balance” alert. Quotes where nothing is executable still block exactly as before.
Minorhooksui
- Sports game-detail tabs are now derived from the game’s own markets instead of a fixed, soccer-shaped list. A baseball game renders Game Lines / 5 Innings / Home Runs / Strikeouts rather than Game Lines / Halves / Other. Three tab kinds are derived per game: Game Lines (full-game moneyline, spreads and totals, plus team props and specials such as the first-inning-run and extra-innings markets), one tab per period family that has lines (1h and 2h collapse into a single Halves tab as before, while first_5_innings reads as 5 Innings), and one tab per player-prop stat, labelled from the market subtype. Soccer Corners / Goals / Assists / Shots tabs are unchanged and still resolve their labels through the existing cornersTab / goalsTab / assistsTab / shotsTab ui-config keys, so partner overrides keep working. Three new overridable label keys are added: quartersTab, setsTab and playerPropsTab. The Game Lines tab no longer filters to regular time. Period-scoped markets now have their own tabs, and that filter had been hiding the period-scoped game props which belong on Game Lines.
- ui: Sports moneyline card: drop decomposed per-team legs as a set once their merged single is present, instead of only the legs carrying a match edge. The matcher routinely pairs just some of a game’s legs, which left an orphan leg beside the anchor and still rendered the whole matchup question as a pill.
Patchui
- Sports moneyline card: render one pill per team when a venue’s decomposed per-team legs and their merged cross-venue single are both in scope. Opening the leg venue’s own event (e.g. kalshi’s side of an MLB game) previously showed the merged anchor as an extra pill labelled with the whole matchup question.
Patchui
- Show every quoted venue in Smart Routing, not just the fundable ones. A solo
venue whose own funding lane was short came back without an executable quote id
and was dropped from the comparison list — so when an off-chain venue won the
route (which keeps the overall quote
ok), the alternative venue vanished from the panel entirely. The card now renders with its payout for comparison; the panel’s existing Deposit / Add funds CTA remains the funding signal.
Patchsdkhooks
- Add
isVenueExecutablevenue predicate (@agg/common) for gating per-venue order-execution eligibility, distinct fromisVenueActive(compile-time) andisVenueDataVisible(data display).
Weekly
Changed
- Markets listed under an event are ordered more sensibly. Sets of competing candidates now sort by odds, and events whose legs are labelled by month sort chronologically instead of falling back to a shared settlement date.
- Limitless recurring short-window crypto markets now appear as soon as the venue publishes the next slot, ahead of the window opening, instead of showing up part-way through it. They arrive with
statusofunopenedand only become tradable once the window starts.
Fixed
- Orders and transfers no longer fail with invalid- or insufficient-balance errors in two cases: Limitless positions reported more shares than the wallet could actually sell, and BNB transfers were quoted against a larger amount than the one that landed in the wallet.
- Polymarket deposit wallets now resolve to the address the venue actually deployed. Funding and orders were being pointed at a predicted address that no longer exists on chain.
- Activity now lists only deposits a user actually made. Internal settlement and bridge transfers arriving in a managed wallet were being reported as incoming deposits.
- Polymarket events that were missing some of their markets, and quiet markets whose prices had stopped updating, now stay current.
- Markets Polymarket has shelved no longer show as open and tradable, and events that have finished report a
volume24hrof0rather than a frozen figure. - Full settlement rules are returned for every venue on a matched market instead of just one of them, and Limitless grouped markets now carry their own rules text.
- Search and orderbook reads stay fast and reliable under heavy load. Both previously slowed to several seconds or failed outright when traffic was high.
Minorsdk
-
Add
bookQualityto position responses (OutcomePosition,VenuePositionBalance). Positions are marked at the price the held size could actually be closed at, by walking the venue’s resting book. When a venue’s book is degenerate — a handful of contracts of real bid behind a stub ladder — that mark collapses, butpriceSourcestill reports"orderbook"because the walk did fill. Nothing in the response distinguished that from a healthy fill.bookQualitycarries the engine’s existingBookQualityverdict (healthy/wide_spread/bid_only/ask_only/endpoint_stub/crossed/empty) for the worst book across the position’s legs, so clients can label a low-confidence mark instead of rendering it as a market price. Values are unchanged — this adds a signal, it does not re-mark. ReadpriceSourcefirst:bookQualityonly qualifies book-derived marks, and asettledposition reportsemptybecause it consults no book.
Patchui
-
Fix Tailwind utilities resolving theme tokens at
:rootinstead of at the element. The@themeblock is now@theme inline, so.bg-agg-primary& friends emitvar(--agg-color-primary)directly rather than a--color-agg-*alias bound at:root. Two consequences of the old form are fixed:- Dark mode.
:rootnever matches.dark .agg-root:not(.light), so every utility resolved against the light defaults regardless of theme —.bg-agg-primaryrendered#536dfeand.text-agg-foregroundrendered#020205on dark surfaces. - Consumer theming. Overrides scoped to
.agg-root(including Partner Theme Studio’s exported CSS) never reached any utility class.
:rootcan drop that block. - Dark mode.
Patchauth
- Surface auth-callback failures as a toast. Account linking (and sign-in) completes on the OAuth redirect-return page, detached from the UI that started it — so when
linkAccountConfirmrejects (e.g. HTTP 409already_linked_elsewherewhen the provider identity is already linked to a different user) the error only landed silently inAggAuthProvider’s error state and the user saw nothing.AggAuthProvidernow toasts the callback error (when a toast provider is mounted) with a readable message —already_linked_elsewhere→ “That account is already linked to a different user.” — titled for linking vs sign-in based on whether alink_confirm_tokenis present.
Patchsdk
- Fix
client.linkAccountConfirm()401’ing with “Missing Authorization header”. Confirm runs on the OAuth redirect-return page, where the full-page reload has wiped the in-memory access token (tokens are never persisted). The request therefore went out with noAuthorizationheader, andrequest()’s 401-refresh-retry is gated on an existing token so it couldn’t recover — so account linking failed at the final step.linkAccountConfirm()now mints a fresh access token from the refresh cookie/token (deduped) before the request when the in-memory token is absent; if the session is genuinely gone the refresh throws and the caller surfaces it.
Patchsdkhooksui
- Complete the ProfileModal account-linking flow. The initial fix (#2503) switched ProfileModal’s connect buttons to
client.linkAccount(), but the rest of the round-trip was missing — this finishes it:@agg-build/sdk—client.linkAccount()now sendscredentials: "include"in the default bearer delivery mode. Without it the same-origin link-proof cookie the server sets on/users/me/link-account/startwas dropped on the cross-origin response, so the OAuth link callback rejected every link withlink_proof_invalid.@agg-build/hooks—handleAuthCallback(the shared callback handler auto-run by@agg-build/auth’sAggAuthProvideranduseAggAuthCallback) now detects thelink_confirm_tokenthe provider callback returns, callsclient.linkAccountConfirm(), refreshes the user, and strips the token from the URL. Previously nothing consumed the token and the link silently never persisted. A collision (identity already linked to a different principal) surfaces as the callback error (HTTP 409);already_linked_sameresolves idempotently.@agg-build/ui— email linking (magic link, no redirect) now shows a “check your inbox” success toast so the click has visible feedback.
Patchui
- Fix ProfileModal social connect/disconnect. Connect now links the provider to the already-signed-in principal via
client.linkAccount()(POST /users/me/link-account/start) instead of starting a fresh sign-in viastartAuth()(POST /auth/start), which could not attach to the current user and caused a competing double-redirect. Disconnect (and connect) calls are now guarded and surface the API error (e.g. “Cannot disconnect the only linked auth provider”) through the modal’s toast instead of escaping as an unhandled promise rejection with no user feedback.
Patchhooks
- Poll the venue-event query while a market lingers “open” past its endDate, so short-cadence markets (e.g. Kalshi 15-min BTC) transition to their resolved state instead of rendering a stale open market with no orderbooks (SNA-3047). endDate only triggers refetches — server status stays authoritative, so venues with inaccurate endDates can’t disable trading.
Patchui
- Update settlement differences UI behavior
Patchui
- Stop the combined-moneyline card from rendering unmerged cross-venue duplicates of one market as two identical pills (“Match Winner” ×2 showing the same Yes price twice). When per-leg labels aren’t distinct, the card falls back to the standard single-market rendering with team-title pills (SNA-3028, esports).
Patchui
- Render “Team to Advance” in the Game Lines tab, above the Moneyline (Polymarket parity). Knockout advance markets are primary game lines (multi-million volume) and were buried in Other; for a venue whose only market is the advance single (hyperliquid) this is what makes Game Lines exist at all. One card per game, anchored by the 2-outcome single with team-name pills (SNA-3028).
Minorui
- The Search primitive now requests
status: ["open"]so open-only filtering happens server-side: pages arrive full of tradeable results and pagination is honest, instead of fetching all statuses and emptying resolved-heavy pages client-side (which rendered “No markets found” for queries like “5m btc” whose top results are recurring-series history).
Minorsdkhooksui
- sdk, hooks: Add an optional
statusfilter to search:client.search({ status: ["open"] }),useSearch({ status: ["open"] }), anduseMarketSearch({ status: ["open"] })return only markets/events in the given statuses. Pass["open"]for tradeable-only results — without it, recurring series (e.g. 5-minute up/down markets) can fill a page with resolved history, which a UI that hides non-open rows renders as an empty result. - ui: Give whole-match totals a clean unit-based title (“Total Goals” / “Total Corners” / “Total Rounds”) derived from the group’s stat, instead of a raw venue question that produced labels like “Reg Time: Over 0.5 goals scored Totals” when a kalshi market anchored the group (SNA-3028). Per-team totals keep their subject (“Argentina Totals”).
Patchui
- Show consistent team names on sports spread outcome pills (
{Favored} −X/{Dog} +X) regardless of which venue anchors the ladder stop. A kalshi/limitless anchor storesYes/Nolabels; the team names are now borrowed from the cross-venue twins (poly/predict) at the same signed line, falling back toYes/Noonly when no venue carries a team title (SNA-3028).
Patchui
- Raise the sports event per-tab market fetch page size from 20 to 100 (the API max), so a prop-heavy tab like “Other” loads in 1–3 requests instead of ~15.
- Render sports spreads as a single symmetric ladder (home ← center → away) like Polymarket, instead of two same-titled “Spreads” cards. Both favored-side families (
…_sp_arg/…_sp_che) now collapse into one spread group, and the ladder lays them on a signed magnitude axis with the home/first team anchoring the negative side (SNA-3028).
Patchui
- Group sports spread/total ladders by the aggKey line-family instead of the market question, so the same total (e.g. match total O/U) no longer fragments into separate cards across venues that phrase it differently (SNA-3028).
Patchsdkhooks
- Clarify the id vocabulary across the WS surface and surface resolved-market status on
/midpoints.useMarketOrderbooknow acceptsvenueMarketOutcomeId(theoutcomes[].idfrom REST market responses); the oldmarketIdoption keeps working but is deprecated — it has always carried a venueMarketOutcomeId, not a venueMarketId.- SDK
onSnapshot/onDeltacallback parameters are renamedoutcomeId(type-level only, no runtime change). subscribed/unsubscribedconfirmations on the arb channel now also echo the ids undermarketIds(arb subscriptions are keyed by marketIds); the misleadingoutcomeIdsmirror stays for backwards compatibility.- The gateway’s
Snapshot unavailable for <id>error now explains that orderbook subscriptions take venueMarketOutcomeIds, not venueMarketIds. GET /midpointsentries now carrymarketStatus, and resolved markets return null prices plus a structurederror(code: "market_resolved") instead of a stale settled-market mark; unknown ids getcode: "market_not_found".
Minorsdkhooksui
- Discovery responses no longer carry outcome prices.
GET /venue-events,GET /venue-events/:id, andGET /venue-markets(and/search, which shares the same shapes) stop returningvenueMarketOutcomes[].price— including onmatchedVenueMarkets[]siblings. TheVenueMarketOutcome.pricetype is now optional and deprecated. Fetch live prices fromGET /midpoints(or theuseMidpoints/useViewportMidpoints/ live WS hooks), keyed byvenueMarketOutcomeId. UI components already prefer live midpoints; the staticpricewas only a pre-live seed and is now ignored when absent.
Patchui
- Sports detail page: honor the documented open period grammar (
set_N,map_N,game_N,period_N,inning_N,first_N_innings) instead of collapsing those markets into the “Other” period bucket; treatmatchas full-game scope so whole-match markets stay in Game Lines; stop parsing the opaqueaggKeyfor the league label (categories are the only label source).
Patchui
- Fold cross-venue moneyline legs into the 3-way Moneyline card regardless of which venue anchors the merged representative:
isBinarySportsMoneylineMarketnow also recognizes a leg by its deterministic_ml_aggKey (e.g. a kalshi-anchored “Reg Time: Brazil” withmarketSubtype=null), so no leg drops out as a standalone row. Mis-tagged props stay excluded (they are never_ml_-keyed).
Patchsdkhooksui
-
Add a
context: "list" | "detail"option togetVenueMarkets/useVenueMarketsand passcontext: "list"from the event tile’s market-scroll query. On list/tile surfaces, axis and dates events now sort their markets by lifetime volume (biggest market first) for both the embedded top-3 and the scroll-loaded tail, while the detail page keeps its structured order (threshold/date ascending).candidate/sportevents are unchanged.
Patchsdkhooksuiauth
- Improve live trading and resolved-market handling across the AGG React packages.
@agg-build/hooks- invalidate and optimistically refresh cached market, balance, position, and activity data when
market_resolvedWebSocket events arrive - export venue-attributed live best-price candidate helpers/hooks so UI surfaces can keep the displayed venue logo aligned with the freshest live price
- invalidate and optimistically refresh cached market, balance, position, and activity data when
@agg-build/ui- add shared claim-winnings and resolved-market claim hooks for resolved positions
- show the new resolved-market earnings/claim state in the event market flow
- add
onBeforePrimaryActionso partners can run a pre-submit gate before normal order execution - keep market detail outcome prices and venue logos in sync with live best-price updates
@agg-build/sdk- no direct SDK source or API changes landed in this push
- patch bump only to keep the linked public package versions aligned for release/publishing with the updated hooks and UI peers
Patchhooksui
-
Add provider-level AGG UI trading execution mode config.
AggProvidernow acceptsconfig.trading.executionModeso hosted UI surfaces can share a global live or paper trading mode without threadingexecutionModethrough every page or order panel.PlaceOrder,HomePage,EventMarketPage, andUserProfilePageuse the configured mode by default while preserving explicit component-level overrides. The shared balance provider now also uses the configured paper mode, soConnectButtonheader totals andUserProfilePagebalance/positions value cards read paper balances instead of falling back to live-mode zeroes. Paper balances are labeled as Paper in the user profile network breakdown, use a shared paper-mode icon, and show a tooltip warning when the app is running with simulated paper funds.
Minorsdkhooksui
-
Add safe midpoint batching for component-driven market pages.
AggClient.getMidpointsnow splits large/midpointsGET requests into smaller batches and merges the responses, defaulting to 75 venue market IDs per request to stay below common CDN URL limits. React hooks and UI components read the same default throughconfig.market.maxMidpointIdsPerRequest, and direct hook/SDK callers can override the cap when needed.
Majorsdkhooksuiauth
-
sdk, hooks: Narrow recurrence filters to the documented public cadence enum and expose the full supported venue-event cadence list through
RECURRENCE_CADENCES, includingPT10M,P1M, andP1Y. Migration guidance: replace dynamic recurrence-catalog calls with the SDKRECURRENCE_CADENCESexport or the OpenAPI enum. Pass the literal"null"only when filtering one-off venue events.listRecurringCryptoMarketsremains limited to deterministic crypto durations:PT5M,PT15M,PT1H, andP1D.
Minorsdkhooksui
- Frontend feature round-up since the last release: live arbitrage signals, nested category navigation, event-tile price gaps, paper-trading mode, and position/redeem fixes.
- Live arbitrage (
@agg-build/sdk,@agg-build/hooks,@agg-build/ui)- SDK added
subscribeArbandsubscribeArbFeed, with the supporting wire types (WsArbMarketUpdate,WsArbFeedBatch,WsArbFeedEntry), socket dispatch, reconnect, and refcount handling, and documented the new arb actions in theWsClientMessageunion. - Hooks added
useMarketArb(live per-market arb) anduseArbFeed(event-level MAX rollup), exported with theirUseMarketArbResult/UseArbFeedResulttypes. - UI brought back the arbitrage sort option and added event-list filters; event tiles and lists now surface arb-driven ordering.
- SDK added
- Nested categories (
@agg-build/hooks,@agg-build/ui)- Hooks added
useCategoryChildren(withUseCategoryChildrenOptions) for fetching subcategories. - UI renders the category
displayNameon home tabs and event-list filters, supports nested subcategories, andEventListPropsgainedonCategoryRootChange.HomePageCategorynow carries an optionaldisplayName.
- Hooks added
- Event-tile price gaps (
@agg-build/hooks,@agg-build/ui)- Hooks exported the
computePriceGapshelper plusMAX_PRICE_GAP_PCT/MIN_PRICE_GAP_PCTand theComputePriceGapsOptions/PriceGapValuetypes. - A new
enablePriceGapfeature flag andpriceGaplabel gate compact price-gap signals on aggregated event tiles; tiles wait for midpoints before computing gaps to avoid flicker.
- Hooks exported the
- Paper-trading mode (
@agg-build/sdk,@agg-build/hooks,@agg-build/ui)- SDK introduced the
ExecutionMode("live" | "paper") type and threaded an optionalmodethroughExecuteManagedParams, smart-route params, positions/orders queries, andManagedBalancesParams. - UI’s place-order panel accepts an
executionModeprop and reports the chosenmodeback throughonPrimaryAction.
- SDK introduced the
- Positions, redeem, and claim fixes (
@agg-build/hooks,@agg-build/ui)- Hooks exported
invalidateUserClaimStateand now walk the active bucket when counting redeem-eligible positions; auto-settled HL winners are reported as redeemed rather than ineligible. - UI user-profile tabs trust server-provided position buckets, redeem payout renders from the 6-decimal
totalPayoutRaw(no longer derived fromlegs[0]decimals), and a new partner-overridableclaimlabel group powers claim lifecycle notifications.
- Hooks exported
- Withdrawals & misc (
@agg-build/sdk,@agg-build/ui)- SDK added the
WithdrawalSourceTokenSymboltype to support pUSD withdrawal sources;WithdrawManagedSourceItem.tokenSymbolnow acceptspUSD. - UI event-list skeletons can render the discovery sidebar (
withSidebar), with refreshed event-tile coloring, volume sort, and updatedsort-volume-24hr/shield-trusticons.
- SDK added the
- Live arbitrage (
Patchsdk
- Add
email: string | nullto the typedaccounts.createdwebhook event payload so partners can read email addresses supplied by magic-link or OAuth sign-in.
Patchhooksui
-
Expand the trading labels surface with 9 new partner-overridable keys
for execution failure messaging (
sellNoOnchainPosition,venueQuoteUnfillable,venueMinOrderSize,sourceBalanceChanged,venueMarketResolved,dflowWalletUnverified,venueNoQuotePath,solanaBlockhashExpired,venueRateLimited,serviceBlockedOrder), and wire matching patterns intonormalizePlaceOrderErrorMessageso the SDK renders friendly copy for everyUserActionableStepErrorreason code the trade-executor now emits. Also rewrites the venue-terminated pattern coverage to handle Limitless’sFAILED/UNMATCHEDsettlement statuses with dedicated friendly copy ("Order didn't settle on-chain"and"No liquidity matched your order at the quoted price"), and extends the min-order-size pattern to recognize predict.fun’s existingpredict_min_quantityuser-actionable copy. - Centralize execution failure labels and clean up place-order error normalization for venue outages and expired submission deadlines.
Patchsdkhooksuiauth
- Deposit & withdraw UX overhaul:
- New
useWithdrawEstimatehook surfaces per-route fee and ETA estimates before submit. - Refreshed deposit and withdraw flows, including new amount/method/success screens, transfer fee summary, and friendly error states.
WithdrawManagedResponsenow exposescompletedAmountRaw, and the WSWithdrawalLifecycleEventincludesrequestedAmountRawandcompletedAmountRawso consumers can render the terminal settled amount.- New balance/activity invalidation helpers (
invalidateUserActivityQueries,invalidateUserMoneyState,userActivityQueryKeys) exported from@agg-build/hooks. - User profile activity rows and balance cards updated with refined states; new
spinnerandcircle-xmarkicons; tooltip primitive tweaks.
- New
Patchui
- Fix a bug in geo-blocking behavior for order splitting
Patchui
- UI updates for Positions tab and removed hardcoded colors
Patchui
- Added new prop in tooltip for gap and UI adjustments
Patchui
- Fix a bug in geo-blocking behavior for order splitting
Patchui
- UI updates in the withdraw modal and claim flow for design QA
Patchui
- Bug fix for nullable venueMarketOutcomeId
Patchui
- Bug fix for nullable venueMarketOutcomeId
- Update network chain logos to prediction-markets CDN paths; fix Solana missing from deposit modal network list
Patchui
- removed redundant div from venue selection
Patchui
- Sorting user positions
Patchui
- Market details UX updates
Minorsdkhooksuiauth
-
Added smart-route fee breakdown support across AGG packages.
@agg-build/sdknow includes optionalfeeBreakdowndata on smart-route quote responses so integrators can display venue fees, bridge fees, execution gas, and total fees.@agg-build/hooksaddsfeatures.showFeesBreakdownto UI config and new label keys for fees and updated positions table/status copy.@agg-build/uiadds optional fee breakdown display in the place-order flow, updates route ordering to prioritize better executable value, improves mobile event-market trade opening from outcome selection, and upgrades positions UX (active/closed filtering, status/result badges, and claim-state handling).
showFeesBreakdown).
Minorui
- Added xs size for icons and geo block updates for order
Patchhooksuiauth
-
Refresh published package metadata and fixes for the AGG SDK package stack.
Updates:
- @agg-build/hooks: fix midpoint price calculation in
useViewportMidpoints; minor adjustments to UI-config labels and theuseWithdrawFlowhook. - @agg-build/ui: settlement formatting refactor (new
settlement-text-renderer+settlement-text.utils);PlaceOrderflow updates including default amount, sell-tab default, partially-filled state, best-price wiring, max label, and a sign-in-to-trade flow; refreshed typography variants; newappsandcircle-overlapicons; customSelectmigration for TBAs; connect-button view rewrite; event-list search/filter improvements. - @agg-build/auth: updates to the SIWE adapter and shared auth utils.
- @agg-build/hooks: fix midpoint price calculation in
Patchsdkhooksui
-
sdk: Add withdrawal lifecycle WebSocket support — new
WsWithdrawalLifecycleEventmessage type,onWithdrawalLifecycleSDK callback, and associated types (WsWithdrawalLifecycleStatus,WsWithdrawalLegStatus,WsWithdrawalLifecycleLeg). hooks: AdduseWithdrawFlow,useWithdrawalLifecycle, anduseOnWithdrawalLifecyclehooks with full withdrawal lifecycle tracking via WebSocket. Fix live outcome price fallback so REST midpoints surface when no WS midpoint exists. ImproveuseMidpointsto prefer the venue with the lower YES midpoint for better buyer pricing. Fix hooks package exports to use format-specific type declarations (.d.mtsfor ESM consumers). ui: Add wallet withdrawal flow — recipient address input, amount/token/network selection, confirmation step, and an order-style execution timeline showing per-leg bridge/transfer progress with live lifecycle status. AddCopyButtonprimitive. Show wallet address on card-payment pending step in the deposit flow. Surface best-price venue indicators in the event list, market details, and orderbook. Fix cluster-aware market deduplication to collapse cross-page duplicates.
Majorsdkhooksuiauth
- Initial v1.0.0 release of the AGG client libraries on npm under the
@agg-buildscope.