@agg-build/ui 1.2.11 → 1.3.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 (99) hide show
  1. package/README.md +34 -1
  2. package/dist/{chunk-NWJHFGBZ.mjs → chunk-55ODXLOS.mjs} +1 -1
  3. package/dist/{chunk-3ZSNHGAB.mjs → chunk-5ALBEKAT.mjs} +842 -300
  4. package/dist/{chunk-YP75TIY6.mjs → chunk-6PQ6O6M5.mjs} +583 -186
  5. package/dist/{chunk-ENAGASVU.mjs → chunk-ONVP7YWS.mjs} +439 -339
  6. package/dist/{chunk-SJLHOAKK.mjs → chunk-QUZWA34R.mjs} +1256 -844
  7. package/dist/{chunk-54PCEK6G.mjs → chunk-UFC7L74C.mjs} +26 -27
  8. package/dist/{chunk-J7K2U44E.mjs → chunk-YWJIYEJV.mjs} +236 -121
  9. package/dist/events.js +2460 -1355
  10. package/dist/events.mjs +5 -3
  11. package/dist/index.js +5741 -3841
  12. package/dist/index.mjs +485 -106
  13. package/dist/modals.js +1399 -1093
  14. package/dist/modals.mjs +3 -3
  15. package/dist/pages.js +4039 -2687
  16. package/dist/pages.mjs +6 -6
  17. package/dist/primitives.js +1267 -895
  18. package/dist/primitives.mjs +3 -1
  19. package/dist/styles.css +1 -1
  20. package/dist/tailwind.css +1 -1
  21. package/dist/trading.js +1032 -695
  22. package/dist/trading.mjs +4 -4
  23. package/dist/types/agg-provider.d.mts +27 -0
  24. package/dist/types/agg-provider.d.ts +27 -0
  25. package/dist/types/events/item/event-list-item-v2.utils.d.mts +28 -0
  26. package/dist/types/events/item/event-list-item-v2.utils.d.ts +28 -0
  27. package/dist/types/events/item/event-list-item.constants.d.mts +1 -1
  28. package/dist/types/events/item/event-list-item.constants.d.ts +1 -1
  29. package/dist/types/events/item/index.d.mts +4 -0
  30. package/dist/types/events/item/index.d.ts +4 -0
  31. package/dist/types/events/list/event-list-tabs.d.mts +6 -1
  32. package/dist/types/events/list/event-list-tabs.d.ts +6 -1
  33. package/dist/types/events/list/event-list.types.d.mts +2 -0
  34. package/dist/types/events/list/event-list.types.d.ts +2 -0
  35. package/dist/types/events/list/event-list.utils.d.mts +19 -0
  36. package/dist/types/events/list/event-list.utils.d.ts +19 -0
  37. package/dist/types/events/list/index.d.mts +1 -1
  38. package/dist/types/events/list/index.d.ts +1 -1
  39. package/dist/types/index.d.mts +2 -0
  40. package/dist/types/index.d.ts +2 -0
  41. package/dist/types/notifications/agg-notification-events-provider.d.mts +35 -0
  42. package/dist/types/notifications/agg-notification-events-provider.d.ts +35 -0
  43. package/dist/types/notifications/agg-toast-provider.d.mts +27 -0
  44. package/dist/types/notifications/agg-toast-provider.d.ts +27 -0
  45. package/dist/types/notifications/deposit-notification-events.d.mts +10 -0
  46. package/dist/types/notifications/deposit-notification-events.d.ts +10 -0
  47. package/dist/types/notifications/index.d.mts +2 -0
  48. package/dist/types/notifications/index.d.ts +2 -0
  49. package/dist/types/pages/home/home.types.d.mts +1 -0
  50. package/dist/types/pages/home/home.types.d.ts +1 -0
  51. package/dist/types/pages/user-profile/user-profile.types.d.mts +30 -4
  52. package/dist/types/pages/user-profile/user-profile.types.d.ts +30 -4
  53. package/dist/types/primitives/button/button.types.d.mts +4 -0
  54. package/dist/types/primitives/button/button.types.d.ts +4 -0
  55. package/dist/types/primitives/button/index.d.mts +1 -1
  56. package/dist/types/primitives/button/index.d.ts +1 -1
  57. package/dist/types/primitives/icon/index.d.mts +2 -1
  58. package/dist/types/primitives/icon/index.d.ts +2 -1
  59. package/dist/types/primitives/icon/registry.d.mts +20 -0
  60. package/dist/types/primitives/icon/registry.d.ts +20 -0
  61. package/dist/types/primitives/icon/svg/gift-bonus.d.mts +5 -0
  62. package/dist/types/primitives/icon/svg/gift-bonus.d.ts +5 -0
  63. package/dist/types/primitives/icon/svg/sort-end-date.d.mts +5 -0
  64. package/dist/types/primitives/icon/svg/sort-end-date.d.ts +5 -0
  65. package/dist/types/primitives/icon/svg/sort-top-arbitrage.d.mts +5 -0
  66. package/dist/types/primitives/icon/svg/sort-top-arbitrage.d.ts +5 -0
  67. package/dist/types/primitives/icon/svg/sort-volume-24hr.d.mts +5 -0
  68. package/dist/types/primitives/icon/svg/sort-volume-24hr.d.ts +5 -0
  69. package/dist/types/primitives/icon/svg/sort-volume.d.mts +5 -0
  70. package/dist/types/primitives/icon/svg/sort-volume.d.ts +5 -0
  71. package/dist/types/primitives/search/search.types.d.mts +2 -1
  72. package/dist/types/primitives/search/search.types.d.ts +2 -1
  73. package/dist/types/primitives/select/index.d.mts +1 -1
  74. package/dist/types/primitives/select/index.d.ts +1 -1
  75. package/dist/types/primitives/select/select.types.d.mts +9 -0
  76. package/dist/types/primitives/select/select.types.d.ts +9 -0
  77. package/dist/types/primitives/skeleton/index.d.mts +1 -1
  78. package/dist/types/primitives/skeleton/index.d.ts +1 -1
  79. package/dist/types/primitives/skeleton/skeleton.types.d.mts +4 -0
  80. package/dist/types/primitives/skeleton/skeleton.types.d.ts +4 -0
  81. package/dist/types/primitives/skeleton/views/event-list-skeleton-view.d.mts +1 -1
  82. package/dist/types/primitives/skeleton/views/event-list-skeleton-view.d.ts +1 -1
  83. package/dist/types/primitives/toast/toast.types.d.mts +3 -0
  84. package/dist/types/primitives/toast/toast.types.d.ts +3 -0
  85. package/dist/types/profile/index.d.mts +1 -1
  86. package/dist/types/profile/index.d.ts +1 -1
  87. package/dist/types/profile/profile-modal.constants.d.mts +2 -2
  88. package/dist/types/profile/profile-modal.constants.d.ts +2 -2
  89. package/dist/types/profile/tabs/accounts-wallets-tab.d.mts +2 -17
  90. package/dist/types/profile/tabs/accounts-wallets-tab.d.ts +2 -17
  91. package/dist/types/profile/tabs/trading-access-tab.d.mts +15 -0
  92. package/dist/types/profile/tabs/trading-access-tab.d.ts +15 -0
  93. package/dist/types/trading/place-order/index.d.mts +1 -1
  94. package/dist/types/trading/place-order/index.d.ts +1 -1
  95. package/dist/types/trading/place-order/index.place-order.types.d.mts +4 -1
  96. package/dist/types/trading/place-order/index.place-order.types.d.ts +4 -1
  97. package/dist/types/trading/place-order/index.place-order.utils.d.mts +3 -1
  98. package/dist/types/trading/place-order/index.place-order.utils.d.ts +3 -1
  99. package/package.json +3 -3
@@ -8,10 +8,10 @@ import {
8
8
  getTradingValueLabel,
9
9
  getTradingVenueLabel,
10
10
  resolveOrderEligibilityMessage
11
- } from "./chunk-54PCEK6G.mjs";
11
+ } from "./chunk-UFC7L74C.mjs";
12
12
  import {
13
13
  GeoBlockBanner
14
- } from "./chunk-NWJHFGBZ.mjs";
14
+ } from "./chunk-55ODXLOS.mjs";
15
15
  import {
16
16
  AGG_TERMS_OF_SERVICE_URL,
17
17
  Button,
@@ -31,13 +31,14 @@ import {
31
31
  UserTrustIcon,
32
32
  VenueLogo,
33
33
  __async,
34
+ __pow,
34
35
  __spreadProps,
35
36
  __spreadValues,
36
37
  cn,
37
38
  formatUsd,
38
39
  getMotionClassName,
39
40
  skeletonViews
40
- } from "./chunk-SJLHOAKK.mjs";
41
+ } from "./chunk-QUZWA34R.mjs";
41
42
 
42
43
  // src/trading/types.ts
43
44
  import { Venue, enumGuard, isFiniteNonNeg, safeParse } from "@agg-build/sdk";
@@ -82,11 +83,11 @@ import {
82
83
  getWalletAddressFromUserProfile,
83
84
  invalidateBalanceQueries,
84
85
  invalidatePositionQueries,
86
+ mergeBestPricesPreferringLive,
85
87
  requestAggAuthChooserOpen,
86
88
  resolveEventTradingState,
87
89
  resolveMarketTradingState,
88
90
  resolveOrderEligibility,
89
- TradeSide,
90
91
  useAggAuthContext,
91
92
  useAggBalanceState,
92
93
  useAggClient as useAggClient2,
@@ -99,8 +100,8 @@ import {
99
100
  useLabels,
100
101
  useLiveBestPrices,
101
102
  useLiveOutcomePrices,
103
+ useManagedBalances,
102
104
  useQueryClient,
103
- mergeBestPricesPreferringLive,
104
105
  useSdkUiConfig,
105
106
  useSmartRoute
106
107
  } from "@agg-build/hooks";
@@ -818,13 +819,19 @@ var getTradingRoutePriceLabel = (value) => {
818
819
  const centsValue = Number.isFinite(value) ? value * 100 : 0;
819
820
  return `${routePriceLabelFormatter.format(centsValue)}\xA2`;
820
821
  };
822
+ var isQuoteBelowVenueMinimum = (quoteData) => {
823
+ if (!quoteData) return false;
824
+ if (quoteData.status === "insufficient_balance") return false;
825
+ if (quoteData.status === "min_order_size_violated") return true;
826
+ return typeof quoteData.error === "string" && quoteData.error.startsWith("Trade below ");
827
+ };
821
828
  var resolvePlaceOrderQuoteStatus = ({
822
829
  amount,
823
830
  labels,
824
831
  quoteData,
825
832
  selectedMarket
826
833
  }) => {
827
- var _a, _b, _c, _d;
834
+ var _a, _b, _c;
828
835
  if (!selectedMarket) {
829
836
  return {
830
837
  tone: "warning",
@@ -833,43 +840,46 @@ var resolvePlaceOrderQuoteStatus = ({
833
840
  };
834
841
  }
835
842
  if (!quoteData) return void 0;
836
- if (quoteData.status === "no_orderbooks") {
843
+ if (quoteData.status === "insufficient_balance") {
844
+ return void 0;
845
+ }
846
+ if (isQuoteBelowVenueMinimum(quoteData)) {
837
847
  return {
838
848
  tone: "error",
839
- message: labels.noOrderbooks,
849
+ message: labels.minOrderSizeViolated,
840
850
  placement: "above-action"
841
851
  };
842
852
  }
843
- if (quoteData.status === "infeasible") {
853
+ if (quoteData.status === "no_orderbooks") {
844
854
  return {
845
855
  tone: "error",
846
- message: labels.insufficientLiquidity,
856
+ message: labels.noOrderbooks,
847
857
  placement: "above-action"
848
858
  };
849
859
  }
850
- if (quoteData.status === "min_order_size_violated") {
860
+ if (quoteData.status === "infeasible") {
851
861
  return {
852
862
  tone: "error",
853
- message: (_a = quoteData.message) != null ? _a : labels.minOrderSizeViolated,
863
+ message: labels.insufficientLiquidity,
854
864
  placement: "above-action"
855
865
  };
856
866
  }
857
867
  if (quoteData.status === "insufficient_input_amount") {
858
868
  return {
859
869
  tone: "error",
860
- message: (_b = quoteData.message) != null ? _b : labels.insufficientInputAmount,
870
+ message: (_a = quoteData.message) != null ? _a : labels.insufficientInputAmount,
861
871
  placement: "above-action"
862
872
  };
863
873
  }
864
874
  if (quoteData.status === "invalid_input") {
865
875
  return {
866
876
  tone: "error",
867
- message: (_c = quoteData.message) != null ? _c : labels.quoteUnavailable,
877
+ message: (_b = quoteData.message) != null ? _b : labels.quoteUnavailable,
868
878
  placement: "above-action"
869
879
  };
870
880
  }
871
881
  if (quoteData.status === "insufficient_position") {
872
- const total = (_d = quoteData.positionAvailability) == null ? void 0 : _d.totalSellableShares;
882
+ const total = (_c = quoteData.positionAvailability) == null ? void 0 : _c.totalSellableShares;
873
883
  const message = total != null ? labels.insufficientPosition(total) : labels.insufficientPositionGeneric;
874
884
  return { tone: "error", message, placement: "above-action" };
875
885
  }
@@ -887,9 +897,6 @@ var resolvePlaceOrderQuoteStatus = ({
887
897
  placement: "above-action"
888
898
  };
889
899
  }
890
- if (quoteData.status === "insufficient_balance") {
891
- return void 0;
892
- }
893
900
  if (quoteData.status !== "ok") {
894
901
  return {
895
902
  tone: "error",
@@ -1045,6 +1052,14 @@ var resolveExecutionVenueFromQuote = (quoteData) => {
1045
1052
  const parsed = parseVenue(dominantFill == null ? void 0 : dominantFill.venue);
1046
1053
  return parsed.success ? parsed.data : void 0;
1047
1054
  };
1055
+ var routeCardsHaveSameVenueIdentity = (a, b) => {
1056
+ if (a.kind !== b.kind) return false;
1057
+ if (a.kind === "venue") return a.venue === b.venue;
1058
+ const venuesA = [...new Set(a.quoteData.fills.map((f) => f.venue))].sort();
1059
+ const venuesB = [...new Set(b.quoteData.fills.map((f) => f.venue))].sort();
1060
+ if (venuesA.length !== venuesB.length) return false;
1061
+ return venuesA.every((v, i) => v === venuesB[i]);
1062
+ };
1048
1063
  var getPlaceOrderPotentialReturn = (quoteData) => {
1049
1064
  var _a, _b;
1050
1065
  if (!((_a = quoteData == null ? void 0 : quoteData.fills) == null ? void 0 : _a.length) || quoteData.fills.length < 2) return 0;
@@ -1222,7 +1237,20 @@ var VENUE_UNAVAILABLE_ERROR_PATTERN = /\b(unavailable|unreachable|timeout|timed
1222
1237
  var ALCHEMY_SPONSORSHIP_ERROR_PATTERN = /\bsponsorship failed: sender has no balance of the token for erc20 sponsorship\b/i;
1223
1238
  var ALCHEMY_PREPARE_CALLS_ERROR_PATTERN = /\bwallet_prepareCalls\b/i;
1224
1239
  var DAG_CHECK_BALANCE_SHORTFALL_PATTERN = /\bInsufficient balance on chain\s+\d+\s+token\s+\S+:/i;
1225
- var ALCHEMY_BALANCE_REVERT_PATTERN = /\b(transfer amount exceeds balance|transferFrom failed|insufficient balance|insufficient funds)\b/i;
1240
+ var VENUE_CONNECTOR_UNREACHABLE_PATTERN = /\bvenue-connector\s+unreachable\b/i;
1241
+ var POLYMARKET_DEADLINE_TOO_SOON_PATTERN = /\bdeadline too soon\b/i;
1242
+ var SELL_NO_ONCHAIN_POSITION_PATTERN = /don'?t currently hold any on-chain shares/i;
1243
+ var VENUE_QUOTE_UNFILLABLE_PATTERN = /couldn'?t fill this order at the quoted price|no in-tolerance depth|couldn'?t fill this order at the quoted/i;
1244
+ var QUOTED_PRICE_UNAVAILABLE_PATTERN = /Quoted price is no longer available|missing a valid quoted price/i;
1245
+ var VENUE_MIN_ORDER_SIZE_PATTERN = /below (?:the )?(?:venue |Limitless'?s |Polymarket'?s |Hyperliquid'?s |predict\.fun'?s )?(?:0\.01-share )?minimum|Order amount too small/i;
1246
+ var SOURCE_BALANCE_CHANGED_PATTERN = /balance changed since the quote|wallet holds 0 (?:USDC|pUSD|of tokenId)|Polygon balance changed/i;
1247
+ var VENUE_MARKET_RESOLVED_PATTERN = /(?:Limitless|Myriad|Polymarket|Kalshi)?\s*market\s+(?:just\s+)?resolved|market just resolved/i;
1248
+ var DFLOW_WALLET_UNVERIFIED_PATTERN = /(?:wallet\s+needs\s+to\s+be\s+verified\s+with\s+dFlow|dflow\.net\/proof)/i;
1249
+ var VENUE_NO_QUOTE_PATH_PATTERN = /No active quote path/i;
1250
+ var SOLANA_BLOCKHASH_EXPIRED_PATTERN = /\b(blockhash(?:\s+(?:expired|not\s+found))?|TransactionExpiredBlockheightExceeded|transaction\s+expired)\b/i;
1251
+ var VENUE_RATE_LIMITED_PATTERN = /\b(429|rate[\s-]?limit(?:ed)?|too\s+many\s+requests|backoff)\b/i;
1252
+ var SERVICE_BLOCKED_ORDER_PATTERN = /Something on our side blocked this order/i;
1253
+ var ALCHEMY_BALANCE_REVERT_PATTERN = /\b(transfer amount exceeds (?:balance|allowance)|transferFrom failed|insufficient balance|insufficient funds|insufficient allowance)\b/i;
1226
1254
  var ALCHEMY_REVERT_DATA_SELECTOR_PATTERN = /\brevertData["']?:?\s*['"]?(0x[0-9a-fA-F]{8})/i;
1227
1255
  var REVERT_SELECTOR_MESSAGES = {
1228
1256
  // Solady TransferFromFailed() — ERC-20 transferFrom revert. Same recovery
@@ -1243,6 +1271,7 @@ function lookupRevertSelectorMessage(message) {
1243
1271
  }
1244
1272
  var ALCHEMY_SPONSORSHIP_POLICY_PATTERN = /\b(SPONSORSHIP_FAILED|sponsorship.*(quota|cap|exhausted|disabled)|policy.*(disabled|not found|exhausted))\b/i;
1245
1273
  var ALCHEMY_POLICY_MAX_COUNT_PATTERN = /\bSponsorship failed: Policy (max count|count) exceeded\b/i;
1274
+ var ORDER_FAILED_PREFIX_PATTERN = /^Order failed\s+(?:-|--|\u2014)\s+/i;
1246
1275
  var VENUE_TERMINATED_STATUS_PATTERN = /\bterminated with status=(\w+)/i;
1247
1276
  var friendlyTerminatedStatusMessage = (status) => {
1248
1277
  const normalized = status.toLowerCase();
@@ -1255,6 +1284,12 @@ var friendlyTerminatedStatusMessage = (status) => {
1255
1284
  if (normalized === "rejected") {
1256
1285
  return "The venue rejected your order. Please try again.";
1257
1286
  }
1287
+ if (normalized === "failed") {
1288
+ return "Order didn't settle on-chain. Please try again.";
1289
+ }
1290
+ if (normalized === "unmatched") {
1291
+ return "No liquidity matched your order at the quoted price. Try a smaller size or re-quote.";
1292
+ }
1258
1293
  return "Your order did not fill. Please try again.";
1259
1294
  };
1260
1295
  var tryParseJsonErrorValue = (value) => {
@@ -1289,33 +1324,70 @@ var normalizePlaceOrderErrorMessage = ({
1289
1324
  fallbackMessage,
1290
1325
  labels
1291
1326
  }) => {
1292
- var _a, _b;
1327
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
1293
1328
  const extractedMessage = extractPlaceOrderErrorMessage(errorMessage);
1294
1329
  if (!extractedMessage) return fallbackMessage;
1295
- if (DAG_CHECK_BALANCE_SHORTFALL_PATTERN.test(extractedMessage)) {
1330
+ const normalizedMessage = extractedMessage.replace(ORDER_FAILED_PREFIX_PATTERN, "").trim();
1331
+ if (DAG_CHECK_BALANCE_SHORTFALL_PATTERN.test(normalizedMessage)) {
1296
1332
  return (_a = labels == null ? void 0 : labels.quoteBalanceMismatch) != null ? _a : "Quote balance mismatch. Try a different amount.";
1297
1333
  }
1298
- if (ALCHEMY_BALANCE_REVERT_PATTERN.test(extractedMessage)) {
1299
- return "Your balance changed since the quote. Please refresh and try again.";
1334
+ if (VENUE_CONNECTOR_UNREACHABLE_PATTERN.test(normalizedMessage)) {
1335
+ return (_b = labels == null ? void 0 : labels.serviceTemporarilyUnavailable) != null ? _b : "Service temporarily unavailable. Please try again in a moment.";
1336
+ }
1337
+ if (POLYMARKET_DEADLINE_TOO_SOON_PATTERN.test(normalizedMessage)) {
1338
+ return (_c = labels == null ? void 0 : labels.orderDeadlineExpiredBeforeSubmission) != null ? _c : "Order deadline expired before submission. Please try again.";
1339
+ }
1340
+ if (DFLOW_WALLET_UNVERIFIED_PATTERN.test(normalizedMessage)) {
1341
+ return (_d = labels == null ? void 0 : labels.dflowWalletUnverified) != null ? _d : "Your Solana wallet needs to be verified with dFlow before you can trade Kalshi markets. Verify at https://dflow.net/proof, then try again.";
1342
+ }
1343
+ if (SELL_NO_ONCHAIN_POSITION_PATTERN.test(normalizedMessage)) {
1344
+ return (_e = labels == null ? void 0 : labels.sellNoOnchainPosition) != null ? _e : "You don't currently hold any on-chain shares of this outcome. If you just sold or redeemed elsewhere, your position display will refresh shortly \u2014 try again after that.";
1345
+ }
1346
+ if (VENUE_MARKET_RESOLVED_PATTERN.test(normalizedMessage)) {
1347
+ return (_f = labels == null ? void 0 : labels.venueMarketResolved) != null ? _f : "This market just resolved. Pick a different market or wait for the next round.";
1348
+ }
1349
+ if (VENUE_NO_QUOTE_PATH_PATTERN.test(normalizedMessage)) {
1350
+ return (_g = labels == null ? void 0 : labels.venueNoQuotePath) != null ? _g : "No active quote path for this market right now. Try a different size, or wait a moment and re-quote.";
1351
+ }
1352
+ if (QUOTED_PRICE_UNAVAILABLE_PATTERN.test(normalizedMessage)) {
1353
+ return (_h = labels == null ? void 0 : labels.quoteUnavailable) != null ? _h : "Quote temporarily unavailable. Please try again.";
1354
+ }
1355
+ if (VENUE_QUOTE_UNFILLABLE_PATTERN.test(normalizedMessage)) {
1356
+ return (_i = labels == null ? void 0 : labels.venueQuoteUnfillable) != null ? _i : "The venue couldn't fill this order at the quoted price right now. Try a smaller size, a higher slippage tolerance, or wait a moment and re-quote.";
1357
+ }
1358
+ if (VENUE_MIN_ORDER_SIZE_PATTERN.test(normalizedMessage)) {
1359
+ return (_j = labels == null ? void 0 : labels.venueMinOrderSize) != null ? _j : "Order size is below the venue minimum. Try a larger amount.";
1360
+ }
1361
+ if (SOURCE_BALANCE_CHANGED_PATTERN.test(normalizedMessage)) {
1362
+ return (_k = labels == null ? void 0 : labels.sourceBalanceChanged) != null ? _k : "Your balance changed since the quote. Refresh and try again, or pick a smaller amount.";
1363
+ }
1364
+ if (SOLANA_BLOCKHASH_EXPIRED_PATTERN.test(normalizedMessage)) {
1365
+ return (_l = labels == null ? void 0 : labels.solanaBlockhashExpired) != null ? _l : "Solana transaction expired before submission. Please re-quote and try again.";
1300
1366
  }
1301
- const selectorMessage = lookupRevertSelectorMessage(extractedMessage);
1367
+ if (VENUE_RATE_LIMITED_PATTERN.test(normalizedMessage)) {
1368
+ return (_m = labels == null ? void 0 : labels.venueRateLimited) != null ? _m : "The venue is rate-limiting requests right now. Please wait a moment and try again.";
1369
+ }
1370
+ if (SERVICE_BLOCKED_ORDER_PATTERN.test(normalizedMessage)) {
1371
+ return (_n = labels == null ? void 0 : labels.serviceBlockedOrder) != null ? _n : "Something on our side blocked this order. Please contact support if it keeps happening \u2014 retrying with the same quote will hit the same issue.";
1372
+ }
1373
+ if (ALCHEMY_BALANCE_REVERT_PATTERN.test(normalizedMessage)) {
1374
+ return (_o = labels == null ? void 0 : labels.sourceBalanceChanged) != null ? _o : "Your balance changed since the quote. Refresh and try again, or pick a smaller amount.";
1375
+ }
1376
+ const selectorMessage = lookupRevertSelectorMessage(normalizedMessage);
1302
1377
  if (selectorMessage) {
1303
1378
  return selectorMessage;
1304
1379
  }
1305
- if (ALCHEMY_POLICY_MAX_COUNT_PATTERN.test(extractedMessage)) {
1380
+ if (ALCHEMY_POLICY_MAX_COUNT_PATTERN.test(normalizedMessage)) {
1306
1381
  return "Sponsored execution is temporarily unavailable (sponsor policy capacity reached). Please try again in a few minutes.";
1307
1382
  }
1308
- if (ALCHEMY_SPONSORSHIP_POLICY_PATTERN.test(extractedMessage) || ALCHEMY_SPONSORSHIP_ERROR_PATTERN.test(extractedMessage)) {
1309
- return "Sponsored execution is temporarily unavailable. Please try again.";
1310
- }
1311
- if (ALCHEMY_PREPARE_CALLS_ERROR_PATTERN.test(extractedMessage)) {
1383
+ if (ALCHEMY_SPONSORSHIP_POLICY_PATTERN.test(normalizedMessage) || ALCHEMY_SPONSORSHIP_ERROR_PATTERN.test(normalizedMessage) || ALCHEMY_PREPARE_CALLS_ERROR_PATTERN.test(normalizedMessage)) {
1312
1384
  return "Sponsored execution is temporarily unavailable. Please try again.";
1313
1385
  }
1314
- const terminatedMatch = extractedMessage.match(VENUE_TERMINATED_STATUS_PATTERN);
1386
+ const terminatedMatch = normalizedMessage.match(VENUE_TERMINATED_STATUS_PATTERN);
1315
1387
  if (terminatedMatch) {
1316
- return friendlyTerminatedStatusMessage((_b = terminatedMatch[1]) != null ? _b : "");
1388
+ return friendlyTerminatedStatusMessage((_p = terminatedMatch[1]) != null ? _p : "");
1317
1389
  }
1318
- return extractedMessage;
1390
+ return normalizedMessage;
1319
1391
  };
1320
1392
  var resolvePlaceOrderFailureKind = ({
1321
1393
  errorMessage,
@@ -1862,17 +1934,17 @@ var PlaceOrderSuccessView = ({
1862
1934
  onDone,
1863
1935
  onShare: _onShare
1864
1936
  }) => {
1865
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1937
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1866
1938
  const [isExecutionDetailsExpanded, setIsExecutionDetailsExpanded] = useState2(true);
1867
- const newTradeLabel = (_a = tradingLabels.orderNewTrade) != null ? _a : "New Trade";
1868
- const _shareLabel = (_b = tradingLabels.orderShare) != null ? _b : "Share";
1939
+ const doneLabel = tradingLabels.orderDone;
1940
+ const _shareLabel = (_a = tradingLabels.orderShare) != null ? _a : "Share";
1869
1941
  const potentialReturnLabel = summary.potentialReturnLabel && tradingLabels.potentialReturnBonus ? tradingLabels.potentialReturnBonus(summary.potentialReturnLabel) : summary.potentialReturnLabel ? `+${summary.potentialReturnLabel} Better Payout` : null;
1870
- const resolvedActionLabel = (_c = summary.actionLabel) != null ? _c : tradingLabels.orderSuccessTitle;
1871
- const resolvedTradeSide = (_d = summary.tradeSide) != null ? _d : "buy";
1872
- const resolvedAmountLabel = (_e = summary.amountLabel) != null ? _e : resolvedTradeSide === "sell" ? summary.shares : summary.estimatedCost;
1873
- const resolvedToWinLabel = (_f = summary.toWinLabel) != null ? _f : resolvedTradeSide === "sell" ? summary.estimatedCost : resolveBuyToWinLabel(summary.shares);
1874
- const executionStepGroups = (_g = summary.executionStepGroups) != null ? _g : [];
1875
- const finalStep = (_h = executionStepGroups.at(-1)) == null ? void 0 : _h[0];
1942
+ const resolvedActionLabel = (_b = summary.actionLabel) != null ? _b : tradingLabels.orderSuccessTitle;
1943
+ const resolvedTradeSide = (_c = summary.tradeSide) != null ? _c : "buy";
1944
+ const resolvedAmountLabel = (_d = summary.amountLabel) != null ? _d : resolvedTradeSide === "sell" ? summary.shares : summary.estimatedCost;
1945
+ const resolvedToWinLabel = (_e = summary.toWinLabel) != null ? _e : resolvedTradeSide === "sell" ? summary.estimatedCost : resolveBuyToWinLabel(summary.shares);
1946
+ const executionStepGroups = (_f = summary.executionStepGroups) != null ? _f : [];
1947
+ const finalStep = (_g = executionStepGroups.at(-1)) == null ? void 0 : _g[0];
1876
1948
  const detailedStepGroups = executionStepGroups.slice(0, -1);
1877
1949
  const hasExecutionDetails = detailedStepGroups.length > 0;
1878
1950
  const resolveStepIconName = (tone) => {
@@ -1887,7 +1959,7 @@ var PlaceOrderSuccessView = ({
1887
1959
  /* @__PURE__ */ jsx3(
1888
1960
  RemoteImage,
1889
1961
  {
1890
- src: (_i = summary.eventImage) != null ? _i : null,
1962
+ src: (_h = summary.eventImage) != null ? _h : null,
1891
1963
  alt: "",
1892
1964
  className: "h-12 w-12 shrink-0 overflow-hidden rounded-agg-lg object-cover"
1893
1965
  }
@@ -2007,7 +2079,7 @@ var PlaceOrderSuccessView = ({
2007
2079
  ] }),
2008
2080
  summary.potentialReturnLabel ? /* @__PURE__ */ jsxs2("div", { className: "flex w-full flex-col items-center justify-center gap-1 overflow-hidden rounded-agg-lg border border-agg-primary/50 bg-gradient-to-b from-agg-primary/8 to-agg-primary/15 p-3 text-center", children: [
2009
2081
  /* @__PURE__ */ jsx3("p", { className: "bg-gradient-to-r from-agg-primary to-agg-primary-hover bg-clip-text text-agg-lg font-agg-bold leading-[28px] text-transparent", children: potentialReturnLabel }),
2010
- /* @__PURE__ */ jsx3("p", { className: "text-agg-xs leading-agg-4 text-agg-foreground", children: (_j = tradingLabels.withSmartRouting) != null ? _j : "with Smart Routing" })
2082
+ /* @__PURE__ */ jsx3("p", { className: "text-agg-xs leading-agg-4 text-agg-foreground", children: (_i = tradingLabels.withSmartRouting) != null ? _i : "with Smart Routing" })
2011
2083
  ] }) : null,
2012
2084
  /* @__PURE__ */ jsx3("div", { className: "agg-order-success-actions flex gap-3", children: /* @__PURE__ */ jsx3(
2013
2085
  Button,
@@ -2015,9 +2087,9 @@ var PlaceOrderSuccessView = ({
2015
2087
  variant: "secondary",
2016
2088
  size: "large",
2017
2089
  className: "flex-1",
2018
- "aria-label": newTradeLabel,
2090
+ "aria-label": doneLabel,
2019
2091
  onClick: onDone,
2020
- children: newTradeLabel
2092
+ children: doneLabel
2021
2093
  }
2022
2094
  ) })
2023
2095
  ] }) });
@@ -2334,17 +2406,10 @@ var PlaceOrderResolvedView = ({
2334
2406
  resolvedClaim,
2335
2407
  className
2336
2408
  }) => {
2337
- var _a, _b, _c, _d, _e, _f, _g, _h;
2409
+ var _a, _b, _c, _d, _e;
2338
2410
  const labels = useLabels();
2339
2411
  const tradingLabels = labels.trading;
2340
2412
  const extendedTradingLabels = tradingLabels;
2341
- const winningOutcomeLabel = (_c = (_b = (_a = tradingState.winningOutcome) == null ? void 0 : _a.label) == null ? void 0 : _b.trim().toLowerCase()) != null ? _c : "";
2342
- const isPositiveWinningOutcome = ["yes", "up", "buy", "long", "true"].includes(
2343
- winningOutcomeLabel
2344
- );
2345
- const resolvedIconName = isPositiveWinningOutcome ? "success-check" : "close";
2346
- const resolvedIconToneClassName = isPositiveWinningOutcome ? "text-agg-success" : "text-agg-error";
2347
- const resolvedIconContainerClassName = isPositiveWinningOutcome ? "bg-agg-success/15" : "bg-agg-error/15";
2348
2413
  return /* @__PURE__ */ jsx4(
2349
2414
  Card,
2350
2415
  {
@@ -2361,9 +2426,9 @@ var PlaceOrderResolvedView = ({
2361
2426
  {
2362
2427
  className: cn(
2363
2428
  "flex h-15 w-15 items-center justify-center rounded-full",
2364
- resolvedIconContainerClassName
2429
+ "bg-agg-primary/15"
2365
2430
  ),
2366
- children: /* @__PURE__ */ jsx4(Icon, { name: resolvedIconName, className: cn("h-6 w-6", resolvedIconToneClassName) })
2431
+ children: /* @__PURE__ */ jsx4(Icon, { name: "success-check", className: cn("h-6 w-6", "text-agg-primary") })
2367
2432
  }
2368
2433
  ),
2369
2434
  /* @__PURE__ */ jsxs3(
@@ -2383,18 +2448,18 @@ var PlaceOrderResolvedView = ({
2383
2448
  resolvedClaim ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
2384
2449
  /* @__PURE__ */ jsx4("div", { className: "h-px w-full bg-agg-separator" }),
2385
2450
  /* @__PURE__ */ jsxs3("div", { className: "flex w-full flex-col gap-5 p-6", children: [
2386
- /* @__PURE__ */ jsx4(Typography, { variant: "body-strong", className: "text-center", children: (_d = extendedTradingLabels.resolvedEarningsTitle) != null ? _d : "Your Earnings" }),
2451
+ /* @__PURE__ */ jsx4(Typography, { variant: "body-strong", className: "text-center", children: (_a = extendedTradingLabels.resolvedEarningsTitle) != null ? _a : "Your Earnings" }),
2387
2452
  /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-3 text-agg-sm leading-agg-5 text-agg-foreground", children: [
2388
2453
  resolvedClaim.resolutionDateLabel ? /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between gap-4", children: [
2389
- /* @__PURE__ */ jsx4("span", { children: (_e = extendedTradingLabels.resolvedResolutionDateLabel) != null ? _e : "Resolution date" }),
2454
+ /* @__PURE__ */ jsx4("span", { children: (_b = extendedTradingLabels.resolvedResolutionDateLabel) != null ? _b : "Resolution date" }),
2390
2455
  /* @__PURE__ */ jsx4("span", { className: "font-agg-bold", children: resolvedClaim.resolutionDateLabel })
2391
2456
  ] }) : null,
2392
2457
  /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between gap-4", children: [
2393
- /* @__PURE__ */ jsx4("span", { children: (_f = extendedTradingLabels.resolvedSharesLabel) != null ? _f : "Shares" }),
2458
+ /* @__PURE__ */ jsx4("span", { children: (_c = extendedTradingLabels.resolvedSharesLabel) != null ? _c : "Shares" }),
2394
2459
  /* @__PURE__ */ jsx4("span", { className: "font-agg-bold", children: resolvedClaim.sharesLabel })
2395
2460
  ] }),
2396
2461
  /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between gap-4", children: [
2397
- /* @__PURE__ */ jsx4("span", { children: (_g = extendedTradingLabels.resolvedTotalPayoutLabel) != null ? _g : "Total payout" }),
2462
+ /* @__PURE__ */ jsx4("span", { children: (_d = extendedTradingLabels.resolvedTotalPayoutLabel) != null ? _d : "Total payout" }),
2398
2463
  /* @__PURE__ */ jsx4("span", { className: "font-agg-bold", children: resolvedClaim.totalPayoutLabel })
2399
2464
  ] })
2400
2465
  ] }),
@@ -2406,7 +2471,7 @@ var PlaceOrderResolvedView = ({
2406
2471
  onClick: resolvedClaim.onClaim,
2407
2472
  isLoading: resolvedClaim.isClaiming,
2408
2473
  disabled: resolvedClaim.isClaiming,
2409
- children: (_h = extendedTradingLabels.claimWinnings) != null ? _h : "Claim Winnings"
2474
+ children: (_e = extendedTradingLabels.claimWinnings) != null ? _e : "Claim Winnings"
2410
2475
  }
2411
2476
  ) : null
2412
2477
  ] })
@@ -2733,6 +2798,7 @@ var PlaceOrder = ({
2733
2798
  className,
2734
2799
  classNames,
2735
2800
  eventTradingState,
2801
+ executionMode = "live",
2736
2802
  isLoading = false,
2737
2803
  isPrimaryActionDisabled = false,
2738
2804
  isPrimaryActionLoading = false,
@@ -2741,7 +2807,6 @@ var PlaceOrder = ({
2741
2807
  onClose,
2742
2808
  onOutcomeChange,
2743
2809
  onPrimaryAction,
2744
- onSlippageChange,
2745
2810
  onTabChange,
2746
2811
  onSuccess,
2747
2812
  onError,
@@ -2818,7 +2883,27 @@ var PlaceOrder = ({
2818
2883
  );
2819
2884
  const isResolvedOutcomeCtaLocked = resolvedEventTradingState.kind === "resolved" || resolvedTradingState.kind === "resolved";
2820
2885
  const { isAuthenticated, user } = useAggAuthContext();
2821
- const { totalBalance, isLoading: isBalanceLoading } = useAggBalanceState();
2886
+ const isPaperMode = executionMode === "paper";
2887
+ const liveBalanceState = useAggBalanceState();
2888
+ const paperBalancesQuery = useManagedBalances({
2889
+ enabled: Boolean(isAuthenticated && isPaperMode),
2890
+ mode: "paper"
2891
+ });
2892
+ const paperTotalBalance = useMemo2(() => {
2893
+ var _a2, _b2;
2894
+ const cash = (_b2 = (_a2 = paperBalancesQuery.balances) == null ? void 0 : _a2.cash) != null ? _b2 : [];
2895
+ return cash.reduce((sum, token) => {
2896
+ if (!token.tokenSymbol.toUpperCase().includes("USD")) return sum;
2897
+ return sum + token.chains.reduce((chainSum, chain) => {
2898
+ var _a3;
2899
+ const raw = Number(chain.balanceRaw);
2900
+ if (!Number.isFinite(raw)) return chainSum;
2901
+ return chainSum + raw / __pow(10, (_a3 = chain.decimals) != null ? _a3 : token.decimals);
2902
+ }, 0);
2903
+ }, 0);
2904
+ }, [paperBalancesQuery.balances]);
2905
+ const totalBalance = isPaperMode ? paperTotalBalance : liveBalanceState.totalBalance;
2906
+ const isBalanceLoading = isPaperMode ? paperBalancesQuery.isLoading : liveBalanceState.isLoading;
2822
2907
  const executeManaged = useExecuteManaged();
2823
2908
  const aggClient = useAggClient2();
2824
2909
  const queryClient = useQueryClient();
@@ -2852,7 +2937,7 @@ var PlaceOrder = ({
2852
2937
  const [internalTab, setInternalTab] = useState3("buy");
2853
2938
  const [internalAmount, setInternalAmount] = useState3(PLACE_ORDER_DEFAULT_AMOUNT);
2854
2939
  const [sellFilledForOutcomeId, setSellFilledForOutcomeId] = useState3(null);
2855
- const [internalSlippage, setInternalSlippage] = useState3(DEFAULT_SLIPPAGE_VALUE);
2940
+ const [internalSlippage] = useState3(DEFAULT_SLIPPAGE_VALUE);
2856
2941
  const [isRoutesExpanded, setIsRoutesExpanded] = useState3(false);
2857
2942
  const [selectedRouteCardId, setSelectedRouteCardId] = useState3(null);
2858
2943
  const [isSplitDetailOpen, setIsSplitDetailOpen] = useState3(false);
@@ -2887,7 +2972,8 @@ var PlaceOrder = ({
2887
2972
  isLoading: isExecutionPositionsLoading,
2888
2973
  isFetching: isExecutionPositionsFetching
2889
2974
  } = useExecutionPositions({
2890
- enabled: Boolean(isAuthenticated && isSell)
2975
+ enabled: Boolean(isAuthenticated && isSell),
2976
+ mode: isPaperMode ? "paper" : void 0
2891
2977
  });
2892
2978
  const smartRoute = useSmartRoute({
2893
2979
  venueMarketOutcomeId: scopedSelectedOutcomeId,
@@ -2900,6 +2986,7 @@ var PlaceOrder = ({
2900
2986
  slipCapBps: 1e6,
2901
2987
  compareVenues: true,
2902
2988
  tradeSide: isSell ? "sell" : "buy",
2989
+ mode: isPaperMode ? "paper" : void 0,
2903
2990
  enabled: debouncedAmount > 0 && orderEligibility.canPlaceOrder
2904
2991
  });
2905
2992
  const currentSellableShares = useMemo2(() => {
@@ -3039,6 +3126,7 @@ var PlaceOrder = ({
3039
3126
  );
3040
3127
  const executionProgress = useExecutionProgress({
3041
3128
  orderIds: (_q = submissionProgressState == null ? void 0 : submissionProgressState.orderIds) != null ? _q : null,
3129
+ mode: isPaperMode ? "paper" : void 0,
3042
3130
  enabled: ((submissionProgressState == null ? void 0 : submissionProgressState.phase) === "submitting" || (submissionProgressState == null ? void 0 : submissionProgressState.phase) === "executing") && !!((_r = submissionProgressState == null ? void 0 : submissionProgressState.orderIds) == null ? void 0 : _r.length)
3043
3131
  });
3044
3132
  const selectedOutcomeLabel = (_u = (_t = (_s = outcomes.find((outcome) => outcome.id === scopedSelectedOutcomeId)) == null ? void 0 : _s.label) != null ? _t : scopedSelectedOutcome == null ? void 0 : scopedSelectedOutcome.label) != null ? _u : "";
@@ -3307,8 +3395,14 @@ var PlaceOrder = ({
3307
3395
  const activeQuoteData = (_B = (_A = selectedRouteCard == null ? void 0 : selectedRouteCard.quoteData) != null ? _A : smartRoute.data) != null ? _B : null;
3308
3396
  const visibleRouteCards = orderedRouteCards.length > PLACE_ORDER_ROUTE_COLLAPSED_CARD_COUNT && !isRoutesExpanded ? orderedRouteCards.slice(0, PLACE_ORDER_ROUTE_COLLAPSED_CARD_COUNT) : orderedRouteCards;
3309
3397
  const hasEnteredAmount = internalAmount > 0;
3398
+ const isQuoteLoading = hasEnteredAmount && (smartRoute.isFetching || smartRoute.isLoading);
3310
3399
  const isInsufficientBalance = !isSell && isAuthenticated && hasEnteredAmount && !isBalanceLoading && internalAmount > totalBalance;
3311
- const isBelowMinimum = !isSell && hasEnteredAmount && internalAmount < MIN_BUY_ORDER_AMOUNT;
3400
+ const isQuoteInsufficientBalance = (activeQuoteData == null ? void 0 : activeQuoteData.status) === "insufficient_balance";
3401
+ const shouldShowInsufficientBalanceAlert = isInsufficientBalance || isQuoteInsufficientBalance;
3402
+ const isBelowClientMinimum = !isSell && hasEnteredAmount && internalAmount < MIN_BUY_ORDER_AMOUNT;
3403
+ const isBelowVenueMinimumFromQuote = isQuoteBelowVenueMinimum(activeQuoteData);
3404
+ const isBelowMinimum = isBelowClientMinimum || isBelowVenueMinimumFromQuote;
3405
+ const belowMinimumMessage = isBelowClientMinimum ? tradingLabels.minimumOrderAmount(MIN_BUY_ORDER_AMOUNT) : tradingLabels.minOrderSizeViolated;
3312
3406
  const quoteStatus = useMemo2(() => {
3313
3407
  if (!orderEligibility.canPlaceOrder) return void 0;
3314
3408
  return resolvePlaceOrderQuoteStatus({
@@ -3403,6 +3497,7 @@ var PlaceOrder = ({
3403
3497
  if (!activeFeeBreakdown) return [];
3404
3498
  return [
3405
3499
  {
3500
+ kind: "amount",
3406
3501
  label: tradingLabels.feeBreakdownVenueFees,
3407
3502
  value: formatUsd(activeFeeBreakdown.venueFees, {
3408
3503
  minimumFractionDigits: 2,
@@ -3410,25 +3505,25 @@ var PlaceOrder = ({
3410
3505
  })
3411
3506
  },
3412
3507
  {
3413
- label: tradingLabels.feeBreakdownBridgeFees,
3414
- value: formatUsd(activeFeeBreakdown.bridgeFees, {
3508
+ kind: "amount",
3509
+ label: tradingLabels.feeBreakdownExecutionGas,
3510
+ value: formatUsd(activeFeeBreakdown.executionGas, {
3415
3511
  minimumFractionDigits: 2,
3416
3512
  maximumFractionDigits: 2
3417
3513
  })
3418
3514
  },
3419
3515
  {
3420
- label: tradingLabels.feeBreakdownExecutionGas,
3421
- value: formatUsd(activeFeeBreakdown.executionGas, {
3516
+ kind: "amount",
3517
+ label: tradingLabels.feeBreakdownBridgeFees,
3518
+ value: formatUsd(activeFeeBreakdown.bridgeFees, {
3422
3519
  minimumFractionDigits: 2,
3423
3520
  maximumFractionDigits: 2
3424
3521
  })
3425
3522
  },
3426
3523
  {
3427
- label: tradingLabels.feeBreakdownTotalFees,
3428
- value: formatUsd(
3429
- activeFeeBreakdown.venueFees + activeFeeBreakdown.bridgeFees + activeFeeBreakdown.executionGas,
3430
- { minimumFractionDigits: 2, maximumFractionDigits: 2 }
3431
- )
3524
+ kind: "badge",
3525
+ label: tradingLabels.feeBreakdownAggMarket,
3526
+ badgeLabel: tradingLabels.feeBreakdownPlatformFeeBadge
3432
3527
  }
3433
3528
  ];
3434
3529
  }, [activeFeeBreakdown, tradingLabels]);
@@ -3449,33 +3544,23 @@ var PlaceOrder = ({
3449
3544
  }, [selectedRouteCard, geoBlockedVenuesFromWarnings]);
3450
3545
  const shouldShowGeoBlockBanner = isTradingBlocked || selectedRouteGeoBlocked || isPrimaryVenueGeoBlocked;
3451
3546
  const actionLabel = `${internalTab === "buy" ? tradingLabels.buy : tradingLabels.sell} ${selectedOutcomeLabel}`.trim();
3452
- const isActionDisabled = isPrimaryActionDisabled || !orderEligibility.canPlaceOrder || isActionLoading || !hasEnteredAmount || !scopedSelectedMarket || isInsufficientBalance || isBelowMinimum || !selectedRouteCard || !selectedRouteCard.quoteData.quoteId || selectedRouteGeoBlocked || !isAuthenticated || quoteStatus !== void 0;
3453
- const shouldShowSmartRouting = orderEligibility.canPlaceOrder && hasEnteredAmount && (orderedRouteCards.length > 0 || smartRoute.isFetching);
3454
- const shouldShowRouteToggle = orderedRouteCards.length > PLACE_ORDER_ROUTE_COLLAPSED_CARD_COUNT;
3455
- const handleStartNewTrade = useCallback2(() => {
3547
+ const isActionDisabled = isPrimaryActionDisabled || !orderEligibility.canPlaceOrder || isActionLoading || !hasEnteredAmount || !scopedSelectedMarket || isInsufficientBalance || isQuoteInsufficientBalance || isBelowMinimum || isQuoteLoading || !selectedRouteCard || !selectedRouteCard.quoteData.quoteId || selectedRouteGeoBlocked || !isAuthenticated || quoteStatus !== void 0;
3548
+ const shouldShowSmartRouting = orderEligibility.canPlaceOrder && hasEnteredAmount && !isBelowMinimum && (orderedRouteCards.length > 0 || smartRoute.isFetching);
3549
+ const shouldShowRouteToggle = !isQuoteLoading && orderedRouteCards.length > PLACE_ORDER_ROUTE_COLLAPSED_CARD_COUNT;
3550
+ const handleReturnToOrderForm = useCallback2(() => {
3456
3551
  const submittedSelection = submittedSelectionRef.current;
3457
3552
  submittedSelectionRef.current = null;
3458
3553
  setSubmissionProgressState(null);
3459
3554
  setSubmissionFeedback(null);
3460
- setInternalAmount(PLACE_ORDER_DEFAULT_AMOUNT);
3461
- setSellFilledForOutcomeId(null);
3462
- setInternalSlippage(DEFAULT_SLIPPAGE_VALUE);
3463
- setInternalTab("buy");
3464
- tradingContext == null ? void 0 : tradingContext.setTradeSide(TradeSide.Buy);
3465
3555
  setIsRoutesExpanded(false);
3466
3556
  setSelectedRouteCardId(null);
3467
- onAmountChange == null ? void 0 : onAmountChange(PLACE_ORDER_DEFAULT_AMOUNT);
3468
- onSlippageChange == null ? void 0 : onSlippageChange(formatPercentageValue(DEFAULT_SLIPPAGE_VALUE));
3469
- onTabChange == null ? void 0 : onTabChange("buy");
3470
3557
  if (submittedSelection && tradingContext) {
3471
3558
  tradingContext.selectMarketAndOutcome(
3472
3559
  submittedSelection.marketId,
3473
3560
  submittedSelection.outcomeId
3474
3561
  );
3475
- } else if (scopedSelectedEvent) {
3476
- tradingContext == null ? void 0 : tradingContext.initializeFromEvent(scopedSelectedEvent);
3477
3562
  }
3478
- }, [onAmountChange, onSlippageChange, onTabChange, scopedSelectedEvent, tradingContext]);
3563
+ }, [tradingContext]);
3479
3564
  const handleShareTrade = () => {
3480
3565
  var _a2, _b2;
3481
3566
  const shareText = (_b2 = (_a2 = submissionProgressState == null ? void 0 : submissionProgressState.summary) == null ? void 0 : _a2.shareText) == null ? void 0 : _b2.trim();
@@ -3515,16 +3600,19 @@ var PlaceOrder = ({
3515
3600
  });
3516
3601
  executionDebugAttemptIdRef.current = (_c2 = debugAttempt == null ? void 0 : debugAttempt.attemptId) != null ? _c2 : null;
3517
3602
  if (onPrimaryAction) {
3603
+ const primaryActionPayload = isPaperMode ? { quoteId, mode: "paper" } : { quoteId };
3518
3604
  debugStore == null ? void 0 : debugStore.appendEvent(debugAttempt.attemptId, {
3519
3605
  kind: "execute_request",
3520
3606
  label: "delegated_to_partner",
3521
- data: { quoteId }
3607
+ data: primaryActionPayload
3522
3608
  });
3523
- onPrimaryAction({ quoteId });
3609
+ onPrimaryAction(primaryActionPayload);
3524
3610
  return;
3525
3611
  }
3526
3612
  try {
3527
- const response = yield executeManaged.mutateAsync({ quoteId });
3613
+ const response = yield executeManaged.mutateAsync(
3614
+ isPaperMode ? { quoteId, mode: "paper" } : { quoteId }
3615
+ );
3528
3616
  if (debugAttempt) {
3529
3617
  debugStore == null ? void 0 : debugStore.appendEvent(debugAttempt.attemptId, {
3530
3618
  kind: "execute_response",
@@ -3569,6 +3657,7 @@ var PlaceOrder = ({
3569
3657
  internalAmount,
3570
3658
  internalSlippage,
3571
3659
  isSell,
3660
+ isPaperMode,
3572
3661
  onPrimaryAction,
3573
3662
  scopedSelectedEvent == null ? void 0 : scopedSelectedEvent.id,
3574
3663
  scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.id,
@@ -3615,8 +3704,8 @@ var PlaceOrder = ({
3615
3704
  ]);
3616
3705
  const handleRetrySubmission = useCallback2(() => __async(null, null, function* () {
3617
3706
  var _a2, _b2, _c2;
3618
- if (!orderEligibility.canPlaceOrder) {
3619
- handleStartNewTrade();
3707
+ if (!orderEligibility.canPlaceOrder || (failureSummary == null ? void 0 : failureSummary.kind) === "generic") {
3708
+ handleReturnToOrderForm();
3620
3709
  return;
3621
3710
  }
3622
3711
  setSubmissionFeedback(null);
@@ -3646,7 +3735,8 @@ var PlaceOrder = ({
3646
3735
  chainBalances: chainBalancesOverride,
3647
3736
  slipCapBps: 1e6,
3648
3737
  compareVenues: true,
3649
- tradeSide: isSell ? "sell" : "buy"
3738
+ tradeSide: isSell ? "sell" : "buy",
3739
+ mode: isPaperMode ? "paper" : void 0
3650
3740
  });
3651
3741
  } else {
3652
3742
  const refetchedQuoteResult = yield smartRoute.refetch();
@@ -3661,8 +3751,10 @@ var PlaceOrder = ({
3661
3751
  quoteData: refetchedQuoteData,
3662
3752
  tradeSide: internalTab
3663
3753
  });
3754
+ const originalSelectedCard = selectedRouteCardId ? orderedRouteCards.find((card) => card.id === selectedRouteCardId) : void 0;
3664
3755
  const refreshedSelectedCard = selectedRouteCardId ? refreshedCards.find((card) => card.id === selectedRouteCardId) : void 0;
3665
- if (selectedRouteCardId && !refreshedSelectedCard) {
3756
+ const venueIdentityChanged = !!originalSelectedCard && !!refreshedSelectedCard && !routeCardsHaveSameVenueIdentity(originalSelectedCard, refreshedSelectedCard);
3757
+ if (selectedRouteCardId && (!refreshedSelectedCard || venueIdentityChanged)) {
3666
3758
  setSubmissionProgressState(null);
3667
3759
  setSubmissionFeedback({
3668
3760
  message: tradingLabels.selectedVenueUnavailable,
@@ -3688,12 +3780,14 @@ var PlaceOrder = ({
3688
3780
  executionProgress.terminalOrderEvents,
3689
3781
  failureSummary == null ? void 0 : failureSummary.kind,
3690
3782
  handleExecuteQuote,
3691
- handleStartNewTrade,
3783
+ handleReturnToOrderForm,
3692
3784
  internalAmount,
3693
3785
  internalTab,
3694
3786
  isSell,
3787
+ isPaperMode,
3695
3788
  onAmountChange,
3696
3789
  orderEligibility.canPlaceOrder,
3790
+ orderedRouteCards,
3697
3791
  scopedSelectedEvent == null ? void 0 : scopedSelectedEvent.venueMarkets,
3698
3792
  scopedSelectedOutcomeId,
3699
3793
  selectedRouteCardId,
@@ -3719,7 +3813,7 @@ var PlaceOrder = ({
3719
3813
  className: resolvedStatusClassName,
3720
3814
  summary: submissionProgressState.summary,
3721
3815
  tradingLabels,
3722
- onDone: handleStartNewTrade,
3816
+ onDone: handleReturnToOrderForm,
3723
3817
  onShare: handleShareTrade
3724
3818
  }
3725
3819
  );
@@ -3733,7 +3827,7 @@ var PlaceOrder = ({
3733
3827
  summary: failureSummary,
3734
3828
  tradingLabels,
3735
3829
  onRetry: handleRetrySubmission,
3736
- onDone: handleStartNewTrade,
3830
+ onDone: handleReturnToOrderForm,
3737
3831
  onSkip: handleSkipToSuccess
3738
3832
  }
3739
3833
  );
@@ -3970,7 +4064,7 @@ var PlaceOrder = ({
3970
4064
  /* @__PURE__ */ jsxs3("div", { className: "agg-order-amount-meta flex flex-col", children: [
3971
4065
  /* @__PURE__ */ jsx4("p", { className: "agg-order-amount-label text-agg-base font-agg-bold leading-agg-6 text-agg-foreground whitespace-nowrap", children: tradingLabels.amount(internalTab) }),
3972
4066
  isAuthenticated ? isSell ? /* @__PURE__ */ jsx4("div", { className: "agg-balance-value flex items-baseline gap-1.5 text-agg-sm leading-agg-5 text-agg-muted-foreground", children: isCurrentSellableSharesLoading ? /* @__PURE__ */ jsx4(LoadingIcon, { size: "small" }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
3973
- /* @__PURE__ */ jsx4("span", { children: tradingLabels.shares(displayedCurrentSellableShares) }),
4067
+ /* @__PURE__ */ jsx4("span", { className: "whitespace-pre", children: tradingLabels.shares(displayedCurrentSellableShares) }),
3974
4068
  displayedCurrentSellableShares > 0 ? /* @__PURE__ */ jsx4(
3975
4069
  "button",
3976
4070
  {
@@ -3995,7 +4089,7 @@ var PlaceOrder = ({
3995
4089
  value: internalAmount,
3996
4090
  onChange: handleAmountChange,
3997
4091
  ariaLabel: tradingLabels.amount(internalTab),
3998
- isInvalid: isInsufficientBalance,
4092
+ isInvalid: isInsufficientBalance || isBelowMinimum,
3999
4093
  disabled: !orderEligibility.canPlaceOrder,
4000
4094
  prefix: internalTab === "buy" ? "$" : "",
4001
4095
  decimalPlaces: isSell ? 6 : 2,
@@ -4009,7 +4103,7 @@ var PlaceOrder = ({
4009
4103
  }
4010
4104
  )
4011
4105
  ] }),
4012
- showFeesBreakdown && hasEnteredAmount && estimatedFeesValue ? /* @__PURE__ */ jsxs3("div", { className: "agg-order-fees-section flex items-center justify-between gap-4", children: [
4106
+ showFeesBreakdown && hasEnteredAmount && !isBelowMinimum && estimatedFeesValue ? /* @__PURE__ */ jsxs3("div", { className: "agg-order-fees-section flex items-center justify-between gap-4", children: [
4013
4107
  /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1.5", children: [
4014
4108
  /* @__PURE__ */ jsx4(
4015
4109
  Typography,
@@ -4023,13 +4117,31 @@ var PlaceOrder = ({
4023
4117
  Tooltip,
4024
4118
  {
4025
4119
  "aria-label": tradingLabels.estimatedFeesTooltipAria,
4026
- content: /* @__PURE__ */ jsx4("div", { className: "flex min-w-[220px] flex-col gap-2", children: feeBreakdownRows.map((row) => /* @__PURE__ */ jsxs3(
4120
+ classNames: {
4121
+ content: cn(
4122
+ "min-w-[220px] max-w-[320px] rounded-[10px] px-5 py-4",
4123
+ "shadow-[0_12px_12px_rgba(0,0,0,0.10)]"
4124
+ ),
4125
+ icon: "h-3 w-3 text-agg-muted-foreground",
4126
+ trigger: "h-3 w-3 text-agg-muted-foreground"
4127
+ },
4128
+ content: /* @__PURE__ */ jsx4("div", { className: "flex w-full flex-col gap-2", children: feeBreakdownRows.map((row) => /* @__PURE__ */ jsxs3(
4027
4129
  "div",
4028
4130
  {
4029
- className: "flex items-center justify-between gap-3 text-agg-sm leading-agg-5",
4131
+ className: "flex items-center justify-between gap-3 text-agg-sm font-agg-normal leading-agg-5 text-agg-foreground",
4030
4132
  children: [
4031
- /* @__PURE__ */ jsx4("span", { className: "text-agg-muted-foreground", children: row.label }),
4032
- /* @__PURE__ */ jsx4("span", { className: "font-agg-bold text-agg-foreground", children: row.value })
4133
+ /* @__PURE__ */ jsx4("span", { children: row.label }),
4134
+ row.kind === "badge" ? /* @__PURE__ */ jsx4(
4135
+ "span",
4136
+ {
4137
+ className: cn(
4138
+ "agg-fee-badge inline-flex items-center justify-center rounded-agg-sm border border-agg-primary/50",
4139
+ "bg-linear-to-b from-agg-primary/8 to-agg-primary/15 px-1.5 py-1",
4140
+ "text-agg-xs font-agg-bold leading-agg-4 text-agg-primary uppercase whitespace-nowrap"
4141
+ ),
4142
+ children: row.badgeLabel
4143
+ }
4144
+ ) : /* @__PURE__ */ jsx4("span", { className: "text-right", children: row.value })
4033
4145
  ]
4034
4146
  },
4035
4147
  row.label
@@ -4037,7 +4149,7 @@ var PlaceOrder = ({
4037
4149
  }
4038
4150
  ) : null
4039
4151
  ] }),
4040
- /* @__PURE__ */ jsx4("p", { className: "text-agg-sm font-agg-bold leading-agg-5 text-agg-foreground", children: estimatedFeesValue })
4152
+ /* @__PURE__ */ jsx4("p", { className: "text-agg-sm leading-agg-5 text-agg-foreground", children: estimatedFeesValue })
4041
4153
  ] }) : null,
4042
4154
  shouldShowSmartRouting ? /* @__PURE__ */ jsxs3("div", { className: "agg-route-panel flex flex-col gap-3", children: [
4043
4155
  /* @__PURE__ */ jsxs3("div", { className: "agg-route-panel-header flex items-center justify-between gap-4", children: [
@@ -4064,7 +4176,19 @@ var PlaceOrder = ({
4064
4176
  }
4065
4177
  ) : null
4066
4178
  ] }),
4067
- /* @__PURE__ */ jsx4("div", { className: "agg-route-list flex flex-col gap-2", children: visibleRouteCards.length > 0 ? visibleRouteCards.map((card) => {
4179
+ /* @__PURE__ */ jsx4("div", { className: "agg-route-list flex flex-col gap-2", children: isQuoteLoading ? /* @__PURE__ */ jsxs3(
4180
+ "div",
4181
+ {
4182
+ className: "agg-route-loading flex flex-col gap-2",
4183
+ role: "status",
4184
+ "aria-label": labels.common.loading,
4185
+ "aria-live": "polite",
4186
+ children: [
4187
+ /* @__PURE__ */ jsx4(PlaceOrderRouteCardSkeleton, {}),
4188
+ /* @__PURE__ */ jsx4(PlaceOrderRouteCardSkeleton, {})
4189
+ ]
4190
+ }
4191
+ ) : visibleRouteCards.length > 0 ? visibleRouteCards.map((card) => {
4068
4192
  return /* @__PURE__ */ jsx4(Fragment, { children: renderRouteCard({
4069
4193
  card,
4070
4194
  enableAnimations,
@@ -4073,12 +4197,9 @@ var PlaceOrder = ({
4073
4197
  onSelect: handleRouteCardSelect,
4074
4198
  tradingLabels
4075
4199
  }) }, card.id);
4076
- }) : smartRoute.isFetching ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
4077
- /* @__PURE__ */ jsx4(PlaceOrderRouteCardSkeleton, {}),
4078
- /* @__PURE__ */ jsx4(PlaceOrderRouteCardSkeleton, {})
4079
- ] }) : null })
4200
+ }) : null })
4080
4201
  ] }) : null,
4081
- hasEnteredAmount && selectedRouteCard && orderEligibility.canPlaceOrder ? /* @__PURE__ */ jsxs3("div", { className: "agg-order-summary flex items-start justify-between gap-4", children: [
4202
+ hasEnteredAmount && selectedRouteCard && !isQuoteLoading && !isBelowMinimum && orderEligibility.canPlaceOrder ? /* @__PURE__ */ jsxs3("div", { className: "agg-order-summary flex items-start justify-between gap-4", children: [
4082
4203
  /* @__PURE__ */ jsxs3("div", { className: "agg-order-summary-meta flex flex-col", children: [
4083
4204
  /* @__PURE__ */ jsx4("p", { className: "agg-order-summary-label text-agg-base font-agg-bold leading-agg-6 text-agg-foreground", children: tradingLabels.toWin(internalTab) }),
4084
4205
  /* @__PURE__ */ jsx4("p", { className: "agg-order-summary-hint text-agg-sm leading-agg-5 text-agg-muted-foreground", children: displayedToWinHint })
@@ -4114,13 +4235,7 @@ var PlaceOrder = ({
4114
4235
  message: submissionFeedback.message
4115
4236
  }
4116
4237
  ) : null,
4117
- !submissionFeedback && orderEligibility.canPlaceOrder && !isInsufficientBalance && isBelowMinimum ? /* @__PURE__ */ jsx4(
4118
- InlineAlert,
4119
- {
4120
- tone: "error",
4121
- message: tradingLabels.minimumOrderAmount(MIN_BUY_ORDER_AMOUNT)
4122
- }
4123
- ) : null,
4238
+ !submissionFeedback && orderEligibility.canPlaceOrder && !isInsufficientBalance && isBelowMinimum ? /* @__PURE__ */ jsx4(InlineAlert, { tone: "error", message: belowMinimumMessage }) : null,
4124
4239
  !submissionFeedback && orderEligibility.canPlaceOrder && !isInsufficientBalance && !isBelowMinimum && quoteStatus ? /* @__PURE__ */ jsx4(InlineAlert, { tone: quoteStatus.tone, message: quoteStatus.message }) : null,
4125
4240
  !submissionFeedback && orderEligibility.canPlaceOrder && !isInsufficientBalance && !isBelowMinimum && !quoteStatus && isAuthenticated && hasEnteredAmount && smartRouteErrorMessage ? /* @__PURE__ */ jsx4(
4126
4241
  InlineAlert,
@@ -4134,7 +4249,7 @@ var PlaceOrder = ({
4134
4249
  }
4135
4250
  ) : null
4136
4251
  ] }) : null,
4137
- !submissionFeedback && !shouldShowGeoBlockBanner && orderEligibility.canPlaceOrder && isInsufficientBalance ? /* @__PURE__ */ jsxs3(
4252
+ !submissionFeedback && !shouldShowGeoBlockBanner && orderEligibility.canPlaceOrder && shouldShowInsufficientBalanceAlert ? /* @__PURE__ */ jsxs3(
4138
4253
  "div",
4139
4254
  {
4140
4255
  className: "agg-order-insufficient-balance-alert flex items-center justify-center gap-2",