@agg-build/ui 2.5.3 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/pages.mjs CHANGED
@@ -8,14 +8,14 @@ import {
8
8
  UserProfilePage,
9
9
  buildAggTxExplorerHref,
10
10
  useHomePageModals
11
- } from "./chunk-AELMIG74.mjs";
11
+ } from "./chunk-C247AYH7.mjs";
12
12
  import "./chunk-XAG432PJ.mjs";
13
13
  import {
14
14
  DEPOSIT_MODAL_OPEN_EVENT,
15
15
  WITHDRAW_MODAL_OPEN_EVENT,
16
16
  requestAggDepositModalOpen,
17
17
  requestAggWithdrawModalOpen
18
- } from "./chunk-FAU2VOL6.mjs";
18
+ } from "./chunk-O27JUYCF.mjs";
19
19
  import "./chunk-JQKJDSTW.mjs";
20
20
  import "./chunk-AHQA3B7D.mjs";
21
21
  import "./chunk-FMYYPNZZ.mjs";
package/dist/trading.js CHANGED
@@ -8467,7 +8467,7 @@ var buildLiveRouteCards = ({
8467
8467
  };
8468
8468
  }
8469
8469
  const avgPrice = sq.avgPrice;
8470
- const soloQuoteData = __spreadProps(__spreadValues({}, quoteData), {
8470
+ const soloQuoteData = __spreadValues(__spreadProps(__spreadValues({}, quoteData), {
8471
8471
  // Preview-only solos intentionally carry no executable quoteId; the card
8472
8472
  // should still render for comparison, while the CTA stays disabled until
8473
8473
  // the user is funded and requotes.
@@ -8480,7 +8480,7 @@ var buildLiveRouteCards = ({
8480
8480
  returnPct: sq.returnPct,
8481
8481
  // venueSoloQuotes stripped on solo card's quoteData (only the primary needs them)
8482
8482
  venueSoloQuotes: void 0
8483
- });
8483
+ }), sq.quoteId ? { status: "ok", error: void 0 } : null);
8484
8484
  return {
8485
8485
  id: `live-solo-${sq.venue}`,
8486
8486
  hint: labels.averagePrice(avgPrice),
@@ -8536,6 +8536,17 @@ var buildLiveRouteCards = ({
8536
8536
  })() : [];
8537
8537
  return [...baseCards, ...unavailableCards, ...warningOnlyUnavailableCards];
8538
8538
  };
8539
+ var resolveDefaultRouteCardId = (routeCards, primaryStatus) => {
8540
+ var _a, _b, _c, _d;
8541
+ if (routeCards.length === 0) return null;
8542
+ if (primaryStatus === "insufficient_balance") {
8543
+ const executableCard = routeCards.find(
8544
+ (card) => !card.isUnavailable && card.quoteData.status === "ok" && card.quoteData.quoteId
8545
+ );
8546
+ if (executableCard) return executableCard.id;
8547
+ }
8548
+ return (_d = (_c = (_a = routeCards.find((card) => !card.isUnavailable)) == null ? void 0 : _a.id) != null ? _c : (_b = routeCards[0]) == null ? void 0 : _b.id) != null ? _d : null;
8549
+ };
8539
8550
  var sellSharesToAtomicUnits = (shares) => {
8540
8551
  if (!Number.isFinite(shares) || shares <= 0) return BigInt(0);
8541
8552
  const [whole = "0", fraction = ""] = shares.toFixed(12).split(".");
@@ -10470,7 +10481,7 @@ var PlaceOrder = ({
10470
10481
  resolvedClaim,
10471
10482
  midpointsResult
10472
10483
  }) => {
10473
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X;
10484
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y;
10474
10485
  const {
10475
10486
  enableDebug: isExecutionDebugEnabled,
10476
10487
  features: { enableAnimations, showFeesBreakdown, showLimitOrders },
@@ -10901,13 +10912,13 @@ var PlaceOrder = ({
10901
10912
  venueSellQuotes.quotes
10902
10913
  ]);
10903
10914
  const resolvedSelectedRouteCardId = (0, import_react15.useMemo)(() => {
10904
- var _a2, _b2, _c2, _d2;
10915
+ var _a2;
10905
10916
  if (routeCards.length === 0) return null;
10906
10917
  if (selectedRouteCardId && routeCards.some((card) => card.id === selectedRouteCardId && !card.isUnavailable)) {
10907
10918
  return selectedRouteCardId;
10908
10919
  }
10909
- return (_d2 = (_c2 = (_a2 = routeCards.find((card) => !card.isUnavailable)) == null ? void 0 : _a2.id) != null ? _c2 : (_b2 = routeCards[0]) == null ? void 0 : _b2.id) != null ? _d2 : null;
10910
- }, [routeCards, selectedRouteCardId]);
10920
+ return resolveDefaultRouteCardId(routeCards, isSell ? void 0 : (_a2 = smartRoute.data) == null ? void 0 : _a2.status);
10921
+ }, [routeCards, selectedRouteCardId, isSell, (_w = smartRoute.data) == null ? void 0 : _w.status]);
10911
10922
  (0, import_react15.useEffect)(() => {
10912
10923
  if (routeCards.length === 0) {
10913
10924
  setSelectedRouteCardId(null);
@@ -10947,14 +10958,14 @@ var PlaceOrder = ({
10947
10958
  setLimitPriceInputError(null);
10948
10959
  }, [executionType, scopedSelectedOutcomeId, selectedOutcomeDisplayPrice]);
10949
10960
  const orderedRouteCards = routeCards;
10950
- const selectedRouteCard = (_x = (_w = orderedRouteCards.find((card) => card.id === resolvedSelectedRouteCardId)) != null ? _w : orderedRouteCards[0]) != null ? _x : null;
10961
+ const selectedRouteCard = (_y = (_x = orderedRouteCards.find((card) => card.id === resolvedSelectedRouteCardId)) != null ? _x : orderedRouteCards[0]) != null ? _y : null;
10951
10962
  const isKalshiRoute = (0, import_react15.useMemo)(() => {
10952
10963
  if (selectedRouteCard) {
10953
10964
  return selectedRouteCard.venue === "kalshi" || selectedRouteCard.quoteData.fills.some((f) => f.venue === "kalshi");
10954
10965
  }
10955
10966
  return (scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.venue) === "kalshi";
10956
10967
  }, [selectedRouteCard, scopedSelectedMarket]);
10957
- const displayedBalance = isPaperMode ? paperTotalBalance : isKalshiRoute ? (_y = liveBalanceState.kalshiBalance) != null ? _y : 0 : liveAvailableBalance;
10968
+ const displayedBalance = isPaperMode ? paperTotalBalance : isKalshiRoute ? (_z = liveBalanceState.kalshiBalance) != null ? _z : 0 : liveAvailableBalance;
10958
10969
  const legacyKalshiAccount = (0, import_react15.useMemo)(
10959
10970
  () => {
10960
10971
  var _a2;
@@ -10962,8 +10973,8 @@ var PlaceOrder = ({
10962
10973
  },
10963
10974
  [user == null ? void 0 : user.venueAccounts]
10964
10975
  );
10965
- const isKalshiAccountActive = (_z = kalshiKeyStatus == null ? void 0 : kalshiKeyStatus.connected) != null ? _z : (legacyKalshiAccount == null ? void 0 : legacyKalshiAccount.status) === "active";
10966
- const isKalshiVerified = ((_A = kalshiKeyStatus == null ? void 0 : kalshiKeyStatus.kycStatus) != null ? _A : legacyKalshiAccount == null ? void 0 : legacyKalshiAccount.kycStatus) === "verified";
10976
+ const isKalshiAccountActive = (_A = kalshiKeyStatus == null ? void 0 : kalshiKeyStatus.connected) != null ? _A : (legacyKalshiAccount == null ? void 0 : legacyKalshiAccount.status) === "active";
10977
+ const isKalshiVerified = ((_B = kalshiKeyStatus == null ? void 0 : kalshiKeyStatus.kycStatus) != null ? _B : legacyKalshiAccount == null ? void 0 : legacyKalshiAccount.kycStatus) === "verified";
10967
10978
  const hasKalshiConnectionState = kalshiKeyStatus !== void 0 || (user == null ? void 0 : user.venueAccounts) != null;
10968
10979
  const isKalshiAvailable = (0, import_hooks36.getVenueAvailabilityState)({
10969
10980
  venueId: "kalshi",
@@ -10990,7 +11001,7 @@ var PlaceOrder = ({
10990
11001
  [aggClient, onConnectKalshi, refetchKalshiKeyStatus]
10991
11002
  );
10992
11003
  const needsKycVerification = isAuthenticated && hasKalshiConnectionState && isKalshiRoute && isKalshiAccountActive && !isKalshiVerified;
10993
- const verifyKalshiConnectionLabel = (_E = (_D = (_C = (_B = labels.onboarding) == null ? void 0 : _B.connectKalshiModal) == null ? void 0 : _C.actions) == null ? void 0 : _D.verifyConnection) != null ? _E : tradingLabels.kycRequired;
11004
+ const verifyKalshiConnectionLabel = (_F = (_E = (_D = (_C = labels.onboarding) == null ? void 0 : _C.connectKalshiModal) == null ? void 0 : _D.actions) == null ? void 0 : _E.verifyConnection) != null ? _F : tradingLabels.kycRequired;
10994
11005
  const handleRouteCardSelect = (0, import_react15.useCallback)(
10995
11006
  (cardId) => {
10996
11007
  if (cardId === resolvedSelectedRouteCardId) {
@@ -11005,15 +11016,15 @@ var PlaceOrder = ({
11005
11016
  [resolvedSelectedRouteCardId, routeCards]
11006
11017
  );
11007
11018
  const executionProgress = (0, import_hooks36.useExecutionProgress)({
11008
- orderIds: (_F = submissionProgressState == null ? void 0 : submissionProgressState.orderIds) != null ? _F : null,
11009
- quoteId: (_G = submissionProgressState == null ? void 0 : submissionProgressState.quoteId) != null ? _G : null,
11019
+ orderIds: (_G = submissionProgressState == null ? void 0 : submissionProgressState.orderIds) != null ? _G : null,
11020
+ quoteId: (_H = submissionProgressState == null ? void 0 : submissionProgressState.quoteId) != null ? _H : null,
11010
11021
  mode: isPaperMode ? "paper" : void 0,
11011
- enabled: ((submissionProgressState == null ? void 0 : submissionProgressState.phase) === "submitting" || (submissionProgressState == null ? void 0 : submissionProgressState.phase) === "executing") && !!((_H = submissionProgressState == null ? void 0 : submissionProgressState.orderIds) == null ? void 0 : _H.length)
11022
+ enabled: ((submissionProgressState == null ? void 0 : submissionProgressState.phase) === "submitting" || (submissionProgressState == null ? void 0 : submissionProgressState.phase) === "executing") && !!((_I = submissionProgressState == null ? void 0 : submissionProgressState.orderIds) == null ? void 0 : _I.length)
11012
11023
  });
11013
- const selectedOutcomeLabel = (_K = (_J = (_I = outcomes.find((outcome) => outcome.id === scopedSelectedOutcomeId)) == null ? void 0 : _I.label) != null ? _J : scopedSelectedOutcome == null ? void 0 : scopedSelectedOutcome.label) != null ? _K : "";
11014
- const headerImage = (_M = (_L = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.image) != null ? _L : scopedSelectedEvent == null ? void 0 : scopedSelectedEvent.image) != null ? _M : null;
11015
- const headerTitle = (_O = (_N = scopedSelectedEvent == null ? void 0 : scopedSelectedEvent.title) != null ? _N : scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.question) != null ? _O : "";
11016
- const headerSubtitle = (_P = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.question) != null ? _P : "";
11024
+ const selectedOutcomeLabel = (_L = (_K = (_J = outcomes.find((outcome) => outcome.id === scopedSelectedOutcomeId)) == null ? void 0 : _J.label) != null ? _K : scopedSelectedOutcome == null ? void 0 : scopedSelectedOutcome.label) != null ? _L : "";
11025
+ const headerImage = (_N = (_M = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.image) != null ? _M : scopedSelectedEvent == null ? void 0 : scopedSelectedEvent.image) != null ? _N : null;
11026
+ const headerTitle = (_P = (_O = scopedSelectedEvent == null ? void 0 : scopedSelectedEvent.title) != null ? _O : scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.question) != null ? _P : "";
11027
+ const headerSubtitle = (_Q = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.question) != null ? _Q : "";
11017
11028
  const buildExecutionSummary = (0, import_react15.useCallback)(
11018
11029
  (quoteData, executionVenue, orderId, partialFillSummary) => {
11019
11030
  var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2;
@@ -11311,19 +11322,19 @@ var PlaceOrder = ({
11311
11322
  queryClient,
11312
11323
  submissionProgressState
11313
11324
  ]);
11314
- const activeQuoteData = (_R = (_Q = selectedRouteCard == null ? void 0 : selectedRouteCard.quoteData) != null ? _Q : smartRoute.data) != null ? _R : null;
11325
+ const activeQuoteData = (_S = (_R = selectedRouteCard == null ? void 0 : selectedRouteCard.quoteData) != null ? _R : smartRoute.data) != null ? _S : null;
11315
11326
  const visibleRouteCards = orderedRouteCards.length > PLACE_ORDER_ROUTE_COLLAPSED_CARD_COUNT && !isRoutesExpanded ? orderedRouteCards.slice(0, PLACE_ORDER_ROUTE_COLLAPSED_CARD_COUNT) : orderedRouteCards;
11316
11327
  const hasEnteredAmount = internalAmount > 0;
11317
11328
  const isQuoteLoading = !isLimitOrder && hasEnteredAmount && (smartRoute.isFetching || smartRoute.isLoading || isSell && (venueSellQuotes.isFetching || venueSellQuotes.isLoading));
11318
11329
  const routeLoadingMessage = isQuoteLoading ? smartRoute.loadingReason === "updating-route" ? tradingLabels.updatingRoute : smartRoute.loadingReason === "refreshing-quotes" ? tradingLabels.refreshingQuotes : tradingLabels.findingBestOdds : null;
11319
- const selectedRouteFills = (_S = selectedRouteCard == null ? void 0 : selectedRouteCard.quoteData.fills) != null ? _S : [];
11330
+ const selectedRouteFills = (_T = selectedRouteCard == null ? void 0 : selectedRouteCard.quoteData.fills) != null ? _T : [];
11320
11331
  const isKalshiOnlyRoute = isKalshiRoute && ((selectedRouteCard == null ? void 0 : selectedRouteCard.venue) === import_sdk17.Venue.kalshi || selectedRouteFills.length > 0 && selectedRouteFills.every((fill) => fill.venue === import_sdk17.Venue.kalshi));
11321
11332
  const isOnchainOnlyRoute = !isKalshiRoute || selectedRouteFills.length > 0 && selectedRouteFills.every((fill) => fill.venue !== import_sdk17.Venue.kalshi);
11322
11333
  const kalshiRequiredAmount = isSell ? 0 : selectedRouteFills.filter((fill) => fill.venue === import_sdk17.Venue.kalshi).reduce((total, fill) => total + fill.venueQty * fill.avgPrice, 0);
11323
11334
  const onchainRequiredAmount = isSell ? 0 : selectedRouteFills.filter((fill) => fill.venue !== import_sdk17.Venue.kalshi).reduce((total, fill) => total + fill.venueQty * fill.avgPrice, 0);
11324
11335
  const resolvedKalshiRequiredAmount = isKalshiOnlyRoute || isKalshiRoute && selectedRouteFills.length === 0 ? internalAmount : kalshiRequiredAmount;
11325
11336
  const resolvedOnchainRequiredAmount = isOnchainOnlyRoute || !isKalshiRoute && selectedRouteFills.length === 0 ? internalAmount : onchainRequiredAmount;
11326
- const isKalshiBalanceInsufficient = !isPaperMode && isKalshiRoute && resolvedKalshiRequiredAmount > ((_T = liveBalanceState.kalshiBalance) != null ? _T : 0);
11337
+ const isKalshiBalanceInsufficient = !isPaperMode && isKalshiRoute && resolvedKalshiRequiredAmount > ((_U = liveBalanceState.kalshiBalance) != null ? _U : 0);
11327
11338
  const isOnchainBalanceInsufficient = resolvedOnchainRequiredAmount > liveAvailableBalance;
11328
11339
  const isInsufficientBalance = !isSell && isAuthenticated && hasEnteredAmount && !isBalanceLoading && (isLimitOrder ? internalAmount > totalBalance : isPaperMode ? internalAmount > paperTotalBalance : isKalshiBalanceInsufficient || isOnchainBalanceInsufficient);
11329
11340
  const isQuoteInsufficientBalance = !isLimitOrder && (activeQuoteData == null ? void 0 : activeQuoteData.status) === "insufficient_balance";
@@ -11417,7 +11428,7 @@ var PlaceOrder = ({
11417
11428
  }
11418
11429
  return (_d2 = selectedRouteCard.hint) != null ? _d2 : "";
11419
11430
  }, [selectedRouteCard, tradingLabels]);
11420
- const displayedToWinValue = (_U = selectedRouteCard == null ? void 0 : selectedRouteCard.numericValue) != null ? _U : 0;
11431
+ const displayedToWinValue = (_V = selectedRouteCard == null ? void 0 : selectedRouteCard.numericValue) != null ? _V : 0;
11421
11432
  const limitOrderPayload = (0, import_react15.useMemo)(() => {
11422
11433
  if (!scopedSelectedMarket || !scopedSelectedOutcomeId || internalAmount <= 0) return null;
11423
11434
  if (limitPriceInputError) return null;
@@ -11536,13 +11547,13 @@ var PlaceOrder = ({
11536
11547
  ];
11537
11548
  }, [activeFeeBreakdown, tradingLabels]);
11538
11549
  const isActionLoading = isPrimaryActionLoading || executeManaged.isPending || placeLimitOrder.isPending || isBeforeActionPending;
11539
- const selectedRouteGeoBlocked = (_V = selectedRouteCard == null ? void 0 : selectedRouteCard.isUnavailable) != null ? _V : false;
11550
+ const selectedRouteGeoBlocked = (_W = selectedRouteCard == null ? void 0 : selectedRouteCard.isUnavailable) != null ? _W : false;
11540
11551
  const geoBlockedVenuesFromWarnings = (0, import_react15.useMemo)(
11541
11552
  () => {
11542
11553
  var _a2;
11543
11554
  return extractGeoBlockedVenues((_a2 = smartRoute.data) == null ? void 0 : _a2.warnings);
11544
11555
  },
11545
- [(_W = smartRoute.data) == null ? void 0 : _W.warnings]
11556
+ [(_X = smartRoute.data) == null ? void 0 : _X.warnings]
11546
11557
  );
11547
11558
  const isPrimaryVenueGeoBlocked = (0, import_react15.useMemo)(() => {
11548
11559
  var _a2, _b2;
@@ -12200,7 +12211,7 @@ var PlaceOrder = ({
12200
12211
  PlaceOrderResolvedView,
12201
12212
  {
12202
12213
  tradingState: resolvedReadOnlyTradingState,
12203
- resolutionTimestamp: (_X = resolvedEventTradingState.resolvesAt) != null ? _X : resolvedReadOnlyTradingState.resolvesAt,
12214
+ resolutionTimestamp: (_Y = resolvedEventTradingState.resolvesAt) != null ? _Y : resolvedReadOnlyTradingState.resolvesAt,
12204
12215
  resolvedClaim,
12205
12216
  classNames,
12206
12217
  className,
package/dist/trading.mjs CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  parseVenue,
10
10
  useClaimWinnings,
11
11
  useResolvedMarketClaim
12
- } from "./chunk-FAU2VOL6.mjs";
12
+ } from "./chunk-O27JUYCF.mjs";
13
13
  import {
14
14
  SETTLEMENT_SECTION_ID,
15
15
  Settlement,
@@ -1,12 +1,12 @@
1
1
  import { type VenueEventWithMarkets, type VenueMarket } from "@agg-build/hooks";
2
2
  export declare const sportsSectionMarketsByTab: {
3
3
  game_lines: VenueMarket[];
4
- halves: readonly [VenueMarket, VenueMarket, VenueMarket];
4
+ "period:halves": readonly [VenueMarket, VenueMarket, VenueMarket];
5
5
  exact_score: readonly [VenueMarket];
6
- corners: readonly [VenueMarket, VenueMarket];
7
- goals: VenueMarket[];
8
- assists: readonly [VenueMarket];
9
- shots: readonly [VenueMarket];
6
+ "stat:corners": readonly [VenueMarket, VenueMarket];
7
+ "stat:goals": VenueMarket[];
8
+ "stat:assists": readonly [VenueMarket];
9
+ "stat:shots": readonly [VenueMarket];
10
10
  other: readonly [VenueMarket];
11
11
  };
12
12
  export declare const sportsEventPageFixture: VenueEventWithMarkets;
@@ -1,12 +1,12 @@
1
1
  import { type VenueEventWithMarkets, type VenueMarket } from "@agg-build/hooks";
2
2
  export declare const sportsSectionMarketsByTab: {
3
3
  game_lines: VenueMarket[];
4
- halves: readonly [VenueMarket, VenueMarket, VenueMarket];
4
+ "period:halves": readonly [VenueMarket, VenueMarket, VenueMarket];
5
5
  exact_score: readonly [VenueMarket];
6
- corners: readonly [VenueMarket, VenueMarket];
7
- goals: VenueMarket[];
8
- assists: readonly [VenueMarket];
9
- shots: readonly [VenueMarket];
6
+ "stat:corners": readonly [VenueMarket, VenueMarket];
7
+ "stat:goals": VenueMarket[];
8
+ "stat:assists": readonly [VenueMarket];
9
+ "stat:shots": readonly [VenueMarket];
10
10
  other: readonly [VenueMarket];
11
11
  };
12
12
  export declare const sportsEventPageFixture: VenueEventWithMarkets;
@@ -1,6 +1,4 @@
1
1
  import type { VenueEventWithMarkets, VenueMarket } from "@agg-build/hooks";
2
- export declare const SPORTS_SECTION_TAB_KEYS: readonly ["game_lines", "halves", "exact_score", "corners", "goals", "assists", "shots", "other"];
3
- export type SportsSectionTabKey = (typeof SPORTS_SECTION_TAB_KEYS)[number];
4
2
  export declare const SPORTS_MARKET_TYPE_KEYS: readonly ["to_advance", "moneyline", "spread", "total", "prop", "completion", "other"];
5
3
  export type SportsMarketTypeKey = (typeof SPORTS_MARKET_TYPE_KEYS)[number];
6
4
  export declare const SPORTS_PERIOD_KEYS: readonly ["full", "1h", "2h", "q1", "q2", "q3", "q4", "ot", "first_inning", "second_inning", "third_inning", "first_5_innings", "other"];
@@ -17,41 +15,18 @@ export declare const SPORTS_MARKET_CATEGORY_KEYS: readonly ["game_lines", "exact
17
15
  export type SportsMarketCategoryKey = (typeof SPORTS_MARKET_CATEGORY_KEYS)[number];
18
16
  export declare const SPORTS_MARKET_GROUP_KEYS: readonly ["game_lines", "spreads", "totals", "period_lines", "exact_score", "team_props", "player_props", "specials", "completion", "other"];
19
17
  export type SportsMarketGroupKey = (typeof SPORTS_MARKET_GROUP_KEYS)[number];
20
- export type SportsSectionTabDefinition = {
21
- key: SportsSectionTabKey;
22
- /** Preferred section filter — supersedes `marketCategory`. */
23
- marketGroup?: readonly SportsMarketGroupKey[];
24
- /** Legacy compatibility filter (soccer prop tabs without a marketGroup). */
25
- marketCategory?: SportsMarketCategoryKey;
26
- sportsMarketType?: readonly SportsMarketTypeKey[];
27
- period?: readonly SportsPeriodKey[];
18
+ export type SportsSectionTabKind = "game_lines" | "period" | "stat" | "exact_score" | "other";
19
+ export type SportsSectionTab = {
20
+ /** Stable key: "game_lines" | "exact_score" | "other" | `period:<family>` | `stat:<token>` */
21
+ key: string;
22
+ kind: SportsSectionTabKind;
23
+ /** kind="period": the family this tab covers (e.g. "halves", "first_5_innings"). */
24
+ periodFamily?: string;
25
+ /** kind="period": every period in the family that this game actually has. */
26
+ periods?: readonly SportsPeriodKey[];
27
+ /** kind="stat": the stat token, e.g. "home_runs". "player_props" = the catch-all. */
28
+ stat?: string;
28
29
  };
29
- export declare const SPORTS_SECTION_TAB_DEFINITIONS: readonly [{
30
- readonly key: "game_lines";
31
- readonly marketGroup: readonly ["game_lines", "spreads", "totals"];
32
- }, {
33
- readonly key: "exact_score";
34
- readonly marketGroup: readonly ["exact_score"];
35
- }, {
36
- readonly key: "halves";
37
- readonly marketGroup: readonly ["period_lines"];
38
- readonly period: readonly ["1h", "2h"];
39
- }, {
40
- readonly key: "corners";
41
- readonly marketCategory: "corners";
42
- }, {
43
- readonly key: "goals";
44
- readonly marketCategory: "goals";
45
- }, {
46
- readonly key: "assists";
47
- readonly marketCategory: "assists";
48
- }, {
49
- readonly key: "shots";
50
- readonly marketCategory: "shots";
51
- }, {
52
- readonly key: "other";
53
- readonly marketGroup: readonly ["other", "team_props", "specials", "completion"];
54
- }];
55
30
  export type SportsMarketCardVariant = "outcome" | "line" | "yes_no";
56
31
  export type SportsMarketDisplayGroup = {
57
32
  id: string;
@@ -69,11 +44,27 @@ export type SportsPeriodGroup = {
69
44
  markets: VenueMarket[];
70
45
  groups: SportsMarketDisplayGroup[];
71
46
  };
72
- export declare const resolveSportsSectionDefinition: (key: SportsSectionTabKey) => SportsSectionTabDefinition;
47
+ /**
48
+ * Collapse a period into its display FAMILY, so one tab covers the periods a
49
+ * viewer thinks of together: soccer's 1h+2h are a single "Halves" tab (as
50
+ * today), basketball's q1–q4 a single "Quarters" tab, while baseball's
51
+ * `first_5_innings` stands alone and reads "5 Innings" like Polymarket.
52
+ */
53
+ export declare const resolveSportsPeriodFamily: (period: SportsPeriodKey) => string;
73
54
  export declare const normalizeSportsPeriod: (value: string | null | undefined) => SportsPeriodKey;
74
55
  export declare const normalizeSportsMarketType: (value: string | null | undefined) => SportsMarketTypeKey | null;
75
56
  export declare const normalizeSportsMarketCategory: (value: string | null | undefined) => SportsMarketCategoryKey | null;
76
57
  export declare const normalizeSportsMarketGroup: (value: string | null | undefined) => SportsMarketGroupKey | null;
58
+ /**
59
+ * The stat a player prop measures, as a bare token ("home_runs").
60
+ *
61
+ * Primary source is `marketSubtype`, which both Polymarket and (since the
62
+ * kalshi series-suffix mapping) Kalshi spell identically —
63
+ * `baseball_player_home_runs` on both — so one tab holds both venues' markets.
64
+ * Falls back to `marketCategory` for soccer's legacy corners/goals/assists/
65
+ * shots, which have no player subtype. Null when neither resolves.
66
+ */
67
+ export declare const resolveSportsStatToken: (market: Pick<VenueMarket, "marketSubtype" | "marketCategory" | "question">) => string | null;
77
68
  /**
78
69
  * Map a market to the sports section tab it belongs to — marketGroup-first, with
79
70
  * marketCategory as the documented compatibility fallback (see the
@@ -81,15 +72,16 @@ export declare const normalizeSportsMarketGroup: (value: string | null | undefin
81
72
  * recognizable grouping metadata, so the page can fall back to the default,
82
73
  * ungrouped market list instead of inventing an empty tab.
83
74
  */
84
- export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question" | "sportsMarketType">) => SportsSectionTabKey | null;
85
- export declare const resolveSportsSectionFilters: (key: SportsSectionTabKey) => {
75
+ export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question" | "sportsMarketType" | "period">) => string | null;
76
+ export declare const resolveVisibleSportsSectionTabs: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => SportsSectionTab[];
77
+ export declare const resolveSportsSectionFilters: (tab: SportsSectionTab) => {
86
78
  marketGroup?: SportsMarketGroupKey[];
87
79
  marketCategory?: SportsMarketCategoryKey[];
88
80
  sportsMarketType?: SportsMarketTypeKey[];
89
81
  period?: SportsPeriodKey[];
90
82
  };
91
- export declare const resolveSportsSectionMarkets: ({ tabKey, eventMarkets, sectionMarkets, }: {
92
- tabKey: SportsSectionTabKey;
83
+ export declare const resolveSportsSectionMarkets: ({ tab, eventMarkets, sectionMarkets, }: {
84
+ tab: SportsSectionTab;
93
85
  eventMarkets: VenueMarket[];
94
86
  sectionMarkets: VenueMarket[];
95
87
  }) => VenueMarket[];
@@ -173,8 +165,7 @@ export declare const resolveSportsLeagueLabel: (event: Pick<VenueEventWithMarket
173
165
  */
174
166
  export declare const formatSportsPeriodGrammarLabel: (period: string) => string | null;
175
167
  export declare const isNonStandardSportsLikeEvent: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => boolean;
176
- export declare const resolveVisibleSportsSectionTabDefinitions: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => SportsSectionTabDefinition[];
177
168
  export declare const mergeSportsSectionMarketsIntoEvent: ({ event, sectionMarketsByKey, }: {
178
169
  event: import("@agg-build/hooks").VenueEventWithMarkets;
179
- sectionMarketsByKey: Partial<Record<SportsSectionTabKey, VenueMarket[]>>;
170
+ sectionMarketsByKey: Partial<Record<string, VenueMarket[]>>;
180
171
  }) => import("@agg-build/hooks").VenueEventWithMarkets;
@@ -1,6 +1,4 @@
1
1
  import type { VenueEventWithMarkets, VenueMarket } from "@agg-build/hooks";
2
- export declare const SPORTS_SECTION_TAB_KEYS: readonly ["game_lines", "halves", "exact_score", "corners", "goals", "assists", "shots", "other"];
3
- export type SportsSectionTabKey = (typeof SPORTS_SECTION_TAB_KEYS)[number];
4
2
  export declare const SPORTS_MARKET_TYPE_KEYS: readonly ["to_advance", "moneyline", "spread", "total", "prop", "completion", "other"];
5
3
  export type SportsMarketTypeKey = (typeof SPORTS_MARKET_TYPE_KEYS)[number];
6
4
  export declare const SPORTS_PERIOD_KEYS: readonly ["full", "1h", "2h", "q1", "q2", "q3", "q4", "ot", "first_inning", "second_inning", "third_inning", "first_5_innings", "other"];
@@ -17,41 +15,18 @@ export declare const SPORTS_MARKET_CATEGORY_KEYS: readonly ["game_lines", "exact
17
15
  export type SportsMarketCategoryKey = (typeof SPORTS_MARKET_CATEGORY_KEYS)[number];
18
16
  export declare const SPORTS_MARKET_GROUP_KEYS: readonly ["game_lines", "spreads", "totals", "period_lines", "exact_score", "team_props", "player_props", "specials", "completion", "other"];
19
17
  export type SportsMarketGroupKey = (typeof SPORTS_MARKET_GROUP_KEYS)[number];
20
- export type SportsSectionTabDefinition = {
21
- key: SportsSectionTabKey;
22
- /** Preferred section filter — supersedes `marketCategory`. */
23
- marketGroup?: readonly SportsMarketGroupKey[];
24
- /** Legacy compatibility filter (soccer prop tabs without a marketGroup). */
25
- marketCategory?: SportsMarketCategoryKey;
26
- sportsMarketType?: readonly SportsMarketTypeKey[];
27
- period?: readonly SportsPeriodKey[];
18
+ export type SportsSectionTabKind = "game_lines" | "period" | "stat" | "exact_score" | "other";
19
+ export type SportsSectionTab = {
20
+ /** Stable key: "game_lines" | "exact_score" | "other" | `period:<family>` | `stat:<token>` */
21
+ key: string;
22
+ kind: SportsSectionTabKind;
23
+ /** kind="period": the family this tab covers (e.g. "halves", "first_5_innings"). */
24
+ periodFamily?: string;
25
+ /** kind="period": every period in the family that this game actually has. */
26
+ periods?: readonly SportsPeriodKey[];
27
+ /** kind="stat": the stat token, e.g. "home_runs". "player_props" = the catch-all. */
28
+ stat?: string;
28
29
  };
29
- export declare const SPORTS_SECTION_TAB_DEFINITIONS: readonly [{
30
- readonly key: "game_lines";
31
- readonly marketGroup: readonly ["game_lines", "spreads", "totals"];
32
- }, {
33
- readonly key: "exact_score";
34
- readonly marketGroup: readonly ["exact_score"];
35
- }, {
36
- readonly key: "halves";
37
- readonly marketGroup: readonly ["period_lines"];
38
- readonly period: readonly ["1h", "2h"];
39
- }, {
40
- readonly key: "corners";
41
- readonly marketCategory: "corners";
42
- }, {
43
- readonly key: "goals";
44
- readonly marketCategory: "goals";
45
- }, {
46
- readonly key: "assists";
47
- readonly marketCategory: "assists";
48
- }, {
49
- readonly key: "shots";
50
- readonly marketCategory: "shots";
51
- }, {
52
- readonly key: "other";
53
- readonly marketGroup: readonly ["other", "team_props", "specials", "completion"];
54
- }];
55
30
  export type SportsMarketCardVariant = "outcome" | "line" | "yes_no";
56
31
  export type SportsMarketDisplayGroup = {
57
32
  id: string;
@@ -69,11 +44,27 @@ export type SportsPeriodGroup = {
69
44
  markets: VenueMarket[];
70
45
  groups: SportsMarketDisplayGroup[];
71
46
  };
72
- export declare const resolveSportsSectionDefinition: (key: SportsSectionTabKey) => SportsSectionTabDefinition;
47
+ /**
48
+ * Collapse a period into its display FAMILY, so one tab covers the periods a
49
+ * viewer thinks of together: soccer's 1h+2h are a single "Halves" tab (as
50
+ * today), basketball's q1–q4 a single "Quarters" tab, while baseball's
51
+ * `first_5_innings` stands alone and reads "5 Innings" like Polymarket.
52
+ */
53
+ export declare const resolveSportsPeriodFamily: (period: SportsPeriodKey) => string;
73
54
  export declare const normalizeSportsPeriod: (value: string | null | undefined) => SportsPeriodKey;
74
55
  export declare const normalizeSportsMarketType: (value: string | null | undefined) => SportsMarketTypeKey | null;
75
56
  export declare const normalizeSportsMarketCategory: (value: string | null | undefined) => SportsMarketCategoryKey | null;
76
57
  export declare const normalizeSportsMarketGroup: (value: string | null | undefined) => SportsMarketGroupKey | null;
58
+ /**
59
+ * The stat a player prop measures, as a bare token ("home_runs").
60
+ *
61
+ * Primary source is `marketSubtype`, which both Polymarket and (since the
62
+ * kalshi series-suffix mapping) Kalshi spell identically —
63
+ * `baseball_player_home_runs` on both — so one tab holds both venues' markets.
64
+ * Falls back to `marketCategory` for soccer's legacy corners/goals/assists/
65
+ * shots, which have no player subtype. Null when neither resolves.
66
+ */
67
+ export declare const resolveSportsStatToken: (market: Pick<VenueMarket, "marketSubtype" | "marketCategory" | "question">) => string | null;
77
68
  /**
78
69
  * Map a market to the sports section tab it belongs to — marketGroup-first, with
79
70
  * marketCategory as the documented compatibility fallback (see the
@@ -81,15 +72,16 @@ export declare const normalizeSportsMarketGroup: (value: string | null | undefin
81
72
  * recognizable grouping metadata, so the page can fall back to the default,
82
73
  * ungrouped market list instead of inventing an empty tab.
83
74
  */
84
- export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question" | "sportsMarketType">) => SportsSectionTabKey | null;
85
- export declare const resolveSportsSectionFilters: (key: SportsSectionTabKey) => {
75
+ export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question" | "sportsMarketType" | "period">) => string | null;
76
+ export declare const resolveVisibleSportsSectionTabs: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => SportsSectionTab[];
77
+ export declare const resolveSportsSectionFilters: (tab: SportsSectionTab) => {
86
78
  marketGroup?: SportsMarketGroupKey[];
87
79
  marketCategory?: SportsMarketCategoryKey[];
88
80
  sportsMarketType?: SportsMarketTypeKey[];
89
81
  period?: SportsPeriodKey[];
90
82
  };
91
- export declare const resolveSportsSectionMarkets: ({ tabKey, eventMarkets, sectionMarkets, }: {
92
- tabKey: SportsSectionTabKey;
83
+ export declare const resolveSportsSectionMarkets: ({ tab, eventMarkets, sectionMarkets, }: {
84
+ tab: SportsSectionTab;
93
85
  eventMarkets: VenueMarket[];
94
86
  sectionMarkets: VenueMarket[];
95
87
  }) => VenueMarket[];
@@ -173,8 +165,7 @@ export declare const resolveSportsLeagueLabel: (event: Pick<VenueEventWithMarket
173
165
  */
174
166
  export declare const formatSportsPeriodGrammarLabel: (period: string) => string | null;
175
167
  export declare const isNonStandardSportsLikeEvent: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => boolean;
176
- export declare const resolveVisibleSportsSectionTabDefinitions: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => SportsSectionTabDefinition[];
177
168
  export declare const mergeSportsSectionMarketsIntoEvent: ({ event, sectionMarketsByKey, }: {
178
169
  event: import("@agg-build/hooks").VenueEventWithMarkets;
179
- sectionMarketsByKey: Partial<Record<SportsSectionTabKey, VenueMarket[]>>;
170
+ sectionMarketsByKey: Partial<Record<string, VenueMarket[]>>;
180
171
  }) => import("@agg-build/hooks").VenueEventWithMarkets;
@@ -1,8 +1,7 @@
1
1
  import { type UseMidpointsResult, type VenueEventWithMarkets, type VenueMarket } from "@agg-build/hooks";
2
- import { type SportsSectionTabKey } from "./sports-event-market.utils";
3
2
  export type SportsMarketsProps = {
4
3
  event: VenueEventWithMarkets;
5
- onSectionMarketsChange: (tabKey: SportsSectionTabKey, markets: VenueMarket[]) => void;
4
+ onSectionMarketsChange: (tabKey: string, markets: VenueMarket[]) => void;
6
5
  onOutcomeSelect?: () => void;
7
6
  live?: boolean;
8
7
  midpointsResult?: UseMidpointsResult;
@@ -1,8 +1,7 @@
1
1
  import { type UseMidpointsResult, type VenueEventWithMarkets, type VenueMarket } from "@agg-build/hooks";
2
- import { type SportsSectionTabKey } from "./sports-event-market.utils";
3
2
  export type SportsMarketsProps = {
4
3
  event: VenueEventWithMarkets;
5
- onSectionMarketsChange: (tabKey: SportsSectionTabKey, markets: VenueMarket[]) => void;
4
+ onSectionMarketsChange: (tabKey: string, markets: VenueMarket[]) => void;
6
5
  onOutcomeSelect?: () => void;
7
6
  live?: boolean;
8
7
  midpointsResult?: UseMidpointsResult;
@@ -38,6 +38,15 @@ export declare const getTradingRoutePriceLabel: (value: number) => string;
38
38
  export declare const isQuoteBelowVenueMinimum: (quoteData: SmartRouteResponse | null | undefined) => boolean;
39
39
  export declare const resolvePlaceOrderQuoteStatus: ({ amount, labels, quoteData, selectedMarket, }: ResolvePlaceOrderQuoteStatusParams) => PlaceOrderQuoteStatus;
40
40
  export declare const buildLiveRouteCards: ({ labels, quoteData, tradeSide, eventVenues, geoBlockedVenues: inheritedGeoBlockedVenues, }: BuildLiveRouteCardsParams) => PlaceOrderRouteCard[];
41
+ /**
42
+ * Default route-card pick when the user hasn't selected one (or their selection
43
+ * disappeared from the list). Normally the first available card wins, but when
44
+ * the primary route is blocked on funding (`insufficient_balance`) the panel
45
+ * must not park on it with a blocking alert while an executable solo (status
46
+ * "ok" + real quoteId) sits in the same response — default to that solo so a
47
+ * Kalshi-funded user with no on-chain balance lands on a submittable route.
48
+ */
49
+ export declare const resolveDefaultRouteCardId: (routeCards: PlaceOrderRouteCard[], primaryStatus?: SmartRouteResponse["status"]) => string | null;
41
50
  export declare const clampSellSharesToAvailability: (requestedSellShares: number, availableShares: number) => number;
42
51
  export declare const getRemainingVenueSellShares: (availableShares: number, filledShares: number) => number;
43
52
  export declare const buildVenueSellQuoteRequests: ({ quoteData, requestedSellShares, }: {
@@ -38,6 +38,15 @@ export declare const getTradingRoutePriceLabel: (value: number) => string;
38
38
  export declare const isQuoteBelowVenueMinimum: (quoteData: SmartRouteResponse | null | undefined) => boolean;
39
39
  export declare const resolvePlaceOrderQuoteStatus: ({ amount, labels, quoteData, selectedMarket, }: ResolvePlaceOrderQuoteStatusParams) => PlaceOrderQuoteStatus;
40
40
  export declare const buildLiveRouteCards: ({ labels, quoteData, tradeSide, eventVenues, geoBlockedVenues: inheritedGeoBlockedVenues, }: BuildLiveRouteCardsParams) => PlaceOrderRouteCard[];
41
+ /**
42
+ * Default route-card pick when the user hasn't selected one (or their selection
43
+ * disappeared from the list). Normally the first available card wins, but when
44
+ * the primary route is blocked on funding (`insufficient_balance`) the panel
45
+ * must not park on it with a blocking alert while an executable solo (status
46
+ * "ok" + real quoteId) sits in the same response — default to that solo so a
47
+ * Kalshi-funded user with no on-chain balance lands on a submittable route.
48
+ */
49
+ export declare const resolveDefaultRouteCardId: (routeCards: PlaceOrderRouteCard[], primaryStatus?: SmartRouteResponse["status"]) => string | null;
41
50
  export declare const clampSellSharesToAvailability: (requestedSellShares: number, availableShares: number) => number;
42
51
  export declare const getRemainingVenueSellShares: (availableShares: number, filledShares: number) => number;
43
52
  export declare const buildVenueSellQuoteRequests: ({ quoteData, requestedSellShares, }: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agg-build/ui",
3
- "version": "2.5.3",
3
+ "version": "2.7.0",
4
4
  "description": "Pre-built React component library for the AGG prediction market aggregator. Tailwind-based, themeable, with primitives, event surfaces, trading flows, full pages, and modals.",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",
@@ -100,7 +100,7 @@
100
100
  "liveline": "^0.0.7",
101
101
  "react": "^18.0.0 || ^19.0.0",
102
102
  "react-dom": "^18.0.0 || ^19.0.0",
103
- "@agg-build/hooks": "^2.5.1",
103
+ "@agg-build/hooks": "^2.7.0",
104
104
  "@agg-build/sdk": "^2.5.1"
105
105
  },
106
106
  "dependencies": {