@agg-build/ui 4.11.1 → 4.13.2

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.js CHANGED
@@ -12344,6 +12344,8 @@ var buildMarketDetailsModel = ({
12344
12344
  var import_hooks44 = require("@agg-build/hooks");
12345
12345
  var PRICE_PRECISION = 1e6;
12346
12346
  var SIZE_PRECISION = 1e8;
12347
+ var DISPLAY_PRICE_BUCKETS_PER_UNIT = 1e3;
12348
+ var DISPLAY_ROUNDING_PRECISION = 1e9;
12347
12349
  var POSITIVE_OUTCOME_KEYS = /* @__PURE__ */ new Set(["yes", "y", "true", "up", "buy", "long"]);
12348
12350
  var NEGATIVE_OUTCOME_KEYS = /* @__PURE__ */ new Set(["no", "n", "false", "down", "sell", "short"]);
12349
12351
  var roundTo = (value, precision) => {
@@ -12358,6 +12360,10 @@ var fromScaled = (value, precision) => {
12358
12360
  var toPriceKey = (price) => {
12359
12361
  return String(toScaled(price, PRICE_PRECISION));
12360
12362
  };
12363
+ var toDisplayPrice = (price) => {
12364
+ const bucketSize = DISPLAY_ROUNDING_PRECISION / DISPLAY_PRICE_BUCKETS_PER_UNIT;
12365
+ return Math.round(toScaled(price, DISPLAY_ROUNDING_PRECISION) / bucketSize) / DISPLAY_PRICE_BUCKETS_PER_UNIT;
12366
+ };
12361
12367
  var normalizeOutcomeLabel = (value) => {
12362
12368
  if (typeof value !== "string") return "";
12363
12369
  return value.trim().toLowerCase().replace(/[_-]+/g, " ").replace(/[^\p{L}\p{N}\s]/gu, " ").replace(/\s+/g, " ");
@@ -12471,7 +12477,7 @@ var buildRowsFromAccumulator = ({
12471
12477
  venues,
12472
12478
  price: roundTo(level.price, PRICE_PRECISION),
12473
12479
  size,
12474
- total: roundTo(level.price * size, SIZE_PRECISION),
12480
+ total: roundTo(level.notional, SIZE_PRECISION),
12475
12481
  tone,
12476
12482
  barScale: 0,
12477
12483
  venueBreakdown,
@@ -12489,6 +12495,7 @@ var accumulateSideLevels = ({
12489
12495
  orderbooksByOutcomeId
12490
12496
  }) => {
12491
12497
  const levelsByPrice = /* @__PURE__ */ new Map();
12498
+ let bestPrice = null;
12492
12499
  const includedOutcomeIds = /* @__PURE__ */ new Set();
12493
12500
  const missingOutcomeIds = /* @__PURE__ */ new Set();
12494
12501
  eligibleOutcomes.forEach((eligibleOutcome) => {
@@ -12504,18 +12511,25 @@ var accumulateSideLevels = ({
12504
12511
  includedOutcomeIds.add(eligibleOutcome.outcomeId);
12505
12512
  venueLevels.forEach((level) => {
12506
12513
  var _a;
12507
- const priceKey = toPriceKey(level.price);
12514
+ if (bestPrice == null || (side === "asks" ? level.price < bestPrice : level.price > bestPrice)) {
12515
+ bestPrice = level.price;
12516
+ }
12517
+ const displayPrice = toDisplayPrice(level.price);
12518
+ const priceKey = toPriceKey(displayPrice);
12508
12519
  const scaledSize = toScaled(level.size, SIZE_PRECISION);
12520
+ const notional = level.price * level.size;
12509
12521
  const currentLevel = levelsByPrice.get(priceKey);
12510
12522
  if (currentLevel) {
12511
12523
  currentLevel.sizeScaled += scaledSize;
12524
+ currentLevel.notional += notional;
12512
12525
  currentLevel.venueBreakdownScaled[eligibleOutcome.venue] = ((_a = currentLevel.venueBreakdownScaled[eligibleOutcome.venue]) != null ? _a : 0) + scaledSize;
12513
12526
  currentLevel.sourceOutcomeIds.add(eligibleOutcome.outcomeId);
12514
12527
  return;
12515
12528
  }
12516
12529
  levelsByPrice.set(priceKey, {
12517
- price: level.price,
12530
+ price: displayPrice,
12518
12531
  sizeScaled: scaledSize,
12532
+ notional,
12519
12533
  venueBreakdownScaled: {
12520
12534
  [eligibleOutcome.venue]: scaledSize
12521
12535
  },
@@ -12525,6 +12539,7 @@ var accumulateSideLevels = ({
12525
12539
  });
12526
12540
  return {
12527
12541
  levelsByPrice,
12542
+ bestPrice,
12528
12543
  includedOutcomeIds,
12529
12544
  missingOutcomeIds
12530
12545
  };
@@ -12681,7 +12696,7 @@ var mergeVenueOutcomeOrderbooks = ({
12681
12696
  eligibleOutcomes,
12682
12697
  orderbooksByOutcomeId
12683
12698
  }) => {
12684
- var _a, _b, _c, _d, _e, _f;
12699
+ var _a, _b;
12685
12700
  const bidState = accumulateSideLevels({
12686
12701
  side: "bids",
12687
12702
  eligibleOutcomes,
@@ -12704,8 +12719,8 @@ var mergeVenueOutcomeOrderbooks = ({
12704
12719
  levelsByPrice: askState.levelsByPrice,
12705
12720
  fallbackVenue: (_b = eligibleOutcomes[0]) == null ? void 0 : _b.venue
12706
12721
  });
12707
- const bestBid = (_d = (_c = bidRows[0]) == null ? void 0 : _c.price) != null ? _d : null;
12708
- const bestAsk = (_f = (_e = askRows[0]) == null ? void 0 : _e.price) != null ? _f : null;
12722
+ const bestBid = bidState.bestPrice;
12723
+ const bestAsk = askState.bestPrice;
12709
12724
  return {
12710
12725
  askRows,
12711
12726
  bidRows,
@@ -19493,6 +19508,72 @@ var parseDecimalString = (value) => {
19493
19508
  if (!Number.isFinite(parsed) || parsed <= 0) return null;
19494
19509
  return parsed;
19495
19510
  };
19511
+ var getPlaceOrderBuyPayout = (quoteData) => {
19512
+ var _a;
19513
+ return (_a = quoteData.estimatedPayout) != null ? _a : quoteData.totalFilled;
19514
+ };
19515
+ var getPlaceOrderSellProceeds = (quoteData) => Math.max(
19516
+ 0,
19517
+ quoteData.rawExecCost - quoteData.fills.reduce((sum, fill) => {
19518
+ var _a, _b;
19519
+ return sum + ((_a = fill.venueFee) != null ? _a : 0) + ((_b = fill.builderFee) != null ? _b : 0);
19520
+ }, 0)
19521
+ );
19522
+ var getPlaceOrderQuoteValue = (quoteData, tradeSide) => tradeSide === "sell" ? getPlaceOrderSellProceeds(quoteData) : getPlaceOrderBuyPayout(quoteData);
19523
+ var resolvePlaceOrderNetResult = ({
19524
+ quoteData,
19525
+ tradeSide,
19526
+ shares,
19527
+ usd,
19528
+ terminalOrderEvents,
19529
+ submittedOrders
19530
+ }) => {
19531
+ if (!quoteData) return tradeSide === "sell" ? usd : shares;
19532
+ const actualEvents = (terminalOrderEvents != null ? terminalOrderEvents : []).filter(
19533
+ (event) => (event.event === "filled" || event.event === "partial_fill") && (tradeSide === "buy" ? event.filledAmountRaw != null : event.actualSharesRaw != null)
19534
+ );
19535
+ if (actualEvents.length) {
19536
+ return actualEvents.reduce((sum, event) => {
19537
+ var _a;
19538
+ const outcomeId = (_a = submittedOrders == null ? void 0 : submittedOrders.find(
19539
+ (order) => order.orderId === event.orderId
19540
+ )) == null ? void 0 : _a.outcomeId;
19541
+ const venueFills = quoteData.fills.filter((fill) => fill.venue === event.venue);
19542
+ const exactFill = venueFills.find((fill) => fill.venueMarketOutcomeId === outcomeId);
19543
+ const fills = exactFill ? [exactFill] : venueFills;
19544
+ const legQuote = fills.length ? __spreadProps(__spreadValues({}, quoteData), {
19545
+ fills,
19546
+ totalFilled: fills.reduce((total, fill) => total + fill.venueQty, 0),
19547
+ rawExecCost: fills.reduce((total, fill) => total + fill.avgPrice * fill.venueQty, 0),
19548
+ estimatedPayout: fills.reduce(
19549
+ (total, fill) => {
19550
+ var _a2;
19551
+ return total + fill.venueQty - ((_a2 = fill.settlementFee) != null ? _a2 : 0);
19552
+ },
19553
+ 0
19554
+ )
19555
+ }) : quoteData;
19556
+ const actual = resolveActualExecutionEconomics({
19557
+ quoteData: legQuote,
19558
+ tradeSide,
19559
+ terminalOrderEvents: [event],
19560
+ submittedOrders
19561
+ });
19562
+ return sum + resolvePlaceOrderNetResult({
19563
+ quoteData: legQuote,
19564
+ tradeSide,
19565
+ shares: actual.actualTotalFilled,
19566
+ usd: actual.actualRawExecCost
19567
+ });
19568
+ }, 0);
19569
+ }
19570
+ if (tradeSide === "sell") {
19571
+ const gross = quoteData.rawExecCost;
19572
+ return gross > 0 ? usd * (getPlaceOrderSellProceeds(quoteData) / gross) : usd;
19573
+ }
19574
+ const filled = quoteData.totalFilled;
19575
+ return filled > 0 ? shares * (getPlaceOrderBuyPayout(quoteData) / filled) : shares;
19576
+ };
19496
19577
  var resolvePlaceOrderQuoteResult = ({
19497
19578
  labels,
19498
19579
  quoteData,
@@ -19501,7 +19582,7 @@ var resolvePlaceOrderQuoteResult = ({
19501
19582
  if (!quoteData || quoteData.totalFilled <= 0) return null;
19502
19583
  const avgPrice = getPlaceOrderAverageExecutionPrice(quoteData);
19503
19584
  if (avgPrice == null) return null;
19504
- const quoteValue = tradeSide === "sell" ? quoteData.rawExecCost : quoteData.totalFilled;
19585
+ const quoteValue = getPlaceOrderQuoteValue(quoteData, tradeSide);
19505
19586
  return {
19506
19587
  hint: labels.averagePrice(avgPrice),
19507
19588
  value: getTradingValueLabel({
@@ -19619,7 +19700,7 @@ var buildLiveRouteCards = ({
19619
19700
  eventVenues = [],
19620
19701
  geoBlockedVenues: inheritedGeoBlockedVenues
19621
19702
  }) => {
19622
- var _a, _b, _c, _d;
19703
+ var _a, _b, _c, _d, _e;
19623
19704
  const geoBlockedVenues = extractGeoBlockedVenues(quoteData.warnings);
19624
19705
  for (const venue of inheritedGeoBlockedVenues != null ? inheritedGeoBlockedVenues : []) {
19625
19706
  geoBlockedVenues.add(venue);
@@ -19634,6 +19715,7 @@ var buildLiveRouteCards = ({
19634
19715
  );
19635
19716
  const averageExecutionPrice = (_b = getPlaceOrderAverageExecutionPrice(quoteData)) != null ? _b : void 0;
19636
19717
  const primaryWinnerVenue = quoteData.fills.length === 1 ? primaryVenue : void 0;
19718
+ const primaryWinnerOutcomeId = quoteData.fills.length === 1 ? (_c = quoteData.fills[0]) == null ? void 0 : _c.venueMarketOutcomeId : void 0;
19637
19719
  const isPrimaryRouteGeoBlocked = quoteData.fills.length > 0 && quoteData.fills.some((f) => geoBlockedVenues.has(f.venue));
19638
19720
  const primaryCard = primaryResult ? isPrimaryRouteGeoBlocked ? isSplit ? null : {
19639
19721
  id: "live-route",
@@ -19643,7 +19725,7 @@ var buildLiveRouteCards = ({
19643
19725
  parsedPrimaryVenue.success ? parsedPrimaryVenue.data : void 0
19644
19726
  ),
19645
19727
  executionPrice: averageExecutionPrice,
19646
- numericValue: tradeSide === "sell" ? quoteData.rawExecCost : quoteData.totalFilled,
19728
+ numericValue: getPlaceOrderQuoteValue(quoteData, tradeSide),
19647
19729
  quoteData,
19648
19730
  value: primaryResult.value,
19649
19731
  venue: parsedPrimaryVenue.success ? parsedPrimaryVenue.data : void 0,
@@ -19656,7 +19738,7 @@ var buildLiveRouteCards = ({
19656
19738
  label: isSplit ? labels.orderSplitting : getTradingVenueLabel(
19657
19739
  parsedPrimaryVenue.success ? parsedPrimaryVenue.data : void 0
19658
19740
  ),
19659
- numericValue: tradeSide === "sell" ? quoteData.rawExecCost : quoteData.totalFilled,
19741
+ numericValue: getPlaceOrderQuoteValue(quoteData, tradeSide),
19660
19742
  quoteData,
19661
19743
  rows: mapQuoteDataToRoutingRows(quoteData, tradeSide),
19662
19744
  description: labels.splitOrderDescription,
@@ -19666,7 +19748,7 @@ var buildLiveRouteCards = ({
19666
19748
  requiresSharedKyc: primaryRequiresSharedKyc
19667
19749
  } : null;
19668
19750
  const soloCardId = (prefix, sq) => `${prefix}-${sq.venue}${sq.venueMarketOutcomeId ? `-${sq.venueMarketOutcomeId}` : ""}`;
19669
- const soloCards = ((_c = quoteData.venueSoloQuotes) != null ? _c : []).filter(
19751
+ const soloCards = ((_d = quoteData.venueSoloQuotes) != null ? _d : []).filter(
19670
19752
  (sq) => sq.status === "ok" && sq.unavailableReason !== "venue_unavailable" && sq.avgPrice !== null && sq.filledQty > 0 && // No `sq.quoteId` requirement: a solo is preview-only whenever its own
19671
19753
  // funding lane is short (API nulls the quoteId), which is NOT always the
19672
19754
  // whole-quote `insufficient_balance` case — an off-chain winner (Kalshi
@@ -19674,9 +19756,9 @@ var buildLiveRouteCards = ({
19674
19756
  // stays unfunded. Gating on the quoteId silently hid that venue from the
19675
19757
  // comparison list entirely. The panel's Deposit CTA fires off the same
19676
19758
  // balance condition, and `handleExecuteQuote` rejects an empty quoteId.
19677
- sq.venue !== primaryWinnerVenue
19759
+ (primaryWinnerOutcomeId && sq.venueMarketOutcomeId ? sq.venueMarketOutcomeId !== primaryWinnerOutcomeId : sq.venue !== primaryWinnerVenue)
19678
19760
  ).map((sq) => {
19679
- var _a2, _b2;
19761
+ var _a2, _b2, _c2, _d2, _e2, _f;
19680
19762
  const parsedVenue = parseVenue(sq.venue);
19681
19763
  const venue = parsedVenue.success ? parsedVenue.data : void 0;
19682
19764
  if (geoBlockedVenues.has(sq.venue)) {
@@ -19686,10 +19768,10 @@ var buildLiveRouteCards = ({
19686
19768
  hint: labels.venueUnavailableInRegion,
19687
19769
  kind: "venue",
19688
19770
  label: getTradingVenueLabel(venue),
19689
- numericValue: sq.filledQty,
19771
+ numericValue: (_a2 = sq.estimatedPayout) != null ? _a2 : sq.filledQty,
19690
19772
  quoteData,
19691
19773
  value: getTradingValueLabel({
19692
- amount: sq.filledQty,
19774
+ amount: (_b2 = sq.estimatedPayout) != null ? _b2 : sq.filledQty,
19693
19775
  minimumFractionDigits: 2,
19694
19776
  maximumFractionDigits: 2
19695
19777
  }),
@@ -19703,7 +19785,7 @@ var buildLiveRouteCards = ({
19703
19785
  // Preview-only solos intentionally carry no executable quoteId; the card
19704
19786
  // should still render for comparison, while the CTA stays disabled until
19705
19787
  // the user is funded and requotes.
19706
- quoteId: (_a2 = sq.quoteId) != null ? _a2 : "",
19788
+ quoteId: (_c2 = sq.quoteId) != null ? _c2 : "",
19707
19789
  fills: sq.fills.map((f) => __spreadValues({}, f)),
19708
19790
  totalFilled: sq.filledQty,
19709
19791
  rawExecCost: sq.rawExecCost,
@@ -19716,7 +19798,7 @@ var buildLiveRouteCards = ({
19716
19798
  // primary route's breakdown in place, so selecting a bridge-free venue
19717
19799
  // still showed the primary's bridging charge. Falls back to the
19718
19800
  // primary only when the router omitted one (non-"ok" solos).
19719
- feeBreakdown: (_b2 = sq.feeBreakdown) != null ? _b2 : quoteData.feeBreakdown
19801
+ feeBreakdown: (_d2 = sq.feeBreakdown) != null ? _d2 : quoteData.feeBreakdown
19720
19802
  }), sq.quoteId ? { status: "ok", error: void 0 } : null);
19721
19803
  return {
19722
19804
  id: soloCardId("live-solo", sq),
@@ -19725,10 +19807,10 @@ var buildLiveRouteCards = ({
19725
19807
  kind: "venue",
19726
19808
  label: getTradingVenueLabel(venue),
19727
19809
  executionPrice: avgPrice,
19728
- numericValue: sq.filledQty,
19810
+ numericValue: (_e2 = sq.estimatedPayout) != null ? _e2 : sq.filledQty,
19729
19811
  quoteData: soloQuoteData,
19730
19812
  value: getTradingValueLabel({
19731
- amount: sq.filledQty,
19813
+ amount: (_f = sq.estimatedPayout) != null ? _f : sq.filledQty,
19732
19814
  minimumFractionDigits: 2,
19733
19815
  maximumFractionDigits: 2
19734
19816
  }),
@@ -19736,7 +19818,8 @@ var buildLiveRouteCards = ({
19736
19818
  requiresSharedKyc: venueRequiresSharedKyc({ venue: sq.venue })
19737
19819
  };
19738
19820
  });
19739
- const unavailableCards = ((_d = quoteData.venueSoloQuotes) != null ? _d : []).filter((sq) => sq.status === "unavailable" || sq.unavailableReason === "venue_unavailable").map((sq) => {
19821
+ const unavailableCards = ((_e = quoteData.venueSoloQuotes) != null ? _e : []).filter((sq) => sq.status === "unavailable" || sq.unavailableReason === "venue_unavailable").map((sq) => {
19822
+ var _a2, _b2;
19740
19823
  const parsedVenue = parseVenue(sq.venue);
19741
19824
  const venue = parsedVenue.success ? parsedVenue.data : void 0;
19742
19825
  const temporarilyUnavailable = sq.unavailableReason === "venue_unavailable";
@@ -19747,10 +19830,10 @@ var buildLiveRouteCards = ({
19747
19830
  hint: temporarilyUnavailable ? labels.venueTemporarilyUnavailable : labels.venueUnavailableInRegion,
19748
19831
  kind: "venue",
19749
19832
  label: getTradingVenueLabel(venue),
19750
- numericValue: hasPreview ? sq.filledQty : 0,
19833
+ numericValue: hasPreview ? (_a2 = sq.estimatedPayout) != null ? _a2 : sq.filledQty : 0,
19751
19834
  quoteData: __spreadProps(__spreadValues({}, quoteData), { quoteId: "" }),
19752
19835
  value: hasPreview ? getTradingValueLabel({
19753
- amount: sq.filledQty,
19836
+ amount: (_b2 = sq.estimatedPayout) != null ? _b2 : sq.filledQty,
19754
19837
  minimumFractionDigits: 2,
19755
19838
  maximumFractionDigits: 2
19756
19839
  }) : ""
@@ -19964,10 +20047,13 @@ var getPlaceOrderPotentialReturn = (quoteData) => {
19964
20047
  if (!((_a = quoteData == null ? void 0 : quoteData.fills) == null ? void 0 : _a.length) || quoteData.fills.length < 2) return 0;
19965
20048
  const bestSoloVenueFill = Math.max(
19966
20049
  0,
19967
- ...((_b = quoteData.venueSoloQuotes) != null ? _b : []).filter((quote) => quote.status === "ok" && quote.filledQty > 0).map((quote) => quote.filledQty)
20050
+ ...((_b = quoteData.venueSoloQuotes) != null ? _b : []).filter((quote) => quote.status === "ok" && quote.filledQty > 0).map((quote) => {
20051
+ var _a2;
20052
+ return (_a2 = quote.estimatedPayout) != null ? _a2 : quote.filledQty;
20053
+ })
19968
20054
  );
19969
20055
  if (bestSoloVenueFill <= 0) return 0;
19970
- return Math.max(0, quoteData.totalFilled - bestSoloVenueFill);
20056
+ return Math.max(0, getPlaceOrderBuyPayout(quoteData) - bestSoloVenueFill);
19971
20057
  };
19972
20058
  var resolvePrimarySubmittedOrderId = ({
19973
20059
  allowOrderIdFallback = true,
@@ -23153,7 +23239,16 @@ var PlaceOrder = ({
23153
23239
  });
23154
23240
  const payoutLabel = formatUsd(usdSide);
23155
23241
  const amountLabel = internalTab === "sell" ? sharesLabel : payoutLabel;
23156
- const toWinLabel = internalTab === "sell" ? payoutLabel : formatUsd(sharesSide);
23242
+ const toWinLabel = formatUsd(
23243
+ resolvePlaceOrderNetResult({
23244
+ quoteData,
23245
+ tradeSide: internalTab,
23246
+ shares: sharesSide,
23247
+ usd: usdSide,
23248
+ terminalOrderEvents: executionProgress.terminalOrderEvents,
23249
+ submittedOrders: executionProgress.submittedOrders
23250
+ })
23251
+ );
23157
23252
  const potentialReturnValue = getPlaceOrderPotentialReturn(quoteData);
23158
23253
  const potentialReturnLabel = potentialReturnValue > 0 ? formatUsd(potentialReturnValue) : void 0;
23159
23254
  const eventTitle = (_f2 = (_e2 = scopedSelectedEvent == null ? void 0 : scopedSelectedEvent.title) != null ? _e2 : scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.question) != null ? _f2 : "";
@@ -23557,7 +23652,16 @@ var PlaceOrder = ({
23557
23652
  maximumFractionDigits: 2
23558
23653
  })
23559
23654
  ) : formatUsd(actualEconomics.actualRawExecCost);
23560
- const payoutLabel = isSell ? formatUsd(actualEconomics.actualRawExecCost) : formatUsd(actualEconomics.actualTotalFilled);
23655
+ const payoutLabel = formatUsd(
23656
+ resolvePlaceOrderNetResult({
23657
+ quoteData,
23658
+ tradeSide: internalTab,
23659
+ shares: actualEconomics.actualTotalFilled,
23660
+ usd: actualEconomics.actualRawExecCost,
23661
+ terminalOrderEvents: executionProgress.terminalOrderEvents,
23662
+ submittedOrders: executionProgress.submittedOrders
23663
+ })
23664
+ );
23561
23665
  return __spreadProps(__spreadValues({}, summaryWithGroups), {
23562
23666
  actions: summaryWithGroups.actions.map(
23563
23667
  (action) => action.variant === "retry" ? __spreadProps(__spreadValues({}, action), { label: tradingLabels.orderTryRemaining(remainingLabel) }) : action
@@ -26887,6 +26991,16 @@ var aggregateSportsLineStops = (markets, isSpread = false) => {
26887
26991
  (left, right) => left.lineValue !== right.lineValue ? left.lineValue - right.lineValue : left.value.localeCompare(right.value)
26888
26992
  );
26889
26993
  };
26994
+ var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
26995
+ var resolveSportsLadderTitle = (group, selectedLineDisplay) => {
26996
+ var _a;
26997
+ const anchorLineValue = (_a = group.markets[0]) == null ? void 0 : _a.lineValue;
26998
+ if (anchorLineValue == null || !selectedLineDisplay) return group.title;
26999
+ const anchorDisplay = resolveSelectedSportsLineValue(anchorLineValue);
27000
+ if (anchorDisplay === selectedLineDisplay) return group.title;
27001
+ const pattern = new RegExp(`(^|[^\\d.])${escapeRegExp(anchorDisplay)}(?![\\d.])`);
27002
+ return pattern.test(group.title) ? group.title.replace(pattern, (_match, prefix) => `${prefix}${selectedLineDisplay}`) : group.title;
27003
+ };
26890
27004
  var buildSportsSlideFromGroup = (group) => {
26891
27005
  const lineStops = group.hasLineVariants ? aggregateSportsLineStops(group.markets, group.sportsMarketType === "spread") : [];
26892
27006
  const hasLadder = lineStops.length > 1;
@@ -27395,6 +27509,8 @@ var SportsMarketCard = ({
27395
27509
  });
27396
27510
  }, [slide.kind, activeMarket, group.markets, midpointsResult]);
27397
27511
  if (!activeMarket) return null;
27512
+ const selectedStop = slide.hasLadder ? slide.stops[selectedLineIndex] : void 0;
27513
+ const cardTitle = selectedStop ? resolveSportsLadderTitle(group, selectedStop.value) : group.title;
27398
27514
  const activeOutcome = (_h = activeMarket.venueMarketOutcomes.find(
27399
27515
  (outcome) => outcome.id === (tradingContext == null ? void 0 : tradingContext.selectedOutcomeId)
27400
27516
  )) != null ? _h : activeDefaultOutcome;
@@ -27455,7 +27571,7 @@ var SportsMarketCard = ({
27455
27571
  {
27456
27572
  marketId: activeMarket.id,
27457
27573
  venueMarkets,
27458
- title: group.title,
27574
+ title: cardTitle,
27459
27575
  compactHeader: true,
27460
27576
  subtitleOverride: compactSubtitle,
27461
27577
  headerOutcomeVariant,
@@ -27474,9 +27590,9 @@ var SportsMarketCard = ({
27474
27590
  })),
27475
27591
  selectedIndex: selectedLineIndex,
27476
27592
  onSelect: handleLineSelect,
27477
- ariaLabel: labels.eventMarketPage.sports.lineSelectorAria(group.title),
27478
- previousAriaLabel: labels.eventMarketPage.sports.previousLineAria(group.title),
27479
- nextAriaLabel: labels.eventMarketPage.sports.nextLineAria(group.title)
27593
+ ariaLabel: labels.eventMarketPage.sports.lineSelectorAria(cardTitle),
27594
+ previousAriaLabel: labels.eventMarketPage.sports.previousLineAria(cardTitle),
27595
+ nextAriaLabel: labels.eventMarketPage.sports.nextLineAria(cardTitle)
27480
27596
  }
27481
27597
  ) : void 0,
27482
27598
  classNames: { root: "agg-market-list-item agg-sports-market-card" },
package/dist/pages.mjs CHANGED
@@ -11,14 +11,14 @@ import {
11
11
  formatRecurringCountdown,
12
12
  formatShareAmount,
13
13
  useHomePageModals
14
- } from "./chunk-VMG6BUHI.mjs";
15
- import "./chunk-EYJS45RP.mjs";
14
+ } from "./chunk-VAL2IB3M.mjs";
15
+ import "./chunk-IS45S6R3.mjs";
16
16
  import {
17
17
  DEPOSIT_MODAL_OPEN_EVENT,
18
18
  WITHDRAW_MODAL_OPEN_EVENT,
19
19
  requestAggDepositModalOpen,
20
20
  requestAggWithdrawModalOpen
21
- } from "./chunk-WWIVSROM.mjs";
21
+ } from "./chunk-VHKGW4DB.mjs";
22
22
  import "./chunk-6EHT5OFU.mjs";
23
23
  import "./chunk-TXQJUVRW.mjs";
24
24
  import "./chunk-W7HQVQ22.mjs";
package/dist/trading.js CHANGED
@@ -9315,6 +9315,72 @@ var parseDecimalString = (value) => {
9315
9315
  if (!Number.isFinite(parsed) || parsed <= 0) return null;
9316
9316
  return parsed;
9317
9317
  };
9318
+ var getPlaceOrderBuyPayout = (quoteData) => {
9319
+ var _a;
9320
+ return (_a = quoteData.estimatedPayout) != null ? _a : quoteData.totalFilled;
9321
+ };
9322
+ var getPlaceOrderSellProceeds = (quoteData) => Math.max(
9323
+ 0,
9324
+ quoteData.rawExecCost - quoteData.fills.reduce((sum, fill) => {
9325
+ var _a, _b;
9326
+ return sum + ((_a = fill.venueFee) != null ? _a : 0) + ((_b = fill.builderFee) != null ? _b : 0);
9327
+ }, 0)
9328
+ );
9329
+ var getPlaceOrderQuoteValue = (quoteData, tradeSide) => tradeSide === "sell" ? getPlaceOrderSellProceeds(quoteData) : getPlaceOrderBuyPayout(quoteData);
9330
+ var resolvePlaceOrderNetResult = ({
9331
+ quoteData,
9332
+ tradeSide,
9333
+ shares,
9334
+ usd,
9335
+ terminalOrderEvents,
9336
+ submittedOrders
9337
+ }) => {
9338
+ if (!quoteData) return tradeSide === "sell" ? usd : shares;
9339
+ const actualEvents = (terminalOrderEvents != null ? terminalOrderEvents : []).filter(
9340
+ (event) => (event.event === "filled" || event.event === "partial_fill") && (tradeSide === "buy" ? event.filledAmountRaw != null : event.actualSharesRaw != null)
9341
+ );
9342
+ if (actualEvents.length) {
9343
+ return actualEvents.reduce((sum, event) => {
9344
+ var _a;
9345
+ const outcomeId = (_a = submittedOrders == null ? void 0 : submittedOrders.find(
9346
+ (order) => order.orderId === event.orderId
9347
+ )) == null ? void 0 : _a.outcomeId;
9348
+ const venueFills = quoteData.fills.filter((fill) => fill.venue === event.venue);
9349
+ const exactFill = venueFills.find((fill) => fill.venueMarketOutcomeId === outcomeId);
9350
+ const fills = exactFill ? [exactFill] : venueFills;
9351
+ const legQuote = fills.length ? __spreadProps(__spreadValues({}, quoteData), {
9352
+ fills,
9353
+ totalFilled: fills.reduce((total, fill) => total + fill.venueQty, 0),
9354
+ rawExecCost: fills.reduce((total, fill) => total + fill.avgPrice * fill.venueQty, 0),
9355
+ estimatedPayout: fills.reduce(
9356
+ (total, fill) => {
9357
+ var _a2;
9358
+ return total + fill.venueQty - ((_a2 = fill.settlementFee) != null ? _a2 : 0);
9359
+ },
9360
+ 0
9361
+ )
9362
+ }) : quoteData;
9363
+ const actual = resolveActualExecutionEconomics({
9364
+ quoteData: legQuote,
9365
+ tradeSide,
9366
+ terminalOrderEvents: [event],
9367
+ submittedOrders
9368
+ });
9369
+ return sum + resolvePlaceOrderNetResult({
9370
+ quoteData: legQuote,
9371
+ tradeSide,
9372
+ shares: actual.actualTotalFilled,
9373
+ usd: actual.actualRawExecCost
9374
+ });
9375
+ }, 0);
9376
+ }
9377
+ if (tradeSide === "sell") {
9378
+ const gross = quoteData.rawExecCost;
9379
+ return gross > 0 ? usd * (getPlaceOrderSellProceeds(quoteData) / gross) : usd;
9380
+ }
9381
+ const filled = quoteData.totalFilled;
9382
+ return filled > 0 ? shares * (getPlaceOrderBuyPayout(quoteData) / filled) : shares;
9383
+ };
9318
9384
  var resolvePlaceOrderQuoteResult = ({
9319
9385
  labels,
9320
9386
  quoteData,
@@ -9323,7 +9389,7 @@ var resolvePlaceOrderQuoteResult = ({
9323
9389
  if (!quoteData || quoteData.totalFilled <= 0) return null;
9324
9390
  const avgPrice = getPlaceOrderAverageExecutionPrice(quoteData);
9325
9391
  if (avgPrice == null) return null;
9326
- const quoteValue = tradeSide === "sell" ? quoteData.rawExecCost : quoteData.totalFilled;
9392
+ const quoteValue = getPlaceOrderQuoteValue(quoteData, tradeSide);
9327
9393
  return {
9328
9394
  hint: labels.averagePrice(avgPrice),
9329
9395
  value: getTradingValueLabel({
@@ -9441,7 +9507,7 @@ var buildLiveRouteCards = ({
9441
9507
  eventVenues = [],
9442
9508
  geoBlockedVenues: inheritedGeoBlockedVenues
9443
9509
  }) => {
9444
- var _a, _b, _c, _d;
9510
+ var _a, _b, _c, _d, _e;
9445
9511
  const geoBlockedVenues = extractGeoBlockedVenues(quoteData.warnings);
9446
9512
  for (const venue of inheritedGeoBlockedVenues != null ? inheritedGeoBlockedVenues : []) {
9447
9513
  geoBlockedVenues.add(venue);
@@ -9456,6 +9522,7 @@ var buildLiveRouteCards = ({
9456
9522
  );
9457
9523
  const averageExecutionPrice = (_b = getPlaceOrderAverageExecutionPrice(quoteData)) != null ? _b : void 0;
9458
9524
  const primaryWinnerVenue = quoteData.fills.length === 1 ? primaryVenue : void 0;
9525
+ const primaryWinnerOutcomeId = quoteData.fills.length === 1 ? (_c = quoteData.fills[0]) == null ? void 0 : _c.venueMarketOutcomeId : void 0;
9459
9526
  const isPrimaryRouteGeoBlocked = quoteData.fills.length > 0 && quoteData.fills.some((f) => geoBlockedVenues.has(f.venue));
9460
9527
  const primaryCard = primaryResult ? isPrimaryRouteGeoBlocked ? isSplit ? null : {
9461
9528
  id: "live-route",
@@ -9465,7 +9532,7 @@ var buildLiveRouteCards = ({
9465
9532
  parsedPrimaryVenue.success ? parsedPrimaryVenue.data : void 0
9466
9533
  ),
9467
9534
  executionPrice: averageExecutionPrice,
9468
- numericValue: tradeSide === "sell" ? quoteData.rawExecCost : quoteData.totalFilled,
9535
+ numericValue: getPlaceOrderQuoteValue(quoteData, tradeSide),
9469
9536
  quoteData,
9470
9537
  value: primaryResult.value,
9471
9538
  venue: parsedPrimaryVenue.success ? parsedPrimaryVenue.data : void 0,
@@ -9478,7 +9545,7 @@ var buildLiveRouteCards = ({
9478
9545
  label: isSplit ? labels.orderSplitting : getTradingVenueLabel(
9479
9546
  parsedPrimaryVenue.success ? parsedPrimaryVenue.data : void 0
9480
9547
  ),
9481
- numericValue: tradeSide === "sell" ? quoteData.rawExecCost : quoteData.totalFilled,
9548
+ numericValue: getPlaceOrderQuoteValue(quoteData, tradeSide),
9482
9549
  quoteData,
9483
9550
  rows: mapQuoteDataToRoutingRows(quoteData, tradeSide),
9484
9551
  description: labels.splitOrderDescription,
@@ -9488,7 +9555,7 @@ var buildLiveRouteCards = ({
9488
9555
  requiresSharedKyc: primaryRequiresSharedKyc
9489
9556
  } : null;
9490
9557
  const soloCardId = (prefix, sq) => `${prefix}-${sq.venue}${sq.venueMarketOutcomeId ? `-${sq.venueMarketOutcomeId}` : ""}`;
9491
- const soloCards = ((_c = quoteData.venueSoloQuotes) != null ? _c : []).filter(
9558
+ const soloCards = ((_d = quoteData.venueSoloQuotes) != null ? _d : []).filter(
9492
9559
  (sq) => sq.status === "ok" && sq.unavailableReason !== "venue_unavailable" && sq.avgPrice !== null && sq.filledQty > 0 && // No `sq.quoteId` requirement: a solo is preview-only whenever its own
9493
9560
  // funding lane is short (API nulls the quoteId), which is NOT always the
9494
9561
  // whole-quote `insufficient_balance` case — an off-chain winner (Kalshi
@@ -9496,9 +9563,9 @@ var buildLiveRouteCards = ({
9496
9563
  // stays unfunded. Gating on the quoteId silently hid that venue from the
9497
9564
  // comparison list entirely. The panel's Deposit CTA fires off the same
9498
9565
  // balance condition, and `handleExecuteQuote` rejects an empty quoteId.
9499
- sq.venue !== primaryWinnerVenue
9566
+ (primaryWinnerOutcomeId && sq.venueMarketOutcomeId ? sq.venueMarketOutcomeId !== primaryWinnerOutcomeId : sq.venue !== primaryWinnerVenue)
9500
9567
  ).map((sq) => {
9501
- var _a2, _b2;
9568
+ var _a2, _b2, _c2, _d2, _e2, _f;
9502
9569
  const parsedVenue = parseVenue(sq.venue);
9503
9570
  const venue = parsedVenue.success ? parsedVenue.data : void 0;
9504
9571
  if (geoBlockedVenues.has(sq.venue)) {
@@ -9508,10 +9575,10 @@ var buildLiveRouteCards = ({
9508
9575
  hint: labels.venueUnavailableInRegion,
9509
9576
  kind: "venue",
9510
9577
  label: getTradingVenueLabel(venue),
9511
- numericValue: sq.filledQty,
9578
+ numericValue: (_a2 = sq.estimatedPayout) != null ? _a2 : sq.filledQty,
9512
9579
  quoteData,
9513
9580
  value: getTradingValueLabel({
9514
- amount: sq.filledQty,
9581
+ amount: (_b2 = sq.estimatedPayout) != null ? _b2 : sq.filledQty,
9515
9582
  minimumFractionDigits: 2,
9516
9583
  maximumFractionDigits: 2
9517
9584
  }),
@@ -9525,7 +9592,7 @@ var buildLiveRouteCards = ({
9525
9592
  // Preview-only solos intentionally carry no executable quoteId; the card
9526
9593
  // should still render for comparison, while the CTA stays disabled until
9527
9594
  // the user is funded and requotes.
9528
- quoteId: (_a2 = sq.quoteId) != null ? _a2 : "",
9595
+ quoteId: (_c2 = sq.quoteId) != null ? _c2 : "",
9529
9596
  fills: sq.fills.map((f) => __spreadValues({}, f)),
9530
9597
  totalFilled: sq.filledQty,
9531
9598
  rawExecCost: sq.rawExecCost,
@@ -9538,7 +9605,7 @@ var buildLiveRouteCards = ({
9538
9605
  // primary route's breakdown in place, so selecting a bridge-free venue
9539
9606
  // still showed the primary's bridging charge. Falls back to the
9540
9607
  // primary only when the router omitted one (non-"ok" solos).
9541
- feeBreakdown: (_b2 = sq.feeBreakdown) != null ? _b2 : quoteData.feeBreakdown
9608
+ feeBreakdown: (_d2 = sq.feeBreakdown) != null ? _d2 : quoteData.feeBreakdown
9542
9609
  }), sq.quoteId ? { status: "ok", error: void 0 } : null);
9543
9610
  return {
9544
9611
  id: soloCardId("live-solo", sq),
@@ -9547,10 +9614,10 @@ var buildLiveRouteCards = ({
9547
9614
  kind: "venue",
9548
9615
  label: getTradingVenueLabel(venue),
9549
9616
  executionPrice: avgPrice,
9550
- numericValue: sq.filledQty,
9617
+ numericValue: (_e2 = sq.estimatedPayout) != null ? _e2 : sq.filledQty,
9551
9618
  quoteData: soloQuoteData,
9552
9619
  value: getTradingValueLabel({
9553
- amount: sq.filledQty,
9620
+ amount: (_f = sq.estimatedPayout) != null ? _f : sq.filledQty,
9554
9621
  minimumFractionDigits: 2,
9555
9622
  maximumFractionDigits: 2
9556
9623
  }),
@@ -9558,7 +9625,8 @@ var buildLiveRouteCards = ({
9558
9625
  requiresSharedKyc: venueRequiresSharedKyc({ venue: sq.venue })
9559
9626
  };
9560
9627
  });
9561
- const unavailableCards = ((_d = quoteData.venueSoloQuotes) != null ? _d : []).filter((sq) => sq.status === "unavailable" || sq.unavailableReason === "venue_unavailable").map((sq) => {
9628
+ const unavailableCards = ((_e = quoteData.venueSoloQuotes) != null ? _e : []).filter((sq) => sq.status === "unavailable" || sq.unavailableReason === "venue_unavailable").map((sq) => {
9629
+ var _a2, _b2;
9562
9630
  const parsedVenue = parseVenue(sq.venue);
9563
9631
  const venue = parsedVenue.success ? parsedVenue.data : void 0;
9564
9632
  const temporarilyUnavailable = sq.unavailableReason === "venue_unavailable";
@@ -9569,10 +9637,10 @@ var buildLiveRouteCards = ({
9569
9637
  hint: temporarilyUnavailable ? labels.venueTemporarilyUnavailable : labels.venueUnavailableInRegion,
9570
9638
  kind: "venue",
9571
9639
  label: getTradingVenueLabel(venue),
9572
- numericValue: hasPreview ? sq.filledQty : 0,
9640
+ numericValue: hasPreview ? (_a2 = sq.estimatedPayout) != null ? _a2 : sq.filledQty : 0,
9573
9641
  quoteData: __spreadProps(__spreadValues({}, quoteData), { quoteId: "" }),
9574
9642
  value: hasPreview ? getTradingValueLabel({
9575
- amount: sq.filledQty,
9643
+ amount: (_b2 = sq.estimatedPayout) != null ? _b2 : sq.filledQty,
9576
9644
  minimumFractionDigits: 2,
9577
9645
  maximumFractionDigits: 2
9578
9646
  }) : ""
@@ -9786,10 +9854,13 @@ var getPlaceOrderPotentialReturn = (quoteData) => {
9786
9854
  if (!((_a = quoteData == null ? void 0 : quoteData.fills) == null ? void 0 : _a.length) || quoteData.fills.length < 2) return 0;
9787
9855
  const bestSoloVenueFill = Math.max(
9788
9856
  0,
9789
- ...((_b = quoteData.venueSoloQuotes) != null ? _b : []).filter((quote) => quote.status === "ok" && quote.filledQty > 0).map((quote) => quote.filledQty)
9857
+ ...((_b = quoteData.venueSoloQuotes) != null ? _b : []).filter((quote) => quote.status === "ok" && quote.filledQty > 0).map((quote) => {
9858
+ var _a2;
9859
+ return (_a2 = quote.estimatedPayout) != null ? _a2 : quote.filledQty;
9860
+ })
9790
9861
  );
9791
9862
  if (bestSoloVenueFill <= 0) return 0;
9792
- return Math.max(0, quoteData.totalFilled - bestSoloVenueFill);
9863
+ return Math.max(0, getPlaceOrderBuyPayout(quoteData) - bestSoloVenueFill);
9793
9864
  };
9794
9865
  var resolvePrimarySubmittedOrderId = ({
9795
9866
  allowOrderIdFallback = true,
@@ -12975,7 +13046,16 @@ var PlaceOrder = ({
12975
13046
  });
12976
13047
  const payoutLabel = formatUsd(usdSide);
12977
13048
  const amountLabel = internalTab === "sell" ? sharesLabel : payoutLabel;
12978
- const toWinLabel = internalTab === "sell" ? payoutLabel : formatUsd(sharesSide);
13049
+ const toWinLabel = formatUsd(
13050
+ resolvePlaceOrderNetResult({
13051
+ quoteData,
13052
+ tradeSide: internalTab,
13053
+ shares: sharesSide,
13054
+ usd: usdSide,
13055
+ terminalOrderEvents: executionProgress.terminalOrderEvents,
13056
+ submittedOrders: executionProgress.submittedOrders
13057
+ })
13058
+ );
12979
13059
  const potentialReturnValue = getPlaceOrderPotentialReturn(quoteData);
12980
13060
  const potentialReturnLabel = potentialReturnValue > 0 ? formatUsd(potentialReturnValue) : void 0;
12981
13061
  const eventTitle = (_f2 = (_e2 = scopedSelectedEvent == null ? void 0 : scopedSelectedEvent.title) != null ? _e2 : scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.question) != null ? _f2 : "";
@@ -13379,7 +13459,16 @@ var PlaceOrder = ({
13379
13459
  maximumFractionDigits: 2
13380
13460
  })
13381
13461
  ) : formatUsd(actualEconomics.actualRawExecCost);
13382
- const payoutLabel = isSell ? formatUsd(actualEconomics.actualRawExecCost) : formatUsd(actualEconomics.actualTotalFilled);
13462
+ const payoutLabel = formatUsd(
13463
+ resolvePlaceOrderNetResult({
13464
+ quoteData,
13465
+ tradeSide: internalTab,
13466
+ shares: actualEconomics.actualTotalFilled,
13467
+ usd: actualEconomics.actualRawExecCost,
13468
+ terminalOrderEvents: executionProgress.terminalOrderEvents,
13469
+ submittedOrders: executionProgress.submittedOrders
13470
+ })
13471
+ );
13383
13472
  return __spreadProps(__spreadValues({}, summaryWithGroups), {
13384
13473
  actions: summaryWithGroups.actions.map(
13385
13474
  (action) => action.variant === "retry" ? __spreadProps(__spreadValues({}, action), { label: tradingLabels.orderTryRemaining(remainingLabel) }) : action
package/dist/trading.mjs CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  useClaimWinnings,
15
15
  useResolvedMarketClaim,
16
16
  venueRequiresSharedKyc
17
- } from "./chunk-WWIVSROM.mjs";
17
+ } from "./chunk-VHKGW4DB.mjs";
18
18
  import {
19
19
  SETTLEMENT_SECTION_ID,
20
20
  Settlement,