@orderly.network/ui-order-entry 2.11.3-rc.0 → 2.12.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
@@ -1155,6 +1155,13 @@ function getScaledPlaceOrderMessage(result) {
1155
1155
  var safeNumber = (val) => {
1156
1156
  return Number.isNaN(Number(val)) ? 0 : Number(val);
1157
1157
  };
1158
+ var SymbolBadge = (props) => {
1159
+ const { brokerId, brokerName, brokerNameRaw } = hooks.useBadgeBySymbol(
1160
+ props.symbol
1161
+ );
1162
+ const badge = brokerName ?? brokerId ?? void 0;
1163
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.SymbolBadge, { badge, fullName: brokerNameRaw });
1164
+ };
1158
1165
  var OrderConfirmDialog = (props) => {
1159
1166
  const { symbolInfo, order, onConfirm, onCancel } = props;
1160
1167
  const { quote, quote_dp, base_dp } = symbolInfo;
@@ -1312,15 +1319,19 @@ var OrderConfirmDialog = (props) => {
1312
1319
  justify: "between",
1313
1320
  className: "oui-orderEntry-orderConfirmDialog-header",
1314
1321
  children: [
1315
- /* @__PURE__ */ jsxRuntime.jsx(
1316
- ui.Text.formatted,
1317
- {
1318
- rule: "symbol",
1319
- showIcon: true,
1320
- className: "oui-orderConfirmDialog-symbol",
1321
- children: order.symbol
1322
- }
1323
- ),
1322
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gap: 2, direction: "column", itemAlign: "start", children: [
1323
+ /* @__PURE__ */ jsxRuntime.jsx(
1324
+ ui.Text.formatted,
1325
+ {
1326
+ rule: "symbol",
1327
+ formatString: "base",
1328
+ showIcon: true,
1329
+ className: "oui-orderConfirmDialog-symbol",
1330
+ children: order.symbol
1331
+ }
1332
+ ),
1333
+ /* @__PURE__ */ jsxRuntime.jsx(SymbolBadge, { symbol: order.symbol })
1334
+ ] }),
1324
1335
  /* @__PURE__ */ jsxRuntime.jsxs(
1325
1336
  ui.Flex,
1326
1337
  {
@@ -1619,6 +1630,136 @@ var MaxQtyConfirm = React3.memo((props) => {
1619
1630
  }
1620
1631
  );
1621
1632
  });
1633
+ var PermissionlessMarketNoticeDialog = (props) => {
1634
+ const { onConfirm, onCancel } = props;
1635
+ const { t } = i18n.useTranslation();
1636
+ const [checked, setChecked] = React3.useState(false);
1637
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(
1638
+ ui.Flex,
1639
+ {
1640
+ direction: "column",
1641
+ gap: 3,
1642
+ itemAlign: "start",
1643
+ className: "oui-permissionlessNotice-content",
1644
+ children: [
1645
+ /* @__PURE__ */ jsxRuntime.jsx(
1646
+ ui.Text,
1647
+ {
1648
+ className: ui.textVariants({
1649
+ size: "sm",
1650
+ intensity: 54
1651
+ }),
1652
+ children: t("orderEntry.permissionlessNotice.content1")
1653
+ }
1654
+ ),
1655
+ /* @__PURE__ */ jsxRuntime.jsx(
1656
+ ui.Text,
1657
+ {
1658
+ className: ui.textVariants({
1659
+ size: "sm",
1660
+ intensity: 54
1661
+ }),
1662
+ children: t("orderEntry.permissionlessNotice.content2")
1663
+ }
1664
+ ),
1665
+ /* @__PURE__ */ jsxRuntime.jsx(
1666
+ ui.Text,
1667
+ {
1668
+ className: ui.textVariants({
1669
+ size: "sm",
1670
+ intensity: 54
1671
+ }),
1672
+ children: t("orderEntry.permissionlessNotice.content3")
1673
+ }
1674
+ )
1675
+ ]
1676
+ }
1677
+ );
1678
+ const checkboxSection = /* @__PURE__ */ jsxRuntime.jsxs(
1679
+ ui.Flex,
1680
+ {
1681
+ gapX: 1,
1682
+ pt: 4,
1683
+ pb: 5,
1684
+ itemAlign: "start",
1685
+ className: "oui-permissionlessNotice-checkbox oui-orderEntry-orderConfirmDialog-disableConfirm oui-cursor-pointer",
1686
+ children: [
1687
+ /* @__PURE__ */ jsxRuntime.jsx(
1688
+ ui.Checkbox,
1689
+ {
1690
+ id: "permissionlessNotice",
1691
+ color: "white",
1692
+ className: "oui-permissionlessNotice-checkbox-input oui-mt-1",
1693
+ checked,
1694
+ onCheckedChange: (value) => setChecked(!!value)
1695
+ }
1696
+ ),
1697
+ /* @__PURE__ */ jsxRuntime.jsx(
1698
+ "label",
1699
+ {
1700
+ htmlFor: "permissionlessNotice",
1701
+ className: ui.textVariants({
1702
+ size: "xs",
1703
+ intensity: 54,
1704
+ className: "oui-cursor-pointer"
1705
+ }),
1706
+ children: t("orderEntry.permissionlessNotice.checkbox")
1707
+ }
1708
+ )
1709
+ ]
1710
+ }
1711
+ );
1712
+ const confirmButton = /* @__PURE__ */ jsxRuntime.jsx(
1713
+ ui.Flex,
1714
+ {
1715
+ className: "oui-permissionlessNotice-confirm-button oui-w-full",
1716
+ justify: "center",
1717
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1718
+ ui.Button,
1719
+ {
1720
+ fullWidth: true,
1721
+ size: "md",
1722
+ className: "oui-permissionlessNotice-confirm oui-confirm-btn oui-max-w-[244px]",
1723
+ disabled: !checked,
1724
+ onClick: () => onConfirm(),
1725
+ children: t("common.confirm")
1726
+ }
1727
+ )
1728
+ }
1729
+ );
1730
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1731
+ content,
1732
+ checkboxSection,
1733
+ confirmButton
1734
+ ] });
1735
+ };
1736
+ PermissionlessMarketNoticeDialog.displayName = "PermissionlessMarketNoticeDialog";
1737
+ var Dialog2 = (props) => {
1738
+ const { close, resolve, reject } = props;
1739
+ return /* @__PURE__ */ jsxRuntime.jsx(
1740
+ PermissionlessMarketNoticeDialog,
1741
+ {
1742
+ onCancel: () => {
1743
+ reject();
1744
+ close();
1745
+ },
1746
+ onConfirm: () => {
1747
+ resolve();
1748
+ close();
1749
+ }
1750
+ }
1751
+ );
1752
+ };
1753
+ var permissionlessMarketNoticeDialogId = "permissionlessMarketNotice";
1754
+ var permissionlessMarketNoticeDesktopDialogId = "permissionlessMarketNoticeDesktop";
1755
+ ui.registerSimpleDialog(permissionlessMarketNoticeDialogId, Dialog2, {
1756
+ size: "sm",
1757
+ title: () => i18n.i18n.t("orderEntry.permissionlessNotice.title")
1758
+ });
1759
+ ui.registerSimpleDialog(permissionlessMarketNoticeDesktopDialogId, Dialog2, {
1760
+ size: "xl",
1761
+ title: () => i18n.i18n.t("orderEntry.permissionlessNotice.title")
1762
+ });
1622
1763
  var ScaledOrderConfirm = (props) => {
1623
1764
  const { order, symbolInfo, dataSource, national, askAndBid, totalQuantity } = props;
1624
1765
  const { base, quote, base_dp, quote_dp } = symbolInfo;
@@ -1643,7 +1784,7 @@ var ScaledOrderConfirm = (props) => {
1643
1784
  "div",
1644
1785
  {
1645
1786
  className: ui.cn(
1646
- "oui-h-[38px] oui-w-1 oui-shrink-0 oui-rounded-[1px]",
1787
+ "oui-h-[42px] oui-w-1 oui-shrink-0 oui-rounded-[1px]",
1647
1788
  record.side === types.OrderSide.BUY ? "oui-bg-trade-profit" : "oui-bg-trade-loss"
1648
1789
  )
1649
1790
  }
@@ -1651,17 +1792,12 @@ var ScaledOrderConfirm = (props) => {
1651
1792
  /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "column", itemAlign: "start", children: [
1652
1793
  /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gapX: 1, children: [
1653
1794
  /* @__PURE__ */ jsxRuntime.jsx(ui.TokenIcon, { symbol: value, className: "oui-size-3" }),
1654
- /* @__PURE__ */ jsxRuntime.jsx(
1655
- ui.Text.formatted,
1656
- {
1657
- rule: "symbol",
1658
- size: "xs",
1659
- formatString: "base-type",
1660
- children: value
1661
- }
1662
- )
1795
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text.formatted, { rule: "symbol", size: "xs", formatString: "base", children: value })
1663
1796
  ] }),
1664
- /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "neutral", size: "xs", children: t("orderEntry.orderType.limit") })
1797
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gap: 1, children: [
1798
+ /* @__PURE__ */ jsxRuntime.jsx(SymbolBadge, { symbol: value }),
1799
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "neutral", size: "xs", children: t("orderEntry.orderType.limit") })
1800
+ ] })
1665
1801
  ] })
1666
1802
  ] });
1667
1803
  }
@@ -1862,6 +1998,7 @@ ui.registerSimpleDialog(scaledOrderConfirmDialogId, ScaledOrderConfirmWidget, {
1862
1998
  var OrderTypeSelect = (props) => {
1863
1999
  const { t } = i18n.useTranslation();
1864
2000
  const { isMobile } = ui.useScreen();
2001
+ const { marketOrderDisabled = false, marketOrderDisabledTooltip } = props;
1865
2002
  const allOptions = React3.useMemo(() => {
1866
2003
  return [
1867
2004
  { label: t("orderEntry.orderType.limitOrder"), value: types.OrderType.LIMIT },
@@ -1942,7 +2079,24 @@ var OrderTypeSelect = (props) => {
1942
2079
  children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xs", children: t("orderEntry.orderType.limit") })
1943
2080
  }
1944
2081
  ),
1945
- /* @__PURE__ */ jsxRuntime.jsx(
2082
+ marketOrderDisabled && marketOrderDisabledTooltip ? /* @__PURE__ */ jsxRuntime.jsx(
2083
+ ui.Tooltip,
2084
+ {
2085
+ content: marketOrderDisabledTooltip,
2086
+ className: "oui-max-w-[275px]",
2087
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "oui-inline-flex oui-flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
2088
+ "button",
2089
+ {
2090
+ type: "button",
2091
+ className: unselectedButtonClassName,
2092
+ "aria-pressed": false,
2093
+ disabled: true,
2094
+ "data-testid": "oui-testid-orderEntry-orderType-market",
2095
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xs", children: t("orderEntry.orderType.market") })
2096
+ }
2097
+ ) })
2098
+ }
2099
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1946
2100
  "button",
1947
2101
  {
1948
2102
  type: "button",
@@ -1992,14 +2146,25 @@ var OrderTypeSelect = (props) => {
1992
2146
  }
1993
2147
  );
1994
2148
  }
2149
+ const mobileOptions = React3.useMemo(() => allOptions, [allOptions]);
2150
+ const handleMobileValueChange = (value) => {
2151
+ if (marketOrderDisabled && value === types.OrderType.MARKET && marketOrderDisabledTooltip) {
2152
+ ui.modal.alert({
2153
+ title: t("common.tips"),
2154
+ message: marketOrderDisabledTooltip
2155
+ });
2156
+ return;
2157
+ }
2158
+ props.onChange(value);
2159
+ };
1995
2160
  return /* @__PURE__ */ jsxRuntime.jsx(
1996
2161
  ui.Select.options,
1997
2162
  {
1998
2163
  testid: "oui-testid-orderEntry-orderType-button",
1999
2164
  currentValue: props.type,
2000
2165
  value: props.type,
2001
- options: allOptions,
2002
- onValueChange: props.onChange,
2166
+ options: mobileOptions,
2167
+ onValueChange: handleMobileValueChange,
2003
2168
  contentProps: {
2004
2169
  className: ui.cn(
2005
2170
  "oui-orderEntry-orderTypeSelect-content",
@@ -2102,10 +2267,11 @@ var MarginModeSwitch = (props) => {
2102
2267
  {
2103
2268
  className: "oui-tracking-[0.03em]",
2104
2269
  rule: "symbol",
2105
- formatString: "base-type",
2270
+ formatString: "base",
2106
2271
  size: "base",
2107
2272
  weight: "semibold",
2108
2273
  intensity: 98,
2274
+ suffix: /* @__PURE__ */ jsxRuntime.jsx(SymbolBadge, { symbol: props.symbol }),
2109
2275
  children: props.symbol
2110
2276
  }
2111
2277
  )
@@ -2117,7 +2283,8 @@ var MarginModeSwitch = (props) => {
2117
2283
  mode: types.MarginMode.CROSS,
2118
2284
  selected: props.selectedMarginMode === types.MarginMode.CROSS,
2119
2285
  isCurrent: props.currentMarginMode === types.MarginMode.CROSS,
2120
- onClick: () => handleSelect(types.MarginMode.CROSS)
2286
+ onClick: () => handleSelect(types.MarginMode.CROSS),
2287
+ disabled: props.isPermissionlessListing
2121
2288
  }
2122
2289
  ),
2123
2290
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2180,9 +2347,11 @@ var OptionCard = (props) => {
2180
2347
  "oui-relative oui-w-full oui-rounded-md oui-p-2",
2181
2348
  "oui-bg-base-6",
2182
2349
  "oui-text-left",
2183
- props.selected ? "oui-border oui-border-[#38e2fe]" : "oui-border oui-border-transparent hover:oui-border-line-12"
2350
+ props.disabled ? "oui-cursor-not-allowed oui-opacity-50 oui-border oui-border-transparent" : props.selected ? "oui-border oui-border-[#38e2fe]" : "oui-border oui-border-transparent hover:oui-border-line-12"
2184
2351
  ),
2185
- onClick: props.onClick,
2352
+ onClick: props.disabled ? void 0 : props.onClick,
2353
+ disabled: props.disabled,
2354
+ "aria-disabled": props.disabled,
2186
2355
  "data-testid": `oui-testid-marginModeSwitch-option-${props.mode}`,
2187
2356
  children: [
2188
2357
  /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "column", gap: 2, itemAlign: "start", className: "oui-w-full", children: [
@@ -2215,7 +2384,11 @@ var useMarginModeSwitchScript = (options2) => {
2215
2384
  const { symbol, close } = options2;
2216
2385
  const { isMobile } = ui.useScreen();
2217
2386
  const { t } = i18n.useTranslation();
2218
- const { marginMode: currentMarginMode, update } = hooks.useMarginModeBySymbol(symbol);
2387
+ const {
2388
+ marginMode: currentMarginMode,
2389
+ update,
2390
+ isPermissionlessListing
2391
+ } = hooks.useMarginModeBySymbol(symbol);
2219
2392
  const [selectedMarginMode, setSelectedMarginMode] = React3.useState(currentMarginMode);
2220
2393
  React3.useEffect(() => {
2221
2394
  setSelectedMarginMode(currentMarginMode);
@@ -2253,11 +2426,13 @@ var useMarginModeSwitchScript = (options2) => {
2253
2426
  setSelectedMarginMode,
2254
2427
  applyMarginMode,
2255
2428
  close,
2256
- onSelect
2429
+ onSelect,
2430
+ isPermissionlessListing
2257
2431
  };
2258
2432
  };
2259
2433
  var useMarginModeSettingsScript = (options2) => {
2260
2434
  const { isMobile } = ui.useScreen();
2435
+ const { t } = i18n.useTranslation();
2261
2436
  const [markets] = hooks.useMarkets(hooks.MarketsType.ALL);
2262
2437
  const items = React3.useMemo(() => {
2263
2438
  if (!markets || markets.length === 0) {
@@ -2266,10 +2441,20 @@ var useMarginModeSettingsScript = (options2) => {
2266
2441
  return markets.map((market) => ({
2267
2442
  key: market.symbol,
2268
2443
  // Original symbol: "PERP_BTC_USDC"
2269
- symbol: utils.formatSymbol(market.symbol, "base-type")
2444
+ symbol: utils.formatSymbol(market.symbol, "base"),
2270
2445
  // Formatted: "BTC-PERP"
2446
+ brokerId: market.broker_id
2271
2447
  }));
2272
2448
  }, [markets]);
2449
+ const brokerLockedKeys = React3.useMemo(() => {
2450
+ const locked = /* @__PURE__ */ new Set();
2451
+ for (const item of items) {
2452
+ if (item.brokerId) {
2453
+ locked.add(item.key);
2454
+ }
2455
+ }
2456
+ return locked;
2457
+ }, [items]);
2273
2458
  const [searchKeyword, setSearchKeyword] = React3.useState("");
2274
2459
  const [selectedKeys, setSelectedKeys] = React3.useState(
2275
2460
  () => /* @__PURE__ */ new Set()
@@ -2290,11 +2475,15 @@ var useMarginModeSettingsScript = (options2) => {
2290
2475
  const itemMarginModes = React3.useMemo(() => {
2291
2476
  const result = {};
2292
2477
  for (const item of items) {
2478
+ if (brokerLockedKeys.has(item.key)) {
2479
+ result[item.key] = types.MarginMode.ISOLATED;
2480
+ continue;
2481
+ }
2293
2482
  const marginMode = marginModes[item.key];
2294
2483
  result[item.key] = marginMode ?? types.MarginMode.CROSS;
2295
2484
  }
2296
2485
  return result;
2297
- }, [items, marginModes]);
2486
+ }, [brokerLockedKeys, items, marginModes]);
2298
2487
  const filteredItems = React3.useMemo(() => {
2299
2488
  const keyword = searchKeyword.trim().toLowerCase();
2300
2489
  if (!keyword) return items;
@@ -2330,17 +2519,21 @@ var useMarginModeSettingsScript = (options2) => {
2330
2519
  const onSearchChange = React3.useCallback((keyword) => {
2331
2520
  setSearchKeyword(keyword);
2332
2521
  }, []);
2333
- const onToggleItem = React3.useCallback((key) => {
2334
- setSelectedKeys((prev) => {
2335
- const next = new Set(prev);
2336
- if (next.has(key)) {
2337
- next.delete(key);
2338
- } else {
2339
- next.add(key);
2340
- }
2341
- return next;
2342
- });
2343
- }, []);
2522
+ const onToggleItem = React3.useCallback(
2523
+ (key) => {
2524
+ if (brokerLockedKeys.has(key)) return;
2525
+ setSelectedKeys((prev) => {
2526
+ const next = new Set(prev);
2527
+ if (next.has(key)) {
2528
+ next.delete(key);
2529
+ } else {
2530
+ next.add(key);
2531
+ }
2532
+ return next;
2533
+ });
2534
+ },
2535
+ [brokerLockedKeys]
2536
+ );
2344
2537
  const onToggleSelectAll = React3.useCallback(() => {
2345
2538
  setSelectedKeys((prev) => {
2346
2539
  const next = new Set(prev);
@@ -2351,31 +2544,39 @@ var useMarginModeSettingsScript = (options2) => {
2351
2544
  return next;
2352
2545
  }
2353
2546
  for (const item of filteredItems) {
2547
+ if (brokerLockedKeys.has(item.key)) continue;
2354
2548
  next.add(item.key);
2355
2549
  }
2356
2550
  return next;
2357
2551
  });
2358
- }, [filteredItems, isSelectAll]);
2552
+ }, [brokerLockedKeys, filteredItems, isSelectAll]);
2359
2553
  const onSetMarginMode = React3.useCallback(
2360
2554
  async (mode) => {
2361
2555
  if (selectedKeys.size === 0) return;
2556
+ const editableSymbolList = Array.from(selectedKeys).filter(
2557
+ (key) => !brokerLockedKeys.has(key)
2558
+ );
2559
+ if (editableSymbolList.length === 0) {
2560
+ ui.toast.error(t("marginMode.noEditableSymbolsSelected"));
2561
+ return;
2562
+ }
2362
2563
  setIsOperationLoading(true);
2363
2564
  try {
2364
2565
  const payload = {
2365
- symbol_list: Array.from(selectedKeys),
2566
+ symbol_list: editableSymbolList,
2366
2567
  default_margin_mode: mode
2367
2568
  };
2368
2569
  await updateMarginMode(payload);
2369
- ui.toast.success("Updated successfully");
2570
+ ui.toast.success(t("marginMode.updatedSuccessfully"));
2370
2571
  } catch (error) {
2371
2572
  ui.toast.error(
2372
- error instanceof Error ? error.message : "Failed to update margin mode"
2573
+ error instanceof Error ? error.message : t("marginMode.failedToUpdateMarginMode")
2373
2574
  );
2374
2575
  } finally {
2375
2576
  setIsOperationLoading(false);
2376
2577
  }
2377
2578
  },
2378
- [selectedKeys, updateMarginMode]
2579
+ [brokerLockedKeys, selectedKeys, updateMarginMode]
2379
2580
  );
2380
2581
  const isLoading = isDataLoading || isMarginModesLoading || isOperationLoading || isSettingMarginMode;
2381
2582
  return {
@@ -2523,7 +2724,8 @@ var MarginModeSettings = (props) => {
2523
2724
  item,
2524
2725
  checked: props.selectedKeys.has(item.key),
2525
2726
  marginMode: props.itemMarginModes[item.key] ?? types.MarginMode.CROSS,
2526
- onToggle: props.onToggleItem
2727
+ onToggle: props.onToggleItem,
2728
+ disabled: !!item.brokerId
2527
2729
  },
2528
2730
  item.key
2529
2731
  ))
@@ -2626,13 +2828,15 @@ var MarginModeSettings = (props) => {
2626
2828
  var SymbolRow = (props) => {
2627
2829
  const { t } = i18n.useTranslation();
2628
2830
  const handleCheckedChange = React3.useCallback(() => {
2831
+ if (props.disabled) return;
2629
2832
  props.onToggle(props.item.key);
2630
2833
  }, [props]);
2631
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { itemAlign: "center", className: "oui-w-full", children: /* @__PURE__ */ jsxRuntime.jsxs(
2834
+ const row = /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { itemAlign: "center", className: "oui-w-full", children: /* @__PURE__ */ jsxRuntime.jsxs(
2632
2835
  "label",
2633
2836
  {
2634
2837
  className: ui.cn(
2635
- "oui-flex oui-items-center oui-gap-2 oui-flex-1 oui-cursor-pointer oui-select-none oui-w-full"
2838
+ "oui-flex oui-items-center oui-gap-2 oui-flex-1 oui-cursor-pointer oui-select-none oui-w-full",
2839
+ props.disabled ? "oui-cursor-not-allowed oui-opacity-50" : ""
2636
2840
  ),
2637
2841
  "data-testid": `oui-testid-marginModeSettings-item-${props.item.key}`,
2638
2842
  children: [
@@ -2642,10 +2846,12 @@ var SymbolRow = (props) => {
2642
2846
  color: "white",
2643
2847
  checked: props.checked,
2644
2848
  onCheckedChange: handleCheckedChange,
2645
- "aria-label": props.item.symbol
2849
+ "aria-label": props.item.symbol,
2850
+ disabled: props.disabled
2646
2851
  }
2647
2852
  ),
2648
2853
  /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "oui-text-sm oui-font-semibold oui-text-base-contrast-80", children: props.item.symbol }),
2854
+ /* @__PURE__ */ jsxRuntime.jsx(SymbolBadge, { symbol: props.item.key }),
2649
2855
  /* @__PURE__ */ jsxRuntime.jsx(
2650
2856
  "span",
2651
2857
  {
@@ -2661,6 +2867,17 @@ var SymbolRow = (props) => {
2661
2867
  ]
2662
2868
  }
2663
2869
  ) });
2870
+ if (props.disabled) {
2871
+ return /* @__PURE__ */ jsxRuntime.jsx(
2872
+ ui.Tooltip,
2873
+ {
2874
+ content: t("marginMode.disabledSymbolTooltip"),
2875
+ className: "oui-max-w-[280px] oui-text-2xs oui-text-base-contrast-80",
2876
+ children: row
2877
+ }
2878
+ );
2879
+ }
2880
+ return row;
2664
2881
  };
2665
2882
  var SearchGlyph = (props) => {
2666
2883
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -2852,7 +3069,9 @@ function OrderEntryHeader(props) {
2852
3069
  canTrade,
2853
3070
  onChange: (type) => {
2854
3071
  setOrderValue("order_type", type);
2855
- }
3072
+ },
3073
+ marketOrderDisabled: props.marketOrderDisabled,
3074
+ marketOrderDisabledTooltip: props.marketOrderDisabledTooltip
2856
3075
  }
2857
3076
  ) }),
2858
3077
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -4623,12 +4842,15 @@ var usePNLInputBuilder = (props) => {
4623
4842
  }
4624
4843
  if (value === "" || value === "-") return "";
4625
4844
  if (mode === "Offset%" /* PERCENTAGE */) {
4626
- return `${new utils.Decimal(
4627
- value.replace(
4628
- new RegExp(percentageSuffix.current.replace(".", "\\.") + "$"),
4629
- ""
4630
- )
4631
- ).mul(100).todp(2, 4).toString()}${percentageSuffix.current}`;
4845
+ let normalized = value.replace(
4846
+ new RegExp(percentageSuffix.current.replace(".", "\\.") + "$"),
4847
+ ""
4848
+ ).replace(/,/g, "");
4849
+ normalized = normalized.replace(/\.$/, "");
4850
+ if (isNaN(Number(normalized)) || normalized === "" || normalized === "-") {
4851
+ return value;
4852
+ }
4853
+ return `${new utils.Decimal(normalized).mul(100).todp(2, 4).toString()}${percentageSuffix.current}`;
4632
4854
  } else if (mode === "Offset" /* OFFSET */) {
4633
4855
  value = utils.todpIfNeed(value, dp);
4634
4856
  } else ;
@@ -4647,6 +4869,9 @@ var usePNLInputBuilder = (props) => {
4647
4869
  } else {
4648
4870
  percentageSuffix.current = "";
4649
4871
  }
4872
+ if (isNaN(Number(value))) {
4873
+ return value;
4874
+ }
4650
4875
  value = new utils.Decimal(value).div(100).toString();
4651
4876
  value = `${value}${percentageSuffix.current}`;
4652
4877
  }
@@ -5182,6 +5407,7 @@ var OrderEntry = (props) => {
5182
5407
  setOrderValue,
5183
5408
  manualSetOrderValue,
5184
5409
  setOrderValues,
5410
+ setOrderValuesRaw,
5185
5411
  symbolInfo,
5186
5412
  maxQty,
5187
5413
  freeCollateral,
@@ -5197,9 +5423,13 @@ var OrderEntry = (props) => {
5197
5423
  fillMiddleValue,
5198
5424
  soundAlert,
5199
5425
  setSoundAlert,
5200
- currentFocusInput
5426
+ currentFocusInput,
5427
+ walletAddress,
5428
+ isPermissionlessListing,
5429
+ symbol
5201
5430
  } = props;
5202
5431
  const [maxQtyConfirmOpen, setMaxQtyConfirmOpen] = React3.useState(false);
5432
+ const [permissionlessAcknowledgedKeys, setPermissionlessAcknowledgedKeys] = hooks.useLocalStorage("orderly-permissionless-market-notice", []);
5203
5433
  const { t } = i18n.useTranslation();
5204
5434
  const { isMobile } = ui.useScreen();
5205
5435
  const [hasAdvancedTPSLResult, setHasAdvancedTPSLResult] = React3.useState(false);
@@ -5269,22 +5499,7 @@ var OrderEntry = (props) => {
5269
5499
  helper.validate(isSlPriceError ? props.slPriceError : void 0).then(
5270
5500
  // validate success, it return the order
5271
5501
  // TODO: get order from other function
5272
- (order) => {
5273
- if (isScaledOrder) {
5274
- return ui.modal.show(scaledOrderConfirmDialogId, {
5275
- order,
5276
- symbolInfo,
5277
- size: isMobile ? "sm" : "md"
5278
- });
5279
- }
5280
- if (needConfirm) {
5281
- return ui.modal.show(orderConfirmDialogId, {
5282
- order: formattedOrder,
5283
- symbolInfo
5284
- });
5285
- }
5286
- return true;
5287
- },
5502
+ (order) => order,
5288
5503
  // should catch validate error first, then submit
5289
5504
  (errors2) => {
5290
5505
  if (errors2.slippage) {
@@ -5293,7 +5508,38 @@ var OrderEntry = (props) => {
5293
5508
  setErrorMsgVisible(true);
5294
5509
  return Promise.reject();
5295
5510
  }
5296
- ).then(() => {
5511
+ ).then((order) => {
5512
+ const shouldShowPermissionlessNotice = isPermissionlessListing && walletAddress && !(permissionlessAcknowledgedKeys ?? []).includes(
5513
+ `${walletAddress}_${symbol}`
5514
+ );
5515
+ if (shouldShowPermissionlessNotice) {
5516
+ return ui.modal.show(
5517
+ isMobile ? permissionlessMarketNoticeDialogId : permissionlessMarketNoticeDesktopDialogId
5518
+ ).then(() => {
5519
+ setPermissionlessAcknowledgedKeys([
5520
+ ...Array.isArray(permissionlessAcknowledgedKeys) ? permissionlessAcknowledgedKeys : [],
5521
+ `${walletAddress}_${symbol}`
5522
+ ]);
5523
+ return order;
5524
+ });
5525
+ }
5526
+ return Promise.resolve(order);
5527
+ }).then((order) => {
5528
+ if (isScaledOrder) {
5529
+ return ui.modal.show(scaledOrderConfirmDialogId, {
5530
+ order,
5531
+ symbolInfo,
5532
+ size: isMobile ? "sm" : "md"
5533
+ });
5534
+ }
5535
+ if (needConfirm) {
5536
+ return ui.modal.show(orderConfirmDialogId, {
5537
+ order: formattedOrder,
5538
+ symbolInfo
5539
+ });
5540
+ }
5541
+ return true;
5542
+ }).then(() => {
5297
5543
  return submit({ resetOnSuccess: false }).then((result) => {
5298
5544
  if (!result.success && result.message) {
5299
5545
  ui.toast.error(result.message);
@@ -5361,7 +5607,7 @@ var OrderEntry = (props) => {
5361
5607
  if (order.side !== formattedOrder.side) {
5362
5608
  manualSetOrderValue("side", order.side);
5363
5609
  }
5364
- setOrderValues({
5610
+ setOrderValuesRaw({
5365
5611
  position_type: order.position_type,
5366
5612
  tp_order_type: order.tp_order_type,
5367
5613
  tp_pnl: order.tp_pnl,
@@ -5460,7 +5706,11 @@ var OrderEntry = (props) => {
5460
5706
  order_type: formattedOrder.order_type,
5461
5707
  setOrderValue: manualSetOrderValue,
5462
5708
  symbolLeverage: props.symbolLeverage,
5463
- marginMode: props.marginMode
5709
+ marginMode: props.marginMode,
5710
+ marketOrderDisabled: props.isSymbolPostOnly,
5711
+ marketOrderDisabledTooltip: t(
5712
+ "orderEntry.orderType.symbolPostOnly.tooltip"
5713
+ )
5464
5714
  }
5465
5715
  ),
5466
5716
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5858,11 +6108,14 @@ var useOrderEntryScript = (inputs) => {
5858
6108
  defaultSoundValue ?? null
5859
6109
  );
5860
6110
  const canTrade = reactApp.useCanTrade();
5861
- const { marginMode } = hooks.useMarginModeBySymbol(symbol);
6111
+ const { state: accountState } = hooks.useAccount();
6112
+ const { marginMode, isPermissionlessListing } = hooks.useMarginModeBySymbol(symbol);
6113
+ const walletAddress = accountState?.address;
5862
6114
  const {
5863
6115
  formattedOrder,
5864
6116
  setValue,
5865
6117
  setValues: setOrderValues,
6118
+ setValuesRaw: setOrderValuesRaw,
5866
6119
  symbolInfo,
5867
6120
  symbolLeverage,
5868
6121
  ...state
@@ -6058,6 +6311,16 @@ var useOrderEntryScript = (inputs) => {
6058
6311
  setValue("distribution_type", types.DistributionType.FLAT);
6059
6312
  }
6060
6313
  }, [formattedOrder.order_type, formattedOrder.distribution_type]);
6314
+ const isSymbolPostOnly = symbolInfo?.status === "POST_ONLY";
6315
+ React3.useEffect(() => {
6316
+ if (isSymbolPostOnly && (formattedOrder.order_type === types.OrderType.MARKET || formattedOrder.order_type === types.OrderType.STOP_MARKET)) {
6317
+ setLocalOrderType(types.OrderType.LIMIT);
6318
+ setOrderValues({
6319
+ order_type: types.OrderType.LIMIT,
6320
+ order_type_ext: void 0
6321
+ });
6322
+ }
6323
+ }, [isSymbolPostOnly, formattedOrder.order_type, setOrderValues]);
6061
6324
  const currentLtv = hooks.useComputedLTV();
6062
6325
  const askAndBid = useAskAndBid();
6063
6326
  const fillMiddleValue = () => {
@@ -6121,6 +6384,7 @@ var useOrderEntryScript = (inputs) => {
6121
6384
  setOrderValue,
6122
6385
  manualSetOrderValue,
6123
6386
  setOrderValues,
6387
+ setOrderValuesRaw,
6124
6388
  // account-level leverage (for other consumers)
6125
6389
  currentLeverage,
6126
6390
  // symbol-level leverage & margin mode for this order entry
@@ -6149,7 +6413,10 @@ var useOrderEntryScript = (inputs) => {
6149
6413
  symbol,
6150
6414
  soundAlert,
6151
6415
  setSoundAlert,
6152
- currentFocusInput
6416
+ currentFocusInput,
6417
+ walletAddress,
6418
+ isPermissionlessListing,
6419
+ isSymbolPostOnly
6153
6420
  };
6154
6421
  };
6155
6422
  var OrderEntryWidget = (props) => {
@@ -6170,6 +6437,7 @@ exports.LTVRiskTooltipWidget = LTVRiskTooltipWidget;
6170
6437
  exports.OrderConfirmDialog = OrderConfirmDialog;
6171
6438
  exports.OrderEntry = OrderEntry;
6172
6439
  exports.OrderEntryWidget = OrderEntryWidget;
6440
+ exports.SymbolBadge = SymbolBadge;
6173
6441
  exports.useOrderEntryScript = useOrderEntryScript;
6174
6442
  //# sourceMappingURL=index.js.map
6175
6443
  //# sourceMappingURL=index.js.map