@agg-build/ui 4.23.0 → 4.26.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/index.js CHANGED
@@ -20090,7 +20090,8 @@ var init_market_details = __esm({
20090
20090
  var _a, _b, _c;
20091
20091
  const labels = (0, import_hooks63.useLabels)();
20092
20092
  const {
20093
- features: { enableLiveUpdates }
20093
+ features: { enableLiveUpdates },
20094
+ market: { minVolume }
20094
20095
  } = (0, import_hooks63.useSdkUiConfig)();
20095
20096
  const tradingContext = (0, import_hooks63.useEventTradingContext)();
20096
20097
  const selectedMarketId = (_a = tradingContext == null ? void 0 : tradingContext.selectedMarketId) != null ? _a : null;
@@ -20110,7 +20111,9 @@ var init_market_details = __esm({
20110
20111
  // fetchAll drains every page — events can exceed any single-page limit
20111
20112
  // (e.g. 80 open markets on one staging event).
20112
20113
  limit: 100,
20113
- fetchAll: true
20114
+ fetchAll: true,
20115
+ // Same minVolume as useEnrichedVenueEvent's open query (also in the key).
20116
+ minVolume
20114
20117
  // No explicit sortBy: event-scoped /venue-markets sorts by the event's
20115
20118
  // type-aware order (structureOrderBy), matching the home-card top-3 and the
20116
20119
  // markets-under-an-event ordering. Passing sortBy here would override it.
@@ -24159,7 +24162,7 @@ function lookupRevertSelectorMessage(message) {
24159
24162
  if (!selector) return null;
24160
24163
  return (_b = REVERT_SELECTOR_MESSAGES[selector]) != null ? _b : null;
24161
24164
  }
24162
- var import_sdk27, ATOMIC_UNITS, ATOMIC_UNITS_BIGINT, getPlaceOrderBalanceCacheKey, routePriceLabelFormatter, GEO_BLOCK_WARNING_PREFIX, isFiniteNonNegativePrice, getPlaceOrderAverageExecutionPrice, floorToDecimals, formatFlooredShareAmount, normalizeOutcomeName, findMatchingVenueOutcome, resolveSellableSharesByVenue, buildLimitOrderVenueOptions, resolveAutomaticLimitOrderVenueOption, isGeoBlockWarningReason, extractGeoBlockedVenues, getSmartRouteTotalFees, getPlaceOrderContainerClassName, resolveIsPositiveOutcome, getOutcomeButtonClassName, sortOutcomesYesFirst, mapVenueMarketOutcomesToPlaceOrderOutcomes, mapQuoteDataToRoutingRows, deriveAggregateOrderStatus, parseFilledAmountRawDollars, parseDecimalString, getPlaceOrderBuyPayout, getPlaceOrderSellProceeds, getPlaceOrderQuoteValue, resolvePlaceOrderNetResult, resolvePlaceOrderQuoteResult, getTradingRoutePriceLabel, isQuoteBelowVenueMinimum, resolvePlaceOrderQuoteStatus, buildLiveRouteCards, routeCardRequiresKalshi, resolveDefaultRouteCardId, getPlaceOrderRouteCardIdentity, sellSharesToAtomicUnits, atomicUnitsToSellShares, clampSellSharesToAvailability, hasInsufficientVenueInventory, getRemainingVenueSellShares, buildVenueSellQuoteRequests, buildLiveSellRouteCards, resolveExecutionVenueFromQuote, routeCardsHaveSameVenueIdentity, getPlaceOrderPotentialReturn, resolvePrimarySubmittedOrderId, normalizeOrderIdLabelInput, buildPlaceOrderExecutionStepGroups, groupPlaceOrderFailureSteps, buildPlaceOrderExecutionStepGroupsFromFailureSummary, MARKET_RESOLVED_ERROR_PATTERN, VENUE_UNAVAILABLE_ERROR_PATTERN, ALCHEMY_SPONSORSHIP_ERROR_PATTERN, ALCHEMY_PREPARE_CALLS_ERROR_PATTERN, DAG_CHECK_BALANCE_SHORTFALL_PATTERN, VENUE_CONNECTOR_UNREACHABLE_PATTERN, POLYMARKET_DEADLINE_TOO_SOON_PATTERN, SELL_NO_ONCHAIN_POSITION_PATTERN, VENUE_QUOTE_UNFILLABLE_PATTERN, QUOTED_PRICE_UNAVAILABLE_PATTERN, VENUE_MIN_ORDER_SIZE_PATTERN, SOURCE_BALANCE_CHANGED_PATTERN, VENUE_MARKET_RESOLVED_PATTERN, DFLOW_WALLET_UNVERIFIED_PATTERN, VENUE_NO_QUOTE_PATH_PATTERN, SOLANA_BLOCKHASH_EXPIRED_PATTERN, VENUE_RATE_LIMITED_PATTERN, SERVICE_BLOCKED_ORDER_PATTERN, ALCHEMY_BALANCE_REVERT_PATTERN, ALCHEMY_REVERT_DATA_SELECTOR_PATTERN, REVERT_SELECTOR_MESSAGES, ALCHEMY_SPONSORSHIP_POLICY_PATTERN, ALCHEMY_POLICY_MAX_COUNT_PATTERN, ORDER_FAILED_PREFIX_PATTERN, VENUE_TERMINATED_STATUS_PATTERN, friendlyTerminatedStatusMessage, tryParseJsonErrorValue, extractPlaceOrderErrorMessage, normalizePlaceOrderErrorMessage, resolvePlaceOrderFailureKind, resolveFailedVenueStep, resolvePlaceOrderFailureActions, resolveEventExecutionPrice, resolveActualExecutionEconomics, getPlaceOrderUnfilledRemaining, getCanonicalPlaceOrderUnfilledRemaining, buildPlaceOrderFailureSummary, buildPlaceOrderShareText, resolveNextTabFromKey, sanitizePercentageInput, finalizePercentageValue, parsePercentageValue, formatPercentageValue, isPercentageBelowMinimum;
24165
+ var import_sdk27, ATOMIC_UNITS, ATOMIC_UNITS_BIGINT, getPlaceOrderBalanceCacheKey, routePriceLabelFormatter, GEO_BLOCK_WARNING_PREFIX, isFiniteNonNegativePrice, getPlaceOrderAverageExecutionPrice, floorToDecimals, formatFlooredShareAmount, normalizeOutcomeName, findMatchingVenueOutcome, resolveSellableSharesByVenue, buildLimitOrderVenueOptions, resolveAutomaticLimitOrderVenueOption, isGeoBlockWarningReason, extractGeoBlockedVenues, getSmartRouteTotalFees, getPlaceOrderContainerClassName, resolveIsPositiveOutcome, getOutcomeButtonClassName, sortOutcomesYesFirst, mapVenueMarketOutcomesToPlaceOrderOutcomes, mapQuoteDataToRoutingRows, deriveAggregateOrderStatus, parseFilledAmountRawDollars, parseDecimalString, getPlaceOrderBuyPayout, getPlaceOrderSellProceeds, getPlaceOrderQuoteValue, resolvePlaceOrderNetResult, resolvePlaceOrderQuoteResult, getTradingRoutePriceLabel, isQuoteBelowVenueMinimum, resolvePlaceOrderQuoteStatus, buildLiveRouteCards, routeCardRequiresKalshi, resolveDefaultRouteCardId, getPlaceOrderRouteCardIdentity, sellSharesToAtomicUnits, atomicUnitsToSellShares, clampSellSharesToAvailability, hasInsufficientVenueInventory, getRemainingVenueSellShares, buildVenueSellQuoteRequests, buildLiveSellRouteCards, resolveExecutionVenueFromQuote, routeCardsHaveSameVenueIdentity, getPlaceOrderPotentialReturn, resolvePrimarySubmittedOrderId, normalizeOrderIdLabelInput, buildPlaceOrderExecutionStepGroups, groupPlaceOrderFailureSteps, buildPlaceOrderExecutionStepGroupsFromFailureSummary, MARKET_RESOLVED_ERROR_PATTERN, VENUE_UNAVAILABLE_ERROR_PATTERN, ALCHEMY_SPONSORSHIP_ERROR_PATTERN, ALCHEMY_PREPARE_CALLS_ERROR_PATTERN, DAG_CHECK_BALANCE_SHORTFALL_PATTERN, VENUE_CONNECTOR_UNREACHABLE_PATTERN, POLYMARKET_DEADLINE_TOO_SOON_PATTERN, SELL_NO_ONCHAIN_POSITION_PATTERN, VENUE_QUOTE_UNFILLABLE_PATTERN, QUOTED_PRICE_UNAVAILABLE_PATTERN, VENUE_MIN_ORDER_SIZE_PATTERN, SOURCE_BALANCE_CHANGED_PATTERN, VENUE_MARKET_RESOLVED_PATTERN, DFLOW_WALLET_UNVERIFIED_PATTERN, VENUE_NO_QUOTE_PATH_PATTERN, SOLANA_BLOCKHASH_EXPIRED_PATTERN, VENUE_RATE_LIMITED_PATTERN, SERVICE_BLOCKED_ORDER_PATTERN, ALCHEMY_BALANCE_REVERT_PATTERN, ALCHEMY_REVERT_DATA_SELECTOR_PATTERN, REVERT_SELECTOR_MESSAGES, ALCHEMY_SPONSORSHIP_POLICY_PATTERN, ALCHEMY_POLICY_MAX_COUNT_PATTERN, ORDER_FAILED_PREFIX_PATTERN, VENUE_TERMINATED_STATUS_PATTERN, friendlyTerminatedStatusMessage, tryParseJsonErrorValue, extractPlaceOrderErrorMessage, normalizePlaceOrderErrorMessage, resolvePlaceOrderFailureKind, resolveFailedVenueStep, resolvePlaceOrderFailureActions, resolveEventExecutionPrice, resolveActualExecutionEconomics, getPlaceOrderUnfilledRemaining, getCanonicalPlaceOrderUnfilledRemaining, buildPlaceOrderFailureSummary, buildPlaceOrderShareText, resolveNextTabFromKey, sanitizePercentageInput, finalizePercentageValue, parsePercentageValue, formatPercentageValue, isPercentageBelowMinimum, ceilDiv, toRaw6, parseSizeStepRaw, toLimitSizeRaw, isLimitSizeBelowMinimum;
24163
24166
  var init_index_place_order_utils = __esm({
24164
24167
  "src/trading/place-order/index.place-order.utils.ts"() {
24165
24168
  "use strict";
@@ -24486,13 +24489,16 @@ var init_index_place_order_utils = __esm({
24486
24489
  var _a;
24487
24490
  return (_a = quoteData.estimatedPayout) != null ? _a : quoteData.totalFilled;
24488
24491
  };
24489
- getPlaceOrderSellProceeds = (quoteData) => Math.max(
24490
- 0,
24491
- quoteData.rawExecCost - quoteData.fills.reduce((sum, fill) => {
24492
- var _a, _b;
24493
- return sum + ((_a = fill.venueFee) != null ? _a : 0) + ((_b = fill.builderFee) != null ? _b : 0);
24494
- }, 0)
24495
- );
24492
+ getPlaceOrderSellProceeds = (quoteData) => {
24493
+ var _a;
24494
+ return (_a = quoteData.estimatedNetProceeds) != null ? _a : Math.max(
24495
+ 0,
24496
+ quoteData.rawExecCost - quoteData.fills.reduce((sum, fill) => {
24497
+ var _a2, _b;
24498
+ return sum + ((_a2 = fill.venueFee) != null ? _a2 : 0) + ((_b = fill.builderFee) != null ? _b : 0);
24499
+ }, 0)
24500
+ );
24501
+ };
24496
24502
  getPlaceOrderQuoteValue = (quoteData, tradeSide) => tradeSide === "sell" ? getPlaceOrderSellProceeds(quoteData) : getPlaceOrderBuyPayout(quoteData);
24497
24503
  resolvePlaceOrderNetResult = ({
24498
24504
  quoteData,
@@ -25840,6 +25846,38 @@ var init_index_place_order_utils = __esm({
25840
25846
  if (parsedValue === null) return false;
25841
25847
  return parsedValue < minimumValue;
25842
25848
  };
25849
+ ceilDiv = (numerator, denominator) => {
25850
+ return (numerator + denominator - BigInt(1)) / denominator;
25851
+ };
25852
+ toRaw6 = (value) => {
25853
+ const normalizedValue = Number.isFinite(value) ? Math.max(0, value) : 0;
25854
+ return Math.ceil(normalizedValue * Number(import_sdk27.LIMIT_PRICE_RAW_SCALE)).toString();
25855
+ };
25856
+ parseSizeStepRaw = (sizeStepRaw) => {
25857
+ if (!sizeStepRaw || !/^[1-9]\d*$/.test(sizeStepRaw)) return BigInt(1);
25858
+ return BigInt(sizeStepRaw);
25859
+ };
25860
+ toLimitSizeRaw = ({
25861
+ amount: amount2,
25862
+ limitPriceRaw,
25863
+ side,
25864
+ sizeStepRaw
25865
+ }) => {
25866
+ const step = parseSizeStepRaw(sizeStepRaw);
25867
+ if (step <= BigInt(1)) {
25868
+ if (side === "sell") return toRaw6(amount2);
25869
+ const spendRaw = BigInt(toRaw6(amount2));
25870
+ const priceRaw = BigInt(limitPriceRaw);
25871
+ return ceilDiv(spendRaw * import_sdk27.LIMIT_PRICE_RAW_SCALE, priceRaw).toString();
25872
+ }
25873
+ const rawSize = side === "sell" ? BigInt(toRaw6(amount2)) : BigInt(toRaw6(amount2)) * import_sdk27.LIMIT_PRICE_RAW_SCALE / BigInt(limitPriceRaw);
25874
+ return (rawSize / step * step).toString();
25875
+ };
25876
+ isLimitSizeBelowMinimum = (sizeRaw, minSizeRaw) => {
25877
+ const size = BigInt(sizeRaw);
25878
+ if (size <= BigInt(0)) return true;
25879
+ return !!minSizeRaw && /^\d+$/.test(minSizeRaw) && size < BigInt(minSizeRaw);
25880
+ };
25843
25881
  }
25844
25882
  });
25845
25883
 
@@ -26934,7 +26972,7 @@ var init_index_place_order_success = __esm({
26934
26972
  });
26935
26973
 
26936
26974
  // src/trading/place-order/index.tsx
26937
- var import_hooks89, import_sdk28, import_react58, Popover, import_dayjs8, import_timezone2, import_utc2, import_react59, import_jsx_runtime197, SELL_SHARE_INPUT_DECIMALS, SELL_SHARE_DISPLAY_DECIMALS, resolvePlaceOrderPortalContainer, LIMIT_EXPIRATION_OPTION_COUNT, LIMIT_PRICE_STEP, LIMIT_PRICE_MIN, LIMIT_PRICE_MAX, ceilDiv, toRaw6, toLimitPriceRaw, toLimitSizeRaw, formatLimitPriceLabel, formatLimitPriceRawLabel, LIMIT_ORDER_SUBMITTING_PROGRESS, buildLimitOrderExecutionGroup, getLimitOrderToWinValue, normalizeLimitPrice, formatLimitPriceInputValue, parseLimitPriceInputValue, resolveEndOfDayEastern, resolveLimitExpirationDate, serializeLimitOrderExpiration, isFutureLimitExpiration, resolveRefetchedQuoteData, isFillRejection400, PlaceOrderSlippageControl, renderCardHeader, PlaceOrderResolvedView, renderRouteBreakdownRow, SIDE_NAMED_MONEYLINE_QUESTION_RE, shouldUseRawResolvedPlaceOrderOutcomeLabel, renderRouteCard, PlaceOrder;
26975
+ var import_hooks89, import_sdk28, import_react58, Popover, import_dayjs8, import_timezone2, import_utc2, import_react59, import_jsx_runtime197, SELL_SHARE_INPUT_DECIMALS, SELL_SHARE_DISPLAY_DECIMALS, resolvePlaceOrderPortalContainer, LIMIT_EXPIRATION_OPTION_COUNT, LIMIT_SIZE_STEP_VENUES, LIMIT_PRICE_STEP, LIMIT_PRICE_MIN, LIMIT_PRICE_MAX, toLimitPriceRaw, formatLimitPriceLabel, formatLimitPriceRawLabel, LIMIT_ORDER_SUBMITTING_PROGRESS, buildLimitOrderExecutionGroup, getLimitOrderToWinValue, normalizeLimitPrice, formatLimitPriceInputValue, parseLimitPriceInputValue, resolveEndOfDayEastern, resolveLimitExpirationDate, serializeLimitOrderExpiration, isFutureLimitExpiration, resolveRefetchedQuoteData, isFillRejection400, PlaceOrderSlippageControl, renderCardHeader, PlaceOrderResolvedView, renderRouteBreakdownRow, SIDE_NAMED_MONEYLINE_QUESTION_RE, shouldUseRawResolvedPlaceOrderOutcomeLabel, renderRouteCard, PlaceOrder;
26938
26976
  var init_place_order = __esm({
26939
26977
  "src/trading/place-order/index.tsx"() {
26940
26978
  "use strict";
@@ -26992,32 +27030,21 @@ var init_place_order = __esm({
26992
27030
  return (_a = triggerElement == null ? void 0 : triggerElement.closest(".agg-modal-center")) != null ? _a : void 0;
26993
27031
  };
26994
27032
  LIMIT_EXPIRATION_OPTION_COUNT = 5;
27033
+ LIMIT_SIZE_STEP_VENUES = /* @__PURE__ */ new Set([
27034
+ import_sdk28.Venue.tiprun,
27035
+ import_sdk28.Venue.hyperliquid,
27036
+ import_sdk28.Venue.pred,
27037
+ import_sdk28.Venue.polymarket
27038
+ ]);
26995
27039
  import_dayjs8.default.extend(import_utc2.default);
26996
27040
  import_dayjs8.default.extend(import_timezone2.default);
26997
27041
  LIMIT_PRICE_STEP = 1e-3;
26998
27042
  LIMIT_PRICE_MIN = 1e-3;
26999
27043
  LIMIT_PRICE_MAX = 0.999;
27000
- ceilDiv = (numerator, denominator) => {
27001
- return (numerator + denominator - BigInt(1)) / denominator;
27002
- };
27003
- toRaw6 = (value) => {
27004
- const normalizedValue = Number.isFinite(value) ? Math.max(0, value) : 0;
27005
- return Math.ceil(normalizedValue * Number(import_sdk28.LIMIT_PRICE_RAW_SCALE)).toString();
27006
- };
27007
27044
  toLimitPriceRaw = (value) => {
27008
27045
  const clampedValue = Math.min(LIMIT_PRICE_MAX, Math.max(LIMIT_PRICE_MIN, value));
27009
27046
  return Math.round(clampedValue * Number(import_sdk28.LIMIT_PRICE_RAW_SCALE)).toString();
27010
27047
  };
27011
- toLimitSizeRaw = ({
27012
- amount: amount2,
27013
- limitPriceRaw,
27014
- side
27015
- }) => {
27016
- if (side === "sell") return toRaw6(amount2);
27017
- const spendRaw = BigInt(toRaw6(amount2));
27018
- const priceRaw = BigInt(limitPriceRaw);
27019
- return ceilDiv(spendRaw * import_sdk28.LIMIT_PRICE_RAW_SCALE, priceRaw).toString();
27020
- };
27021
27048
  formatLimitPriceLabel = (value) => {
27022
27049
  return `${(value * 100).toLocaleString("en-US", {
27023
27050
  minimumFractionDigits: 0,
@@ -27057,11 +27084,12 @@ var init_place_order = __esm({
27057
27084
  getLimitOrderToWinValue = ({
27058
27085
  amount: amount2,
27059
27086
  limitPriceRaw,
27060
- side
27087
+ side,
27088
+ sizeStepRaw
27061
27089
  }) => {
27062
27090
  const priceRaw = BigInt(limitPriceRaw);
27063
27091
  if (priceRaw <= BigInt(0) || priceRaw >= import_sdk28.LIMIT_PRICE_RAW_SCALE) return 0;
27064
- const sizeRaw = BigInt(toLimitSizeRaw({ amount: amount2, limitPriceRaw, side }));
27092
+ const sizeRaw = BigInt(toLimitSizeRaw({ amount: amount2, limitPriceRaw, side, sizeStepRaw }));
27065
27093
  if (side === "buy") return Number(sizeRaw) / Number(import_sdk28.LIMIT_PRICE_RAW_SCALE);
27066
27094
  return Number(ceilDiv(priceRaw * sizeRaw, import_sdk28.LIMIT_PRICE_RAW_SCALE)) / Number(import_sdk28.LIMIT_PRICE_RAW_SCALE);
27067
27095
  };
@@ -28013,7 +28041,8 @@ var init_place_order = __esm({
28013
28041
  const limitVenueQuoteRequests = (0, import_react59.useMemo)(
28014
28042
  () => visibleLimitVenueOptions.map((option) => ({
28015
28043
  venue: option.venue,
28016
- venueMarketOutcomeId: option.venueMarketOutcomeId
28044
+ venueMarketOutcomeId: option.venueMarketOutcomeId,
28045
+ venueMarketId: option.venueMarketId
28017
28046
  })),
28018
28047
  [visibleLimitVenueOptions]
28019
28048
  );
@@ -28045,10 +28074,83 @@ var init_place_order = __esm({
28045
28074
  }
28046
28075
  return venues;
28047
28076
  }, [limitVenueQuotes.quotes]);
28077
+ const originalLimitPriceRaw = (0, import_react59.useMemo)(() => toLimitPriceRaw(limitPrice), [limitPrice]);
28078
+ const limitPriceAdjustmentByVenue = (0, import_react59.useMemo)(() => {
28079
+ var _a2;
28080
+ const adjustments = /* @__PURE__ */ new Map();
28081
+ for (const option of visibleLimitVenueOptions) {
28082
+ try {
28083
+ adjustments.set(
28084
+ option.venue,
28085
+ (0, import_sdk28.adjustLimitPriceRawToTick)({
28086
+ limitPriceRaw: originalLimitPriceRaw,
28087
+ side: internalTab,
28088
+ tickSize: (_a2 = limitVenueQuoteByVenue.get(option.venue)) == null ? void 0 : _a2.tickSize
28089
+ })
28090
+ );
28091
+ } catch (e) {
28092
+ adjustments.set(
28093
+ option.venue,
28094
+ (0, import_sdk28.adjustLimitPriceRawToTick)({
28095
+ limitPriceRaw: originalLimitPriceRaw,
28096
+ side: internalTab,
28097
+ tickSize: null
28098
+ })
28099
+ );
28100
+ }
28101
+ }
28102
+ return adjustments;
28103
+ }, [internalTab, limitVenueQuoteByVenue, originalLimitPriceRaw, visibleLimitVenueOptions]);
28104
+ const limitSizeRulesByVenue = (0, import_react59.useMemo)(() => {
28105
+ var _a2, _b2;
28106
+ const rulesByVenue = /* @__PURE__ */ new Map();
28107
+ for (const quote of limitVenueQuotes.quotes) {
28108
+ if (!quote.sizeStepRaw && !quote.minSizeRaw) continue;
28109
+ rulesByVenue.set(quote.request.venue, {
28110
+ sizeStepRaw: (_a2 = quote.sizeStepRaw) != null ? _a2 : void 0,
28111
+ minSizeRaw: (_b2 = quote.minSizeRaw) != null ? _b2 : void 0
28112
+ });
28113
+ }
28114
+ return rulesByVenue;
28115
+ }, [limitVenueQuotes.quotes]);
28116
+ const belowMinimumLimitVenues = (0, import_react59.useMemo)(() => {
28117
+ var _a2, _b2;
28118
+ const venues = /* @__PURE__ */ new Set();
28119
+ if (!isLimitOrder || internalAmount <= 0) return venues;
28120
+ for (const option of visibleLimitVenueOptions) {
28121
+ if (geoBlockedLimitVenues.has(option.venue) || (0, import_hooks89.getVenueAvailabilityState)({
28122
+ venueId: option.venue,
28123
+ disabledVenues,
28124
+ isConfigLoading: isAppConfigLoading
28125
+ }) !== "available")
28126
+ continue;
28127
+ const rules = limitSizeRulesByVenue.get(option.venue);
28128
+ if (!(rules == null ? void 0 : rules.sizeStepRaw) && !(rules == null ? void 0 : rules.minSizeRaw)) continue;
28129
+ const sizeRaw = toLimitSizeRaw({
28130
+ amount: internalAmount,
28131
+ limitPriceRaw: (_b2 = (_a2 = limitPriceAdjustmentByVenue.get(option.venue)) == null ? void 0 : _a2.adjustedPriceRaw) != null ? _b2 : originalLimitPriceRaw,
28132
+ side: internalTab,
28133
+ sizeStepRaw: rules.sizeStepRaw
28134
+ });
28135
+ if (isLimitSizeBelowMinimum(sizeRaw, rules.minSizeRaw)) venues.add(option.venue);
28136
+ }
28137
+ return venues;
28138
+ }, [
28139
+ disabledVenues,
28140
+ geoBlockedLimitVenues,
28141
+ internalAmount,
28142
+ internalTab,
28143
+ isAppConfigLoading,
28144
+ isLimitOrder,
28145
+ limitPriceAdjustmentByVenue,
28146
+ limitSizeRulesByVenue,
28147
+ originalLimitPriceRaw,
28148
+ visibleLimitVenueOptions
28149
+ ]);
28048
28150
  const availableLimitVenueOptions = (0, import_react59.useMemo)(() => {
28049
28151
  return visibleLimitVenueOptions.filter((option) => {
28050
28152
  var _a2;
28051
- return !geoBlockedLimitVenues.has(option.venue) && // A limit SELL rests against shares held at that specific venue, so a
28153
+ return !geoBlockedLimitVenues.has(option.venue) && !belowMinimumLimitVenues.has(option.venue) && // A limit SELL rests against shares held at that specific venue, so a
28052
28154
  // venue the user has no position on is a guaranteed 409 from the
28053
28155
  // server's reservation check — and the automatic pick, which sorts on
28054
28156
  // price alone, would happily choose one. Only narrow once we know
@@ -28060,6 +28162,7 @@ var init_place_order = __esm({
28060
28162
  }) === "available";
28061
28163
  });
28062
28164
  }, [
28165
+ belowMinimumLimitVenues,
28063
28166
  disabledVenues,
28064
28167
  geoBlockedLimitVenues,
28065
28168
  isAppConfigLoading,
@@ -28917,8 +29020,6 @@ var init_place_order = __esm({
28917
29020
  const isSelectedVenueInventoryInsufficient = isSell && (selectedRouteCard == null ? void 0 : selectedRouteCard.kind) === "venue" && selectedRouteCard.insufficientInventory === true;
28918
29021
  const isBelowClientMinimum = !isSell && hasEnteredAmount && internalAmount < MIN_BUY_ORDER_AMOUNT;
28919
29022
  const isBelowVenueMinimumFromQuote = isQuoteBelowVenueMinimum(activeQuoteData);
28920
- const isBelowMinimum = isBelowClientMinimum || isBelowVenueMinimumFromQuote;
28921
- const belowMinimumMessage = isBelowClientMinimum ? tradingLabels.minimumOrderAmount(MIN_BUY_ORDER_AMOUNT) : tradingLabels.minOrderSizeViolated;
28922
29023
  const quoteStatus = (0, import_react59.useMemo)(() => {
28923
29024
  if (!orderEligibility.canPlaceOrder) return void 0;
28924
29025
  return resolvePlaceOrderQuoteStatus({
@@ -29045,33 +29146,6 @@ var init_place_order = __esm({
29045
29146
  return averagePrice == null ? "" : tradingLabels.averagePrice(averagePrice);
29046
29147
  }, [selectedRouteCard, tradingLabels]);
29047
29148
  const displayedToWinValue = (_ea = selectedRouteCard == null ? void 0 : selectedRouteCard.numericValue) != null ? _ea : 0;
29048
- const originalLimitPriceRaw = (0, import_react59.useMemo)(() => toLimitPriceRaw(limitPrice), [limitPrice]);
29049
- const limitPriceAdjustmentByVenue = (0, import_react59.useMemo)(() => {
29050
- var _a2;
29051
- const adjustments = /* @__PURE__ */ new Map();
29052
- for (const option of visibleLimitVenueOptions) {
29053
- try {
29054
- adjustments.set(
29055
- option.venue,
29056
- (0, import_sdk28.adjustLimitPriceRawToTick)({
29057
- limitPriceRaw: originalLimitPriceRaw,
29058
- side: internalTab,
29059
- tickSize: (_a2 = limitVenueQuoteByVenue.get(option.venue)) == null ? void 0 : _a2.tickSize
29060
- })
29061
- );
29062
- } catch (e) {
29063
- adjustments.set(
29064
- option.venue,
29065
- (0, import_sdk28.adjustLimitPriceRawToTick)({
29066
- limitPriceRaw: originalLimitPriceRaw,
29067
- side: internalTab,
29068
- tickSize: null
29069
- })
29070
- );
29071
- }
29072
- }
29073
- return adjustments;
29074
- }, [internalTab, limitVenueQuoteByVenue, originalLimitPriceRaw, visibleLimitVenueOptions]);
29075
29149
  const selectedLimitPriceAdjustment = selectedLimitVenueOption ? limitPriceAdjustmentByVenue.get(selectedLimitVenueOption.venue) : void 0;
29076
29150
  const selectedLimitPriceRaw = (_fa = selectedLimitPriceAdjustment == null ? void 0 : selectedLimitPriceAdjustment.adjustedPriceRaw) != null ? _fa : originalLimitPriceRaw;
29077
29151
  const limitPriceAdjustmentMessage = (0, import_react59.useMemo)(() => {
@@ -29092,6 +29166,8 @@ var init_place_order = __esm({
29092
29166
  selectedLimitVenueOption,
29093
29167
  tradingLabels
29094
29168
  ]);
29169
+ const selectedLimitSizeRules = selectedLimitVenueOption ? limitSizeRulesByVenue.get(selectedLimitVenueOption.venue) : void 0;
29170
+ const isLimitSizeRulesPending = isLimitOrder && selectedLimitVenueOption != null && LIMIT_SIZE_STEP_VENUES.has(selectedLimitVenueOption.venue) && limitVenueQuotes.isMetadataPending;
29095
29171
  const limitOrderPayload = (0, import_react59.useMemo)(() => {
29096
29172
  if (!selectedLimitVenueOption || internalAmount <= 0) return null;
29097
29173
  if (limitPriceInputError) return null;
@@ -29107,7 +29183,8 @@ var init_place_order = __esm({
29107
29183
  const sizeRaw = toLimitSizeRaw({
29108
29184
  amount: internalAmount,
29109
29185
  limitPriceRaw,
29110
- side: internalTab
29186
+ side: internalTab,
29187
+ sizeStepRaw: selectedLimitSizeRules == null ? void 0 : selectedLimitSizeRules.sizeStepRaw
29111
29188
  });
29112
29189
  const expiresAt = expirationDate ? serializeLimitOrderExpiration(expirationDate) : void 0;
29113
29190
  return __spreadValues({
@@ -29126,8 +29203,12 @@ var init_place_order = __esm({
29126
29203
  limitExpirationType,
29127
29204
  limitPriceInputError,
29128
29205
  selectedLimitVenueOption,
29129
- selectedLimitPriceRaw
29206
+ selectedLimitPriceRaw,
29207
+ selectedLimitSizeRules == null ? void 0 : selectedLimitSizeRules.sizeStepRaw
29130
29208
  ]);
29209
+ const isLimitSizeBelowVenueMinimum = isLimitOrder && (limitOrderPayload != null && isLimitSizeBelowMinimum(limitOrderPayload.sizeRaw, selectedLimitSizeRules == null ? void 0 : selectedLimitSizeRules.minSizeRaw) || selectedLimitVenueOption == null && belowMinimumLimitVenues.size > 0);
29210
+ const isBelowMinimum = isBelowClientMinimum || isBelowVenueMinimumFromQuote || isLimitSizeBelowVenueMinimum;
29211
+ const belowMinimumMessage = isBelowClientMinimum ? tradingLabels.minimumOrderAmount(MIN_BUY_ORDER_AMOUNT) : isSell ? tradingLabels.venueMinOrderSize : tradingLabels.minOrderSizeViolated;
29131
29212
  const resolvedLimitExpirationDraftDate = (0, import_react59.useMemo)(() => {
29132
29213
  return resolveLimitExpirationDate({
29133
29214
  expirationType: "CUSTOM",
@@ -29171,12 +29252,13 @@ var init_place_order = __esm({
29171
29252
  }, [internalTab, limitOrderPayload]);
29172
29253
  const limitRouteCards = (0, import_react59.useMemo)(() => {
29173
29254
  return visibleLimitVenueOptions.map((option) => {
29174
- var _a2, _b2, _c2, _d2;
29255
+ var _a2, _b2, _c2, _d2, _e2;
29175
29256
  const effectiveLimitPriceRaw = (_b2 = (_a2 = limitPriceAdjustmentByVenue.get(option.venue)) == null ? void 0 : _a2.adjustedPriceRaw) != null ? _b2 : originalLimitPriceRaw;
29176
29257
  const venueToWinValue = getLimitOrderToWinValue({
29177
29258
  amount: internalAmount,
29178
29259
  limitPriceRaw: effectiveLimitPriceRaw,
29179
- side: internalTab
29260
+ side: internalTab,
29261
+ sizeStepRaw: (_c2 = limitSizeRulesByVenue.get(option.venue)) == null ? void 0 : _c2.sizeStepRaw
29180
29262
  });
29181
29263
  const availabilityState = (0, import_hooks89.getVenueAvailabilityState)({
29182
29264
  venueId: option.venue,
@@ -29184,10 +29266,10 @@ var init_place_order = __esm({
29184
29266
  isConfigLoading: isAppConfigLoading
29185
29267
  });
29186
29268
  const isGeoBlocked = geoBlockedLimitVenues.has(option.venue);
29187
- const isUnavailable = isTradingBlocked || isGeoBlocked || availabilityState !== "available";
29269
+ const isUnavailable = isTradingBlocked || isGeoBlocked || belowMinimumLimitVenues.has(option.venue) || availabilityState !== "available";
29188
29270
  const currentPriceLabel = option.currentPrice == null ? "\u2014" : formatProbabilityCents(option.currentPrice, formatPrice);
29189
29271
  const totalFees = getSmartRouteTotalFees(
29190
- (_d2 = (_c2 = limitVenueQuoteByVenue.get(option.venue)) == null ? void 0 : _c2.data) == null ? void 0 : _d2.feeBreakdown
29272
+ (_e2 = (_d2 = limitVenueQuoteByVenue.get(option.venue)) == null ? void 0 : _d2.data) == null ? void 0 : _e2.feeBreakdown
29191
29273
  );
29192
29274
  const feeLabel = totalFees == null ? void 0 : formatUsd(totalFees, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
29193
29275
  return {
@@ -29206,6 +29288,7 @@ var init_place_order = __esm({
29206
29288
  };
29207
29289
  });
29208
29290
  }, [
29291
+ belowMinimumLimitVenues,
29209
29292
  disabledVenues,
29210
29293
  formatPrice,
29211
29294
  geoBlockedLimitVenues,
@@ -29214,6 +29297,7 @@ var init_place_order = __esm({
29214
29297
  isAppConfigLoading,
29215
29298
  isTradingBlocked,
29216
29299
  limitPriceAdjustmentByVenue,
29300
+ limitSizeRulesByVenue,
29217
29301
  limitVenueQuoteByVenue,
29218
29302
  originalLimitPriceRaw,
29219
29303
  tradingLabels,
@@ -29312,10 +29396,10 @@ var init_place_order = __esm({
29312
29396
  const fills = (_b2 = (_a2 = selectedRouteCard.quoteData) == null ? void 0 : _a2.fills) != null ? _b2 : [];
29313
29397
  return fills.length > 0 && fills.every((f) => geoBlockedVenuesFromWarnings.has(f.venue));
29314
29398
  }, [selectedRouteCard, geoBlockedVenuesFromWarnings]);
29315
- const shouldShowGeoBlockBanner = isTradingBlocked || selectedRouteGeoBlocked || isPrimaryVenueGeoBlocked || isLimitOrder && limitRouteCards.length > 0 && limitRouteCards.every((card) => card.isUnavailable);
29399
+ const shouldShowGeoBlockBanner = isTradingBlocked || selectedRouteGeoBlocked || isPrimaryVenueGeoBlocked || isLimitOrder && limitRouteCards.length > 0 && limitRouteCards.every((card) => card.isUnavailable) && limitRouteCards.some((card) => !card.venue || !belowMinimumLimitVenues.has(card.venue));
29316
29400
  const actionLabel = `${internalTab === "buy" ? tradingLabels.buy : tradingLabels.sell} ${selectedOutcomeLabel}`.trim();
29317
- const isActionDisabled = isPrimaryActionDisabled || !orderEligibility.canPlaceOrder || isActionLoading || !hasEnteredAmount || !scopedSelectedMarket || isInsufficientBalance || isBetdexBalanceUnavailable && !canExecuteBetdexQuote || isQuoteInsufficientBalance && !canExecuteBetdexQuote || isSell && isQuoteInputEditing || isSellAmountAboveAvailability || isBelowMinimum || !isLimitOrder && isQuoteLoading || isSelectedVenueInventoryInsufficient || (isLimitOrder ? !limitOrderPayload : !selectedRouteCard || !selectedRouteCard.quoteData.quoteId && !canExecuteBetdexQuote) || selectedRouteGeoBlocked || !isAuthenticated || !isLimitOrder && quoteStatus !== void 0 && !canExecuteBetdexQuote;
29318
- const shouldShowSmartRouting = orderEligibility.canPlaceOrder && hasEnteredAmount && !isBelowMinimum && (isLimitOrder ? limitRouteCards.length > 0 : displayedRouteCards.length > 0 || smartRoute.isFetching || smartRoute.isLoading || isSell && (venueSellQuotes.isFetching || venueSellQuotes.isLoading));
29401
+ const isActionDisabled = isPrimaryActionDisabled || !orderEligibility.canPlaceOrder || isActionLoading || !hasEnteredAmount || !scopedSelectedMarket || isInsufficientBalance || isBetdexBalanceUnavailable && !canExecuteBetdexQuote || isQuoteInsufficientBalance && !canExecuteBetdexQuote || isSell && isQuoteInputEditing || isSellAmountAboveAvailability || isBelowMinimum || isLimitSizeRulesPending || !isLimitOrder && isQuoteLoading || isSelectedVenueInventoryInsufficient || (isLimitOrder ? !limitOrderPayload : !selectedRouteCard || !selectedRouteCard.quoteData.quoteId && !canExecuteBetdexQuote) || selectedRouteGeoBlocked || !isAuthenticated || !isLimitOrder && quoteStatus !== void 0 && !canExecuteBetdexQuote;
29402
+ const shouldShowSmartRouting = orderEligibility.canPlaceOrder && hasEnteredAmount && !isBelowClientMinimum && !isBelowVenueMinimumFromQuote && (isLimitOrder ? limitRouteCards.length > 0 : displayedRouteCards.length > 0 || smartRoute.isFetching || smartRoute.isLoading || isSell && (venueSellQuotes.isFetching || venueSellQuotes.isLoading));
29319
29403
  const shouldShowRouteToggle = !isLimitOrder && !isQuoteLoading && displayedRouteCards.length > PLACE_ORDER_ROUTE_COLLAPSED_CARD_COUNT;
29320
29404
  const handleReturnToOrderForm = (0, import_react59.useCallback)(() => {
29321
29405
  const submittedSelection = submittedSelectionRef.current;
@@ -33993,7 +34077,8 @@ var init_sports_markets = __esm({
33993
34077
  onSectionMarketsChange,
33994
34078
  onOutcomeSelect,
33995
34079
  live,
33996
- midpointsResult
34080
+ midpointsResult,
34081
+ minVolume
33997
34082
  }) => {
33998
34083
  var _a, _b;
33999
34084
  const labels = (0, import_hooks98.useLabels)();
@@ -34003,6 +34088,7 @@ var init_sports_markets = __esm({
34003
34088
  aggKey: event.aggKey ? [event.aggKey] : void 0,
34004
34089
  limit: 100,
34005
34090
  status: import_hooks98.MarketStatus.open,
34091
+ minVolume,
34006
34092
  enabled: hasAggKey
34007
34093
  });
34008
34094
  const {
@@ -34049,6 +34135,7 @@ var init_sports_markets = __esm({
34049
34135
  // completion — hundreds of markets on prop-rich events) from ~15 calls to 1-3.
34050
34136
  limit: 100,
34051
34137
  status: import_hooks98.MarketStatus.open,
34138
+ minVolume,
34052
34139
  enabled: hasAggKey
34053
34140
  });
34054
34141
  const {
@@ -34262,6 +34349,9 @@ var init_sports_event_market_page = __esm({
34262
34349
  onBeforePrimaryAction,
34263
34350
  sharedKyc
34264
34351
  }) => {
34352
+ const {
34353
+ market: { minVolume }
34354
+ } = (0, import_hooks99.useSdkUiConfig)();
34265
34355
  const [sectionMarketsByKey, setSectionMarketsByKey] = (0, import_react68.useState)({});
34266
34356
  const composedEvent = (0, import_react68.useMemo)(() => {
34267
34357
  return mergeSportsSectionMarketsIntoEvent({
@@ -34369,6 +34459,7 @@ var init_sports_event_market_page = __esm({
34369
34459
  {
34370
34460
  event,
34371
34461
  onSectionMarketsChange: handleSectionMarketsChange,
34462
+ minVolume: defaultMarketId ? void 0 : minVolume,
34372
34463
  midpointsResult,
34373
34464
  onOutcomeSelect: isMobileViewport ? () => {
34374
34465
  setIsMobileTradeOpen(true);
@@ -34799,7 +34890,8 @@ var init_event_market = __esm({
34799
34890
  EventMarketPage = (props) => {
34800
34891
  var _a;
34801
34892
  const {
34802
- features: { showSportsMarkets }
34893
+ features: { showSportsMarkets },
34894
+ market: { minVolume }
34803
34895
  } = (0, import_hooks100.useSdkUiConfig)();
34804
34896
  const labels = (0, import_hooks100.useLabels)();
34805
34897
  const hasEventProp = "event" in props && !!props.event;
@@ -34814,7 +34906,10 @@ var init_event_market = __esm({
34814
34906
  } = (0, import_hooks100.useEnrichedVenueEvent)({
34815
34907
  progressive: props.progressiveMarkets,
34816
34908
  eventId: hasEventProp ? "" : (_a = props.eventId) != null ? _a : "",
34817
- enabled: !props.isLoading && !hasEventProp && !!props.eventId
34909
+ enabled: !props.isLoading && !hasEventProp && !!props.eventId,
34910
+ // A deep-linked market may sit below the floor; filtering it out would make the
34911
+ // page silently select a different market, so the floor only applies to browsing.
34912
+ minVolume: props.defaultMarketId ? void 0 : minVolume
34818
34913
  });
34819
34914
  const renderEventContent = (event) => {
34820
34915
  const contentProps = __spreadProps(__spreadValues({}, props), {
@@ -36406,7 +36501,8 @@ var EventListItemContent = ({
36406
36501
  // the volume-sorted top-3 (the detail page omits context and keeps the
36407
36502
  // structured threshold/date order).
36408
36503
  context: "list",
36409
- status: marketStatus
36504
+ status: marketStatus,
36505
+ minVolume: config.market.minVolume
36410
36506
  });
36411
36507
  const resolvedOutcomeMarkets = (0, import_react22.useMemo)(() => {
36412
36508
  if (!isLazyMarketsQueryEnabled || lazyLoadedMarkets.length === 0) return allVenueMarkets;
@@ -37782,7 +37878,8 @@ var EventList = ({
37782
37878
  const labels = (0, import_hooks67.useLabels)();
37783
37879
  const { disabledVenues } = (0, import_hooks67.useAppConfig)();
37784
37880
  const {
37785
- features: { enableVenueEventDiscoveryFilters, showSportsMarkets }
37881
+ features: { enableVenueEventDiscoveryFilters, showSportsMarkets },
37882
+ market: { minVolume }
37786
37883
  } = (0, import_hooks67.useSdkUiConfig)();
37787
37884
  const isDiscoveryFiltersEnabled = enableVenueEventDiscoveryFilters && !search;
37788
37885
  const resolvedTabs = useEventListTabs();
@@ -38025,6 +38122,7 @@ var EventList = ({
38025
38122
  // markets experience is enabled (the sports event-detail view loads the
38026
38123
  // folded companions via aggKey). Gated on the same flag as that view.
38027
38124
  grouped: showSportsMarkets,
38125
+ minVolume,
38028
38126
  initialPages: initialLoadedPageCount,
38029
38127
  enabled: controlledCategoryPath == null || validatedCategoryPathKey === controlledCategoryPathValidationKey
38030
38128
  });
package/dist/index.mjs CHANGED
@@ -16,13 +16,13 @@ import {
16
16
  buildAggTxExplorerHref,
17
17
  formatShareAmount,
18
18
  useHomePageModals
19
- } from "./chunk-J75RLLP2.mjs";
19
+ } from "./chunk-PHT5VLGB.mjs";
20
20
  import {
21
21
  EventList,
22
22
  EventListItem,
23
23
  EventListItemV2,
24
24
  EventListVenueStrip
25
- } from "./chunk-H54RU7NF.mjs";
25
+ } from "./chunk-MDCFCGA3.mjs";
26
26
  import {
27
27
  CARD_NETWORK_OPTIONS,
28
28
  DepositModal,
@@ -40,7 +40,7 @@ import {
40
40
  EventOpenOrdersCard,
41
41
  formatRecurringCountdown,
42
42
  useEventOpenOrders
43
- } from "./chunk-5ET2M3XX.mjs";
43
+ } from "./chunk-4X7OLBO6.mjs";
44
44
  import {
45
45
  EventListItemDetails,
46
46
  MarketDetails,
@@ -55,7 +55,7 @@ import {
55
55
  orderbookRowLimitDefault,
56
56
  resolveEventDetailsSyncKey,
57
57
  useCenterOrderbookSpread
58
- } from "./chunk-JR2XAAK6.mjs";
58
+ } from "./chunk-YYGS6S7N.mjs";
59
59
  import {
60
60
  AggNotificationEventsProvider,
61
61
  DEPOSIT_MODAL_OPEN_EVENT,
@@ -77,7 +77,7 @@ import {
77
77
  useResolvedMarketClaim,
78
78
  useSharedKycFlow,
79
79
  venueRequiresSharedKyc
80
- } from "./chunk-HZXHDH6G.mjs";
80
+ } from "./chunk-KN7JN7F5.mjs";
81
81
  import {
82
82
  SETTLEMENT_SECTION_ID,
83
83
  Settlement,