@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.d.mts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +348 -80
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +350 -83
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +13 -13
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.
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
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-[
|
|
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.
|
|
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:
|
|
2002
|
-
onValueChange:
|
|
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
|
|
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 {
|
|
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
|
|
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(
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
next
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
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:
|
|
2566
|
+
symbol_list: editableSymbolList,
|
|
2366
2567
|
default_margin_mode: mode
|
|
2367
2568
|
};
|
|
2368
2569
|
await updateMarginMode(payload);
|
|
2369
|
-
ui.toast.success("
|
|
2570
|
+
ui.toast.success(t("marginMode.updatedSuccessfully"));
|
|
2370
2571
|
} catch (error) {
|
|
2371
2572
|
ui.toast.error(
|
|
2372
|
-
error instanceof Error ? error.message : "
|
|
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
|
-
|
|
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
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|