@agg-build/ui 2.8.0 → 4.0.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.
Files changed (30) hide show
  1. package/dist/{chunk-AKLGQ6AB.mjs → chunk-JTSLZARU.mjs} +50 -250
  2. package/dist/{chunk-2QCNDFNC.mjs → chunk-R362GNI2.mjs} +1120 -400
  3. package/dist/{chunk-R5S2QOYL.mjs → chunk-XIDQ2A6W.mjs} +152 -59
  4. package/dist/index.js +1764 -1155
  5. package/dist/index.mjs +5 -3
  6. package/dist/modals.js +391 -845
  7. package/dist/modals.mjs +1 -1
  8. package/dist/pages.js +1724 -916
  9. package/dist/pages.mjs +4 -2
  10. package/dist/styles.css +1 -1
  11. package/dist/tailwind.css +1 -1
  12. package/dist/trading.js +567 -472
  13. package/dist/trading.mjs +1 -1
  14. package/dist/types/pages/user-profile/components/available-balance-card.d.mts +5 -1
  15. package/dist/types/pages/user-profile/components/available-balance-card.d.ts +5 -1
  16. package/dist/types/pages/user-profile/components/manage-balances-modal.d.mts +8 -0
  17. package/dist/types/pages/user-profile/components/manage-balances-modal.d.ts +8 -0
  18. package/dist/types/pages/user-profile/index.d.mts +1 -0
  19. package/dist/types/pages/user-profile/index.d.ts +1 -0
  20. package/dist/types/profile/profile-modal.constants.d.mts +1 -2
  21. package/dist/types/profile/profile-modal.constants.d.ts +1 -2
  22. package/dist/types/trading/place-order/index.place-order.constants.d.mts +1 -0
  23. package/dist/types/trading/place-order/index.place-order.constants.d.ts +1 -0
  24. package/dist/types/trading/place-order/index.place-order.types.d.mts +4 -0
  25. package/dist/types/trading/place-order/index.place-order.types.d.ts +4 -0
  26. package/dist/types/trading/place-order/index.place-order.utils.d.mts +7 -3
  27. package/dist/types/trading/place-order/index.place-order.utils.d.ts +7 -3
  28. package/package.json +3 -3
  29. package/dist/types/profile/tabs/balance-management-tab.d.mts +0 -3
  30. package/dist/types/profile/tabs/balance-management-tab.d.ts +0 -3
@@ -148,9 +148,9 @@ import {
148
148
  useExecutionProgress,
149
149
  useGeoBlock,
150
150
  useLabels as useLabels2,
151
+ useLimitOrderVenueQuotes,
151
152
  useLiveBestPrices,
152
153
  useLiveOutcomePrices,
153
- useLimitOrderVenueQuotes,
154
154
  useManagedBalances,
155
155
  useMidpoints,
156
156
  usePlaceLimitOrder,
@@ -613,6 +613,7 @@ var MIN_SELL_ORDER_SHARES = 1;
613
613
  var DEFAULT_SLIPPAGE_VALUE = "0.5";
614
614
  var HIGH_SLIPPAGE_THRESHOLD = 10;
615
615
  var PLACE_ORDER_ROUTE_COLLAPSED_CARD_COUNT = 3;
616
+ var PLACE_ORDER_MAXIMIZE_PAYOUT_ROUTE_ID = "live-maximize-payout";
616
617
  var PLACE_ORDER_NUMERIC_INPUT_CLASS_NAME = "bg-transparent text-right text-agg-3xl font-agg-bold leading-agg-9 tracking-agg-normal text-agg-foreground outline-none";
617
618
  var PLACE_ORDER_CONTAINER_CLASS_NAME = "w-full overflow-hidden rounded-agg-xl border border-agg-separator bg-agg-secondary shadow-none hover:shadow-none";
618
619
  var PLACE_ORDER_OUTCOME_BUTTON_CLASS_NAMES = {
@@ -1087,6 +1088,29 @@ var routePriceLabelFormatter = new Intl.NumberFormat("en-US", {
1087
1088
  maximumFractionDigits: 1
1088
1089
  });
1089
1090
  var GEO_BLOCK_WARNING_PREFIX = "Venue not available in your region";
1091
+ var floorToDecimals = (value, decimals) => {
1092
+ if (!Number.isFinite(value) || value <= 0) return 0;
1093
+ const [coefficient = "0", exponentText = "0"] = value.toString().toLowerCase().split("e");
1094
+ const [whole = "0", fraction = ""] = coefficient.split(".");
1095
+ const exponent = Number(exponentText);
1096
+ const digits = `${whole}${fraction}`;
1097
+ const decimalIndex = whole.length + exponent;
1098
+ const normalized = decimalIndex <= 0 ? `0.${"0".repeat(-decimalIndex)}${digits}` : decimalIndex >= digits.length ? `${digits}${"0".repeat(decimalIndex - digits.length)}` : `${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
1099
+ const [normalizedWhole = "0", normalizedFraction = ""] = normalized.split(".");
1100
+ const truncatedFraction = normalizedFraction.slice(0, decimals);
1101
+ return Number(
1102
+ truncatedFraction.length > 0 ? `${normalizedWhole}.${truncatedFraction}` : normalizedWhole
1103
+ );
1104
+ };
1105
+ var formatFlooredShareAmount = (value, decimals) => {
1106
+ const flooredValue = floorToDecimals(value, decimals);
1107
+ if (flooredValue <= 0) return "0";
1108
+ const formattedValue = flooredValue.toLocaleString("en-US", {
1109
+ minimumFractionDigits: 0,
1110
+ maximumFractionDigits: decimals
1111
+ });
1112
+ return formattedValue.replace(/(\.\d*?[1-9])0+$/u, "$1").replace(/\.0+$/u, "");
1113
+ };
1090
1114
  var normalizeOutcomeName = (value) => {
1091
1115
  var _a;
1092
1116
  return (_a = value == null ? void 0 : value.trim().toLowerCase()) != null ? _a : "";
@@ -1236,18 +1260,24 @@ var mapVenueMarketOutcomesToPlaceOrderOutcomes = (venueMarketOutcomes) => {
1236
1260
  };
1237
1261
  });
1238
1262
  };
1239
- var mapQuoteDataToRoutingRows = (quoteData) => {
1263
+ var mapQuoteDataToRoutingRows = (quoteData, tradeSide = "buy") => {
1240
1264
  if (!(quoteData == null ? void 0 : quoteData.fills.length)) return [];
1241
- return quoteData.fills.map((fill) => ({
1242
- venue: fill.venue,
1243
- label: getTradingValueLabel({ amount: fill.venueQty * fill.avgPrice }),
1244
- priceLabel: getTradingRoutePriceLabel(fill.avgPrice),
1245
- resultLabel: getTradingValueLabel({
1246
- amount: fill.venueQty,
1247
- minimumFractionDigits: 2,
1248
- maximumFractionDigits: 2
1249
- })
1250
- }));
1265
+ return quoteData.fills.map((fill) => {
1266
+ const allocationValueLabel = getTradingValueLabel(__spreadValues({
1267
+ amount: fill.venueQty * fill.avgPrice
1268
+ }, tradeSide === "sell" ? { minimumFractionDigits: 2, maximumFractionDigits: 2 } : {}));
1269
+ const allocationSharesLabel = `${formatFlooredShareAmount(fill.venueQty, 2)} shares`;
1270
+ return {
1271
+ venue: fill.venue,
1272
+ label: tradeSide === "sell" ? allocationSharesLabel : allocationValueLabel,
1273
+ priceLabel: getTradingRoutePriceLabel(fill.avgPrice),
1274
+ resultLabel: tradeSide === "sell" ? allocationValueLabel : getTradingValueLabel({
1275
+ amount: fill.venueQty,
1276
+ minimumFractionDigits: 2,
1277
+ maximumFractionDigits: 2
1278
+ })
1279
+ };
1280
+ });
1251
1281
  };
1252
1282
  var deriveAggregateOrderStatus = (orderIds, terminalEvents) => {
1253
1283
  if (!orderIds.length) return "pending";
@@ -1426,7 +1456,8 @@ var buildLiveRouteCards = ({
1426
1456
  ),
1427
1457
  numericValue: tradeSide === "sell" ? quoteData.rawExecCost : quoteData.totalFilled,
1428
1458
  quoteData,
1429
- rows: mapQuoteDataToRoutingRows(quoteData),
1459
+ rows: mapQuoteDataToRoutingRows(quoteData, tradeSide),
1460
+ description: labels.splitOrderDescription,
1430
1461
  value: primaryResult.value,
1431
1462
  venue: isSplit ? void 0 : parsedPrimaryVenue.success ? parsedPrimaryVenue.data : void 0
1432
1463
  } : null;
@@ -1560,6 +1591,9 @@ var clampSellSharesToAvailability = (requestedSellShares, availableShares) => {
1560
1591
  requestedAtomicShares < availableAtomicShares ? requestedAtomicShares : availableAtomicShares
1561
1592
  );
1562
1593
  };
1594
+ var hasInsufficientVenueInventory = (requestedSellShares, availableShares) => {
1595
+ return sellSharesToAtomicUnits(requestedSellShares) > sellSharesToAtomicUnits(availableShares);
1596
+ };
1563
1597
  var getRemainingVenueSellShares = (availableShares, filledShares) => {
1564
1598
  const availableAtomicShares = sellSharesToAtomicUnits(availableShares);
1565
1599
  const filledAtomicShares = sellSharesToAtomicUnits(filledShares);
@@ -1596,12 +1630,37 @@ var buildVenueSellQuoteRequests = ({
1596
1630
  };
1597
1631
  var buildLiveSellRouteCards = ({
1598
1632
  labels,
1633
+ requestedSellShares,
1599
1634
  smartQuoteData,
1600
1635
  venueQuotes,
1601
1636
  eventVenues = [],
1602
1637
  geoBlockedVenues
1603
1638
  }) => {
1604
1639
  var _a;
1640
+ const availabilityRequests = buildVenueSellQuoteRequests({
1641
+ quoteData: smartQuoteData,
1642
+ requestedSellShares
1643
+ });
1644
+ const availabilityRequestByVenue = new Map(
1645
+ availabilityRequests.map((request) => [request.venue, request])
1646
+ );
1647
+ const decorateVenueCard = (card, request) => {
1648
+ if (card.kind !== "venue" || !card.venue || !request) return card;
1649
+ const executionPrice = card.quoteData.totalFilled > 0 ? card.quoteData.rawExecCost / card.quoteData.totalFilled : void 0;
1650
+ const insufficientInventory = hasInsufficientVenueInventory(
1651
+ requestedSellShares,
1652
+ request.availableShares
1653
+ );
1654
+ const sharesLabel = labels.shares(floorToDecimals(request.availableShares, 2));
1655
+ const priceLabel = executionPrice == null ? "\u2014" : getTradingRoutePriceLabel(executionPrice);
1656
+ return __spreadProps(__spreadValues({}, card), {
1657
+ availableShares: request.availableShares,
1658
+ executionPrice,
1659
+ hint: card.isUnavailable ? card.hint : insufficientInventory ? labels.insufficientVenueInventory(sharesLabel, priceLabel) : labels.venueInventory(sharesLabel, priceLabel),
1660
+ id: `live-solo-${card.venue}`,
1661
+ insufficientInventory
1662
+ });
1663
+ };
1605
1664
  const smartRouteCards = smartQuoteData ? buildLiveRouteCards({
1606
1665
  labels,
1607
1666
  quoteData: __spreadProps(__spreadValues({}, smartQuoteData), {
@@ -1610,12 +1669,25 @@ var buildLiveSellRouteCards = ({
1610
1669
  tradeSide: "sell",
1611
1670
  eventVenues,
1612
1671
  geoBlockedVenues
1672
+ }).map((card) => {
1673
+ if (card.kind === "split") {
1674
+ return __spreadProps(__spreadValues({}, card), {
1675
+ description: labels.maximizePayoutDescription,
1676
+ id: PLACE_ORDER_MAXIMIZE_PAYOUT_ROUTE_ID,
1677
+ label: labels.maximizePayout
1678
+ });
1679
+ }
1680
+ return decorateVenueCard(
1681
+ card,
1682
+ card.venue ? availabilityRequestByVenue.get(card.venue) : void 0
1683
+ );
1613
1684
  }) : [];
1614
1685
  const smartRouteVenue = (smartQuoteData == null ? void 0 : smartQuoteData.status) === "ok" && smartQuoteData.fills.length === 1 ? parseVenue((_a = smartQuoteData.fills[0]) == null ? void 0 : _a.venue) : null;
1615
1686
  const independentVenueCards = /* @__PURE__ */ new Map();
1616
1687
  for (const venueQuote of venueQuotes) {
1617
1688
  const quoteData = venueQuote.quoteData;
1618
- if (!(quoteData == null ? void 0 : quoteData.quoteId) || quoteData.status !== "ok" || quoteData.fills.length === 0 || quoteData.fills.some((fill) => fill.venue !== venueQuote.venue) || (smartRouteVenue == null ? void 0 : smartRouteVenue.success) && smartRouteVenue.data === venueQuote.venue) {
1689
+ const { venue } = venueQuote.request;
1690
+ if (!(quoteData == null ? void 0 : quoteData.quoteId) || quoteData.status !== "ok" || quoteData.fills.length === 0 || quoteData.fills.some((fill) => fill.venue !== venue) || (smartRouteVenue == null ? void 0 : smartRouteVenue.success) && smartRouteVenue.data === venue) {
1619
1691
  continue;
1620
1692
  }
1621
1693
  const [venueCard] = buildLiveRouteCards({
@@ -1626,17 +1698,17 @@ var buildLiveSellRouteCards = ({
1626
1698
  tradeSide: "sell",
1627
1699
  geoBlockedVenues
1628
1700
  });
1629
- if (!venueCard || venueCard.kind !== "venue" || venueCard.venue !== venueQuote.venue) {
1701
+ if (!venueCard || venueCard.kind !== "venue" || venueCard.venue !== venue) {
1630
1702
  continue;
1631
1703
  }
1632
- independentVenueCards.set(venueQuote.venue, __spreadProps(__spreadValues({}, venueCard), {
1633
- id: `live-solo-${venueQuote.venue}`
1634
- }));
1704
+ independentVenueCards.set(venue, decorateVenueCard(venueCard, venueQuote.request));
1635
1705
  }
1636
1706
  const deduplicatedSmartRouteCards = smartRouteCards.filter(
1637
1707
  (card) => !card.venue || !independentVenueCards.has(card.venue)
1638
1708
  );
1639
1709
  return [...deduplicatedSmartRouteCards, ...independentVenueCards.values()].sort((left, right) => {
1710
+ if (left.id === PLACE_ORDER_MAXIMIZE_PAYOUT_ROUTE_ID) return -1;
1711
+ if (right.id === PLACE_ORDER_MAXIMIZE_PAYOUT_ROUTE_ID) return 1;
1640
1712
  if (!!left.isUnavailable !== !!right.isUnavailable) {
1641
1713
  return left.isUnavailable ? 1 : -1;
1642
1714
  }
@@ -2697,29 +2769,6 @@ PlaceOrderSuccessView.displayName = "PlaceOrderSuccessView";
2697
2769
  import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
2698
2770
  var SELL_SHARE_INPUT_DECIMALS = 6;
2699
2771
  var SELL_SHARE_DISPLAY_DECIMALS = 2;
2700
- var floorToDecimals = (value, decimals) => {
2701
- if (!Number.isFinite(value) || value <= 0) return 0;
2702
- const [coefficient = "0", exponentText = "0"] = value.toString().toLowerCase().split("e");
2703
- const [whole = "0", fraction = ""] = coefficient.split(".");
2704
- const exponent = Number(exponentText);
2705
- const digits = `${whole}${fraction}`;
2706
- const decimalIndex = whole.length + exponent;
2707
- const normalized = decimalIndex <= 0 ? `0.${"0".repeat(-decimalIndex)}${digits}` : decimalIndex >= digits.length ? `${digits}${"0".repeat(decimalIndex - digits.length)}` : `${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
2708
- const [normalizedWhole = "0", normalizedFraction = ""] = normalized.split(".");
2709
- const truncatedFraction = normalizedFraction.slice(0, decimals);
2710
- return Number(
2711
- truncatedFraction.length > 0 ? `${normalizedWhole}.${truncatedFraction}` : normalizedWhole
2712
- );
2713
- };
2714
- var formatFlooredShareAmount = (value, decimals) => {
2715
- const flooredValue = floorToDecimals(value, decimals);
2716
- if (flooredValue <= 0) return "0";
2717
- const formattedValue = flooredValue.toLocaleString("en-US", {
2718
- minimumFractionDigits: 0,
2719
- maximumFractionDigits: decimals
2720
- });
2721
- return formattedValue.replace(/(\.\d*?[1-9])0+$/u, "$1").replace(/\.0+$/u, "");
2722
- };
2723
2772
  var resolvePlaceOrderPortalContainer = (triggerElement) => {
2724
2773
  var _a;
2725
2774
  return (_a = triggerElement == null ? void 0 : triggerElement.closest(".agg-modal-center")) != null ? _a : void 0;
@@ -3277,7 +3326,7 @@ var renderRouteCard = ({
3277
3326
  onSelect,
3278
3327
  tradingLabels
3279
3328
  }) => {
3280
- var _a, _b;
3329
+ var _a, _b, _c;
3281
3330
  const showSplitDetails = isSelected && isExpanded && card.kind === "split" && !!((_a = card.rows) == null ? void 0 : _a.length);
3282
3331
  const ariaLabel = [card.label, card.hint, card.value].filter(Boolean).join(" ");
3283
3332
  return /* @__PURE__ */ jsx6(
@@ -3332,6 +3381,14 @@ var renderRouteCard = ({
3332
3381
  className: "shrink-0 text-agg-muted-foreground",
3333
3382
  "aria-hidden": "true"
3334
3383
  }
3384
+ ) : card.insufficientInventory ? /* @__PURE__ */ jsx6(
3385
+ Icon,
3386
+ {
3387
+ name: "warning",
3388
+ size: "xs",
3389
+ className: "shrink-0 text-agg-muted-foreground",
3390
+ "aria-hidden": "true"
3391
+ }
3335
3392
  ) : card.kind === "split" && isSelected ? /* @__PURE__ */ jsx6(
3336
3393
  Icon,
3337
3394
  {
@@ -3358,8 +3415,8 @@ var renderRouteCard = ({
3358
3415
  )
3359
3416
  ] }),
3360
3417
  showSplitDetails ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
3361
- /* @__PURE__ */ jsx6("p", { className: "agg-route-card-description text-agg-xs leading-agg-4 text-agg-foreground", children: tradingLabels.splitOrderDescription }),
3362
- /* @__PURE__ */ jsx6("div", { className: "agg-route-breakdown flex flex-col gap-3", children: (_b = card.rows) == null ? void 0 : _b.map((row) => renderRouteBreakdownRow(row)) })
3418
+ /* @__PURE__ */ jsx6("p", { className: "agg-route-card-description text-agg-xs leading-agg-4 text-agg-foreground", children: (_b = card.description) != null ? _b : tradingLabels.splitOrderDescription }),
3419
+ /* @__PURE__ */ jsx6("div", { className: "agg-route-breakdown flex flex-col gap-3", children: (_c = card.rows) == null ? void 0 : _c.map((row) => renderRouteBreakdownRow(row)) })
3363
3420
  ] }) : null
3364
3421
  ] })
3365
3422
  }
@@ -3966,9 +4023,10 @@ var PlaceOrder = ({
3966
4023
  eventVenues,
3967
4024
  geoBlockedVenues: inheritedBuyGeoBlockedVenues,
3968
4025
  labels: tradingLabels,
4026
+ requestedSellShares: debouncedAmount,
3969
4027
  smartQuoteData: smartRoute.data,
3970
4028
  venueQuotes: venueSellQuotes.quotes.map((venueQuote) => ({
3971
- venue: venueQuote.request.venue,
4029
+ request: venueQuote.request,
3972
4030
  quoteData: venueQuote.data
3973
4031
  }))
3974
4032
  });
@@ -3980,6 +4038,7 @@ var PlaceOrder = ({
3980
4038
  tradeSide: "buy"
3981
4039
  }) : [];
3982
4040
  }, [
4041
+ debouncedAmount,
3983
4042
  smartRoute.data,
3984
4043
  tradingLabels,
3985
4044
  inheritedBuyGeoBlockedVenues,
@@ -3987,16 +4046,19 @@ var PlaceOrder = ({
3987
4046
  scopedSelectedEvent == null ? void 0 : scopedSelectedEvent.venueMarkets,
3988
4047
  venueSellQuotes.quotes
3989
4048
  ]);
4049
+ const isSellQuoteTransitioning = isSell && (isQuoteInputEditing || smartRoute.isLoading || smartRoute.isFetching || venueSellQuotes.isLoading || venueSellQuotes.isFetching);
3990
4050
  const resolvedSelectedRouteCardId = useMemo(() => {
3991
4051
  var _a2;
3992
- if (routeCards.length === 0) return null;
3993
4052
  if (selectedRouteCardId && routeCards.some((card) => card.id === selectedRouteCardId && !card.isUnavailable)) {
3994
4053
  return selectedRouteCardId;
3995
4054
  }
4055
+ if (selectedRouteCardId && isSellQuoteTransitioning) return selectedRouteCardId;
4056
+ if (routeCards.length === 0) return null;
3996
4057
  return resolveDefaultRouteCardId(routeCards, isSell ? void 0 : (_a2 = smartRoute.data) == null ? void 0 : _a2.status);
3997
- }, [routeCards, selectedRouteCardId, isSell, (_x = smartRoute.data) == null ? void 0 : _x.status]);
4058
+ }, [isSell, isSellQuoteTransitioning, routeCards, selectedRouteCardId, (_x = smartRoute.data) == null ? void 0 : _x.status]);
3998
4059
  useEffect2(() => {
3999
4060
  if (routeCards.length === 0) {
4061
+ if (isSellQuoteTransitioning) return;
4000
4062
  setSelectedRouteCardId(null);
4001
4063
  setIsRoutesExpanded(false);
4002
4064
  setIsSplitDetailOpen(false);
@@ -4005,7 +4067,12 @@ var PlaceOrder = ({
4005
4067
  if (resolvedSelectedRouteCardId !== selectedRouteCardId) {
4006
4068
  setSelectedRouteCardId(resolvedSelectedRouteCardId);
4007
4069
  }
4008
- }, [resolvedSelectedRouteCardId, routeCards.length, selectedRouteCardId]);
4070
+ }, [
4071
+ isSellQuoteTransitioning,
4072
+ resolvedSelectedRouteCardId,
4073
+ routeCards.length,
4074
+ selectedRouteCardId
4075
+ ]);
4009
4076
  const isSubmissionLocked = submissionProgressState != null;
4010
4077
  const isSubmissionLockedRef = useRef2(isSubmissionLocked);
4011
4078
  isSubmissionLockedRef.current = isSubmissionLocked;
@@ -4035,6 +4102,11 @@ var PlaceOrder = ({
4035
4102
  useEffect2(() => {
4036
4103
  setSelectedLimitVenue(null);
4037
4104
  }, [scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.id, scopedSelectedOutcomeId]);
4105
+ useEffect2(() => {
4106
+ setSelectedRouteCardId(null);
4107
+ setIsRoutesExpanded(false);
4108
+ setIsSplitDetailOpen(false);
4109
+ }, [executionType, internalTab, scopedSelectedOutcomeId]);
4038
4110
  const orderedRouteCards = routeCards;
4039
4111
  const selectedRouteCard = (_z = (_y = orderedRouteCards.find((card) => card.id === resolvedSelectedRouteCardId)) != null ? _y : orderedRouteCards[0]) != null ? _z : null;
4040
4112
  const isKalshiRoute = useMemo(() => {
@@ -4083,16 +4155,33 @@ var PlaceOrder = ({
4083
4155
  const verifyKalshiConnectionLabel = (_G = (_F = (_E = (_D = labels.onboarding) == null ? void 0 : _D.connectKalshiModal) == null ? void 0 : _E.actions) == null ? void 0 : _F.verifyConnection) != null ? _G : tradingLabels.kycRequired;
4084
4156
  const handleRouteCardSelect = useCallback2(
4085
4157
  (cardId) => {
4158
+ const card = routeCards.find((routeCard) => routeCard.id === cardId);
4159
+ if (!card || card.isUnavailable) return;
4086
4160
  if (cardId === resolvedSelectedRouteCardId) {
4087
- const card = routeCards.find((c) => c.id === cardId);
4088
4161
  if ((card == null ? void 0 : card.kind) === "split") {
4089
4162
  setIsSplitDetailOpen((prev) => !prev);
4090
4163
  return;
4091
4164
  }
4092
4165
  }
4093
4166
  setSelectedRouteCardId(cardId);
4167
+ setIsSplitDetailOpen(false);
4168
+ if (!isSell || card.kind !== "venue" || !card.insufficientInventory || card.availableShares == null) {
4169
+ return;
4170
+ }
4171
+ const clampedAmount = clampSellSharesToAvailability(internalAmount, card.availableShares);
4172
+ if (clampedAmount === internalAmount) return;
4173
+ setInternalAmount(clampedAmount);
4174
+ setSellFilledForOutcomeId(scopedSelectedOutcomeId != null ? scopedSelectedOutcomeId : null);
4175
+ onAmountChange == null ? void 0 : onAmountChange(clampedAmount);
4094
4176
  },
4095
- [resolvedSelectedRouteCardId, routeCards]
4177
+ [
4178
+ internalAmount,
4179
+ isSell,
4180
+ onAmountChange,
4181
+ resolvedSelectedRouteCardId,
4182
+ routeCards,
4183
+ scopedSelectedOutcomeId
4184
+ ]
4096
4185
  );
4097
4186
  const executionProgress = useExecutionProgress({
4098
4187
  orderIds: (_H = submissionProgressState == null ? void 0 : submissionProgressState.orderIds) != null ? _H : null,
@@ -4404,7 +4493,7 @@ var PlaceOrder = ({
4404
4493
  const activeQuoteData = isLimitOrder ? null : (_T = (_S = selectedRouteCard == null ? void 0 : selectedRouteCard.quoteData) != null ? _S : smartRoute.data) != null ? _T : null;
4405
4494
  const visibleMarketRouteCards = orderedRouteCards.length > PLACE_ORDER_ROUTE_COLLAPSED_CARD_COUNT && !isRoutesExpanded ? orderedRouteCards.slice(0, PLACE_ORDER_ROUTE_COLLAPSED_CARD_COUNT) : orderedRouteCards;
4406
4495
  const hasEnteredAmount = internalAmount > 0;
4407
- const isQuoteLoading = !isLimitOrder && hasEnteredAmount && (smartRoute.isFetching || smartRoute.isLoading || isSell && (venueSellQuotes.isFetching || venueSellQuotes.isLoading));
4496
+ const isQuoteLoading = !isLimitOrder && hasEnteredAmount && (isSell && isQuoteInputEditing || smartRoute.isLoading || !isSell && smartRoute.isFetching || isSell && venueSellQuotes.isLoading);
4408
4497
  const routeLoadingMessage = isQuoteLoading ? smartRoute.loadingReason === "updating-route" ? tradingLabels.updatingRoute : smartRoute.loadingReason === "refreshing-quotes" ? tradingLabels.refreshingQuotes : tradingLabels.findingBestOdds : null;
4409
4498
  const selectedRouteFills = (_U = selectedRouteCard == null ? void 0 : selectedRouteCard.quoteData.fills) != null ? _U : [];
4410
4499
  const isKalshiOnlyRoute = isKalshiRoute && ((selectedRouteCard == null ? void 0 : selectedRouteCard.venue) === Venue4.kalshi || selectedRouteFills.length > 0 && selectedRouteFills.every((fill) => fill.venue === Venue4.kalshi));
@@ -4418,6 +4507,7 @@ var PlaceOrder = ({
4418
4507
  const isInsufficientBalance = !isSell && isAuthenticated && hasEnteredAmount && !isBalanceLoading && (isLimitOrder ? internalAmount > totalBalance : isPaperMode ? internalAmount > paperTotalBalance : isKalshiBalanceInsufficient || isOnchainBalanceInsufficient);
4419
4508
  const isQuoteInsufficientBalance = !isLimitOrder && (activeQuoteData == null ? void 0 : activeQuoteData.status) === "insufficient_balance";
4420
4509
  const shouldShowInsufficientBalanceAlert = isInsufficientBalance || isQuoteInsufficientBalance;
4510
+ const isSelectedVenueInventoryInsufficient = isSell && (selectedRouteCard == null ? void 0 : selectedRouteCard.kind) === "venue" && selectedRouteCard.insufficientInventory === true;
4421
4511
  const isBelowClientMinimum = !isSell && hasEnteredAmount && internalAmount < MIN_BUY_ORDER_AMOUNT;
4422
4512
  const isBelowVenueMinimumFromQuote = isQuoteBelowVenueMinimum(activeQuoteData);
4423
4513
  const isBelowMinimum = isBelowClientMinimum || isBelowVenueMinimumFromQuote;
@@ -4499,13 +4589,10 @@ var PlaceOrder = ({
4499
4589
  tradingLabels
4500
4590
  ]);
4501
4591
  const displayedToWinHint = useMemo(() => {
4502
- var _a2, _b2, _c2, _d2;
4592
+ var _a2;
4503
4593
  if (!selectedRouteCard) return "";
4504
- if (selectedRouteCard.isUnavailable) {
4505
- const avgPrice = (_c2 = (_b2 = (_a2 = selectedRouteCard.quoteData) == null ? void 0 : _a2.fills) == null ? void 0 : _b2[0]) == null ? void 0 : _c2.avgPrice;
4506
- return avgPrice != null ? tradingLabels.averagePrice(avgPrice) : "";
4507
- }
4508
- return (_d2 = selectedRouteCard.hint) != null ? _d2 : "";
4594
+ const averagePrice = selectedRouteCard.quoteData.totalFilled > 0 ? selectedRouteCard.quoteData.rawExecCost / selectedRouteCard.quoteData.totalFilled : (_a2 = selectedRouteCard.quoteData.fills[0]) == null ? void 0 : _a2.avgPrice;
4595
+ return averagePrice == null ? "" : tradingLabels.averagePrice(averagePrice);
4509
4596
  }, [selectedRouteCard, tradingLabels]);
4510
4597
  const displayedToWinValue = (_W = selectedRouteCard == null ? void 0 : selectedRouteCard.numericValue) != null ? _W : 0;
4511
4598
  const limitOrderPayload = useMemo(() => {
@@ -4703,7 +4790,7 @@ var PlaceOrder = ({
4703
4790
  const shouldShowGeoBlockBanner = isTradingBlocked || selectedRouteGeoBlocked || isPrimaryVenueGeoBlocked || isLimitOrder && limitRouteCards.length > 0 && limitRouteCards.every((card) => card.isUnavailable);
4704
4791
  const shouldShowLowLiquidityWarning = !isQuoteInputEditing && !isQuoteLoading && (activeQuoteData == null ? void 0 : activeQuoteData.venueMarketOutcomeId) === scopedSelectedOutcomeId && hasLowLiquidityWarning(activeQuoteData.warnings);
4705
4792
  const actionLabel = `${internalTab === "buy" ? tradingLabels.buy : tradingLabels.sell} ${selectedOutcomeLabel}`.trim();
4706
- const isActionDisabled = isPrimaryActionDisabled || !orderEligibility.canPlaceOrder || isActionLoading || !hasEnteredAmount || !scopedSelectedMarket || isInsufficientBalance || isQuoteInsufficientBalance || isSell && isQuoteInputEditing || isSellAmountAboveAvailability || isBelowMinimum || !isLimitOrder && isQuoteLoading || (isLimitOrder ? !limitOrderPayload : !selectedRouteCard || !selectedRouteCard.quoteData.quoteId) || selectedRouteGeoBlocked || !isAuthenticated || !isLimitOrder && quoteStatus !== void 0;
4793
+ const isActionDisabled = isPrimaryActionDisabled || !orderEligibility.canPlaceOrder || isActionLoading || !hasEnteredAmount || !scopedSelectedMarket || isInsufficientBalance || isQuoteInsufficientBalance || isSell && isQuoteInputEditing || isSellAmountAboveAvailability || isBelowMinimum || !isLimitOrder && isQuoteLoading || isSelectedVenueInventoryInsufficient || (isLimitOrder ? !limitOrderPayload : !selectedRouteCard || !selectedRouteCard.quoteData.quoteId) || selectedRouteGeoBlocked || !isAuthenticated || !isLimitOrder && quoteStatus !== void 0;
4707
4794
  const shouldShowSmartRouting = orderEligibility.canPlaceOrder && hasEnteredAmount && !isBelowMinimum && (isLimitOrder ? limitRouteCards.length > 0 : orderedRouteCards.length > 0 || smartRoute.isFetching || smartRoute.isLoading || isSell && (venueSellQuotes.isFetching || venueSellQuotes.isLoading));
4708
4795
  const shouldShowRouteToggle = !isLimitOrder && !isQuoteLoading && orderedRouteCards.length > PLACE_ORDER_ROUTE_COLLAPSED_CARD_COUNT;
4709
4796
  const handleReturnToOrderForm = useCallback2(() => {
@@ -5043,16 +5130,20 @@ var PlaceOrder = ({
5043
5130
  }
5044
5131
  const refreshedCards = selectedVenueQuote ? buildLiveSellRouteCards({
5045
5132
  labels: tradingLabels,
5133
+ requestedSellShares: retryAmount,
5046
5134
  smartQuoteData: null,
5047
5135
  venueQuotes: [
5048
5136
  {
5049
- venue: selectedVenueQuote.request.venue,
5137
+ request: __spreadProps(__spreadValues({}, selectedVenueQuote.request), {
5138
+ sellShares: retryAmount
5139
+ }),
5050
5140
  quoteData: refetchedQuoteData
5051
5141
  }
5052
5142
  ]
5053
5143
  }) : isSell ? buildLiveSellRouteCards({
5054
5144
  eventVenues: scopedSelectedEvent == null ? void 0 : scopedSelectedEvent.venueMarkets.map((market) => market.venue),
5055
5145
  labels: tradingLabels,
5146
+ requestedSellShares: retryAmount,
5056
5147
  smartQuoteData: refetchedQuoteData,
5057
5148
  venueQuotes: []
5058
5149
  }) : buildLiveRouteCards({
@@ -5185,6 +5276,8 @@ var PlaceOrder = ({
5185
5276
  const handleFillSellableShares = () => {
5186
5277
  if (!isSell) return;
5187
5278
  if (maxSellableShares <= 0) return;
5279
+ setSelectedRouteCardId(PLACE_ORDER_MAXIMIZE_PAYOUT_ROUTE_ID);
5280
+ setIsSplitDetailOpen(false);
5188
5281
  handleAmountChange(maxSellableShares);
5189
5282
  };
5190
5283
  const handleExecutionTypeChange = (nextType) => {