@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.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React3, { forwardRef, useState, useImperativeHandle, useEffect, memo, createContext, useMemo, useRef, useCallback, useContext, useId } from 'react';
|
|
2
|
-
import { useLocalStorage, utils, usePositionStream, useMarkets, MarketsType, useMarginModes, useMarginModeBySymbol, useEventEmitter, useDebouncedCallback, useFeeState, useRwaSymbolsInfoStore, useOrderlyContext, useMemoizedFn, ERROR_MSG_CODES, useOrderEntry, useMarginRatio, useComputedLTV, useTpslPriceChecker, useHoldingStream, useAppStore, useIndexPricesStream, useGetEstLiqPrice, useTrack, useQuery, useFeatureFlag, FlagKeys, useBoolean } from '@orderly.network/hooks';
|
|
2
|
+
import { useLocalStorage, utils, usePositionStream, useMarkets, MarketsType, useMarginModes, useMarginModeBySymbol, useBadgeBySymbol, useEventEmitter, useDebouncedCallback, useFeeState, useRwaSymbolsInfoStore, useOrderlyContext, useMemoizedFn, ERROR_MSG_CODES, useAccount, useOrderEntry, useMarginRatio, useComputedLTV, useTpslPriceChecker, useHoldingStream, useAppStore, useIndexPricesStream, useGetEstLiqPrice, useTrack, useQuery, useFeatureFlag, FlagKeys, useBoolean } from '@orderly.network/hooks';
|
|
3
3
|
import { useTranslation, i18n } from '@orderly.network/i18n';
|
|
4
4
|
import { useOrderEntryFormErrorMsg, useCanTrade } from '@orderly.network/react-app';
|
|
5
5
|
import { EMPTY_LIST, DistributionType, TrailingCallbackType, OrderSide, OrderType, MarginMode, PositionType, BBOOrderType, ORDER_ENTRY_EST_LIQ_PRICE_CHANGE, OrderLevel, TrackerEventName } from '@orderly.network/types';
|
|
6
|
-
import { ExclamationFillIcon, modal, Text, Tooltip, TooltipTrigger, Flex, Input, cn, inputFormatter, Box, registerSimpleDialog, SimpleDialog, registerSimpleSheet, Select, Grid, Checkbox, Slider, textVariants, SettingFillIcon, useModal, Badge, Divider, Button, TokenIcon, DataTable, useScreen, toast, IconButton, CloseIcon, CloseCircleFillIcon, ChevronRightIcon, SimpleDropdownMenu, CaretDownIcon, Switch, ThrottledButton, SimpleSheet, InfoCircleIcon, AddCircleIcon, PopoverRoot, PopoverTrigger, PopoverContent, DotStatus, EditIcon as EditIcon$1 } from '@orderly.network/ui';
|
|
6
|
+
import { ExclamationFillIcon, modal, Text, Tooltip, TooltipTrigger, Flex, Input, cn, inputFormatter, Box, registerSimpleDialog, SimpleDialog, registerSimpleSheet, Select, Grid, Checkbox, Slider, textVariants, SettingFillIcon, useModal, Badge, Divider, Button, TokenIcon, DataTable, useScreen, toast, IconButton, CloseIcon, CloseCircleFillIcon, ChevronRightIcon, SymbolBadge as SymbolBadge$1, SimpleDropdownMenu, CaretDownIcon, Switch, ThrottledButton, SimpleSheet, InfoCircleIcon, AddCircleIcon, PopoverRoot, PopoverTrigger, PopoverContent, DotStatus, EditIcon as EditIcon$1 } from '@orderly.network/ui';
|
|
7
7
|
import { TPSLPositionTypeWidget, TPSLAdvancedWidget } from '@orderly.network/ui-tpsl';
|
|
8
8
|
import { Decimal, zero, formatSymbol, todpIfNeed, getBBOType, removeTrailingZeros } from '@orderly.network/utils';
|
|
9
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -1149,6 +1149,13 @@ function getScaledPlaceOrderMessage(result) {
|
|
|
1149
1149
|
var safeNumber = (val) => {
|
|
1150
1150
|
return Number.isNaN(Number(val)) ? 0 : Number(val);
|
|
1151
1151
|
};
|
|
1152
|
+
var SymbolBadge = (props) => {
|
|
1153
|
+
const { brokerId, brokerName, brokerNameRaw } = useBadgeBySymbol(
|
|
1154
|
+
props.symbol
|
|
1155
|
+
);
|
|
1156
|
+
const badge = brokerName ?? brokerId ?? void 0;
|
|
1157
|
+
return /* @__PURE__ */ jsx(SymbolBadge$1, { badge, fullName: brokerNameRaw });
|
|
1158
|
+
};
|
|
1152
1159
|
var OrderConfirmDialog = (props) => {
|
|
1153
1160
|
const { symbolInfo, order, onConfirm, onCancel } = props;
|
|
1154
1161
|
const { quote, quote_dp, base_dp } = symbolInfo;
|
|
@@ -1306,15 +1313,19 @@ var OrderConfirmDialog = (props) => {
|
|
|
1306
1313
|
justify: "between",
|
|
1307
1314
|
className: "oui-orderEntry-orderConfirmDialog-header",
|
|
1308
1315
|
children: [
|
|
1309
|
-
/* @__PURE__ */
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1316
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, direction: "column", itemAlign: "start", children: [
|
|
1317
|
+
/* @__PURE__ */ jsx(
|
|
1318
|
+
Text.formatted,
|
|
1319
|
+
{
|
|
1320
|
+
rule: "symbol",
|
|
1321
|
+
formatString: "base",
|
|
1322
|
+
showIcon: true,
|
|
1323
|
+
className: "oui-orderConfirmDialog-symbol",
|
|
1324
|
+
children: order.symbol
|
|
1325
|
+
}
|
|
1326
|
+
),
|
|
1327
|
+
/* @__PURE__ */ jsx(SymbolBadge, { symbol: order.symbol })
|
|
1328
|
+
] }),
|
|
1318
1329
|
/* @__PURE__ */ jsxs(
|
|
1319
1330
|
Flex,
|
|
1320
1331
|
{
|
|
@@ -1613,6 +1624,136 @@ var MaxQtyConfirm = memo((props) => {
|
|
|
1613
1624
|
}
|
|
1614
1625
|
);
|
|
1615
1626
|
});
|
|
1627
|
+
var PermissionlessMarketNoticeDialog = (props) => {
|
|
1628
|
+
const { onConfirm, onCancel } = props;
|
|
1629
|
+
const { t } = useTranslation();
|
|
1630
|
+
const [checked, setChecked] = useState(false);
|
|
1631
|
+
const content = /* @__PURE__ */ jsxs(
|
|
1632
|
+
Flex,
|
|
1633
|
+
{
|
|
1634
|
+
direction: "column",
|
|
1635
|
+
gap: 3,
|
|
1636
|
+
itemAlign: "start",
|
|
1637
|
+
className: "oui-permissionlessNotice-content",
|
|
1638
|
+
children: [
|
|
1639
|
+
/* @__PURE__ */ jsx(
|
|
1640
|
+
Text,
|
|
1641
|
+
{
|
|
1642
|
+
className: textVariants({
|
|
1643
|
+
size: "sm",
|
|
1644
|
+
intensity: 54
|
|
1645
|
+
}),
|
|
1646
|
+
children: t("orderEntry.permissionlessNotice.content1")
|
|
1647
|
+
}
|
|
1648
|
+
),
|
|
1649
|
+
/* @__PURE__ */ jsx(
|
|
1650
|
+
Text,
|
|
1651
|
+
{
|
|
1652
|
+
className: textVariants({
|
|
1653
|
+
size: "sm",
|
|
1654
|
+
intensity: 54
|
|
1655
|
+
}),
|
|
1656
|
+
children: t("orderEntry.permissionlessNotice.content2")
|
|
1657
|
+
}
|
|
1658
|
+
),
|
|
1659
|
+
/* @__PURE__ */ jsx(
|
|
1660
|
+
Text,
|
|
1661
|
+
{
|
|
1662
|
+
className: textVariants({
|
|
1663
|
+
size: "sm",
|
|
1664
|
+
intensity: 54
|
|
1665
|
+
}),
|
|
1666
|
+
children: t("orderEntry.permissionlessNotice.content3")
|
|
1667
|
+
}
|
|
1668
|
+
)
|
|
1669
|
+
]
|
|
1670
|
+
}
|
|
1671
|
+
);
|
|
1672
|
+
const checkboxSection = /* @__PURE__ */ jsxs(
|
|
1673
|
+
Flex,
|
|
1674
|
+
{
|
|
1675
|
+
gapX: 1,
|
|
1676
|
+
pt: 4,
|
|
1677
|
+
pb: 5,
|
|
1678
|
+
itemAlign: "start",
|
|
1679
|
+
className: "oui-permissionlessNotice-checkbox oui-orderEntry-orderConfirmDialog-disableConfirm oui-cursor-pointer",
|
|
1680
|
+
children: [
|
|
1681
|
+
/* @__PURE__ */ jsx(
|
|
1682
|
+
Checkbox,
|
|
1683
|
+
{
|
|
1684
|
+
id: "permissionlessNotice",
|
|
1685
|
+
color: "white",
|
|
1686
|
+
className: "oui-permissionlessNotice-checkbox-input oui-mt-1",
|
|
1687
|
+
checked,
|
|
1688
|
+
onCheckedChange: (value) => setChecked(!!value)
|
|
1689
|
+
}
|
|
1690
|
+
),
|
|
1691
|
+
/* @__PURE__ */ jsx(
|
|
1692
|
+
"label",
|
|
1693
|
+
{
|
|
1694
|
+
htmlFor: "permissionlessNotice",
|
|
1695
|
+
className: textVariants({
|
|
1696
|
+
size: "xs",
|
|
1697
|
+
intensity: 54,
|
|
1698
|
+
className: "oui-cursor-pointer"
|
|
1699
|
+
}),
|
|
1700
|
+
children: t("orderEntry.permissionlessNotice.checkbox")
|
|
1701
|
+
}
|
|
1702
|
+
)
|
|
1703
|
+
]
|
|
1704
|
+
}
|
|
1705
|
+
);
|
|
1706
|
+
const confirmButton = /* @__PURE__ */ jsx(
|
|
1707
|
+
Flex,
|
|
1708
|
+
{
|
|
1709
|
+
className: "oui-permissionlessNotice-confirm-button oui-w-full",
|
|
1710
|
+
justify: "center",
|
|
1711
|
+
children: /* @__PURE__ */ jsx(
|
|
1712
|
+
Button,
|
|
1713
|
+
{
|
|
1714
|
+
fullWidth: true,
|
|
1715
|
+
size: "md",
|
|
1716
|
+
className: "oui-permissionlessNotice-confirm oui-confirm-btn oui-max-w-[244px]",
|
|
1717
|
+
disabled: !checked,
|
|
1718
|
+
onClick: () => onConfirm(),
|
|
1719
|
+
children: t("common.confirm")
|
|
1720
|
+
}
|
|
1721
|
+
)
|
|
1722
|
+
}
|
|
1723
|
+
);
|
|
1724
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1725
|
+
content,
|
|
1726
|
+
checkboxSection,
|
|
1727
|
+
confirmButton
|
|
1728
|
+
] });
|
|
1729
|
+
};
|
|
1730
|
+
PermissionlessMarketNoticeDialog.displayName = "PermissionlessMarketNoticeDialog";
|
|
1731
|
+
var Dialog2 = (props) => {
|
|
1732
|
+
const { close, resolve, reject } = props;
|
|
1733
|
+
return /* @__PURE__ */ jsx(
|
|
1734
|
+
PermissionlessMarketNoticeDialog,
|
|
1735
|
+
{
|
|
1736
|
+
onCancel: () => {
|
|
1737
|
+
reject();
|
|
1738
|
+
close();
|
|
1739
|
+
},
|
|
1740
|
+
onConfirm: () => {
|
|
1741
|
+
resolve();
|
|
1742
|
+
close();
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
);
|
|
1746
|
+
};
|
|
1747
|
+
var permissionlessMarketNoticeDialogId = "permissionlessMarketNotice";
|
|
1748
|
+
var permissionlessMarketNoticeDesktopDialogId = "permissionlessMarketNoticeDesktop";
|
|
1749
|
+
registerSimpleDialog(permissionlessMarketNoticeDialogId, Dialog2, {
|
|
1750
|
+
size: "sm",
|
|
1751
|
+
title: () => i18n.t("orderEntry.permissionlessNotice.title")
|
|
1752
|
+
});
|
|
1753
|
+
registerSimpleDialog(permissionlessMarketNoticeDesktopDialogId, Dialog2, {
|
|
1754
|
+
size: "xl",
|
|
1755
|
+
title: () => i18n.t("orderEntry.permissionlessNotice.title")
|
|
1756
|
+
});
|
|
1616
1757
|
var ScaledOrderConfirm = (props) => {
|
|
1617
1758
|
const { order, symbolInfo, dataSource, national, askAndBid, totalQuantity } = props;
|
|
1618
1759
|
const { base, quote, base_dp, quote_dp } = symbolInfo;
|
|
@@ -1637,7 +1778,7 @@ var ScaledOrderConfirm = (props) => {
|
|
|
1637
1778
|
"div",
|
|
1638
1779
|
{
|
|
1639
1780
|
className: cn(
|
|
1640
|
-
"oui-h-[
|
|
1781
|
+
"oui-h-[42px] oui-w-1 oui-shrink-0 oui-rounded-[1px]",
|
|
1641
1782
|
record.side === OrderSide.BUY ? "oui-bg-trade-profit" : "oui-bg-trade-loss"
|
|
1642
1783
|
)
|
|
1643
1784
|
}
|
|
@@ -1645,17 +1786,12 @@ var ScaledOrderConfirm = (props) => {
|
|
|
1645
1786
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", itemAlign: "start", children: [
|
|
1646
1787
|
/* @__PURE__ */ jsxs(Flex, { gapX: 1, children: [
|
|
1647
1788
|
/* @__PURE__ */ jsx(TokenIcon, { symbol: value, className: "oui-size-3" }),
|
|
1648
|
-
/* @__PURE__ */ jsx(
|
|
1649
|
-
Text.formatted,
|
|
1650
|
-
{
|
|
1651
|
-
rule: "symbol",
|
|
1652
|
-
size: "xs",
|
|
1653
|
-
formatString: "base-type",
|
|
1654
|
-
children: value
|
|
1655
|
-
}
|
|
1656
|
-
)
|
|
1789
|
+
/* @__PURE__ */ jsx(Text.formatted, { rule: "symbol", size: "xs", formatString: "base", children: value })
|
|
1657
1790
|
] }),
|
|
1658
|
-
/* @__PURE__ */
|
|
1791
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
|
|
1792
|
+
/* @__PURE__ */ jsx(SymbolBadge, { symbol: value }),
|
|
1793
|
+
/* @__PURE__ */ jsx(Badge, { color: "neutral", size: "xs", children: t("orderEntry.orderType.limit") })
|
|
1794
|
+
] })
|
|
1659
1795
|
] })
|
|
1660
1796
|
] });
|
|
1661
1797
|
}
|
|
@@ -1856,6 +1992,7 @@ registerSimpleDialog(scaledOrderConfirmDialogId, ScaledOrderConfirmWidget, {
|
|
|
1856
1992
|
var OrderTypeSelect = (props) => {
|
|
1857
1993
|
const { t } = useTranslation();
|
|
1858
1994
|
const { isMobile } = useScreen();
|
|
1995
|
+
const { marketOrderDisabled = false, marketOrderDisabledTooltip } = props;
|
|
1859
1996
|
const allOptions = useMemo(() => {
|
|
1860
1997
|
return [
|
|
1861
1998
|
{ label: t("orderEntry.orderType.limitOrder"), value: OrderType.LIMIT },
|
|
@@ -1936,7 +2073,24 @@ var OrderTypeSelect = (props) => {
|
|
|
1936
2073
|
children: /* @__PURE__ */ jsx(Text, { size: "xs", children: t("orderEntry.orderType.limit") })
|
|
1937
2074
|
}
|
|
1938
2075
|
),
|
|
1939
|
-
/* @__PURE__ */ jsx(
|
|
2076
|
+
marketOrderDisabled && marketOrderDisabledTooltip ? /* @__PURE__ */ jsx(
|
|
2077
|
+
Tooltip,
|
|
2078
|
+
{
|
|
2079
|
+
content: marketOrderDisabledTooltip,
|
|
2080
|
+
className: "oui-max-w-[275px]",
|
|
2081
|
+
children: /* @__PURE__ */ jsx("span", { className: "oui-inline-flex oui-flex-1", children: /* @__PURE__ */ jsx(
|
|
2082
|
+
"button",
|
|
2083
|
+
{
|
|
2084
|
+
type: "button",
|
|
2085
|
+
className: unselectedButtonClassName,
|
|
2086
|
+
"aria-pressed": false,
|
|
2087
|
+
disabled: true,
|
|
2088
|
+
"data-testid": "oui-testid-orderEntry-orderType-market",
|
|
2089
|
+
children: /* @__PURE__ */ jsx(Text, { size: "xs", children: t("orderEntry.orderType.market") })
|
|
2090
|
+
}
|
|
2091
|
+
) })
|
|
2092
|
+
}
|
|
2093
|
+
) : /* @__PURE__ */ jsx(
|
|
1940
2094
|
"button",
|
|
1941
2095
|
{
|
|
1942
2096
|
type: "button",
|
|
@@ -1986,14 +2140,25 @@ var OrderTypeSelect = (props) => {
|
|
|
1986
2140
|
}
|
|
1987
2141
|
);
|
|
1988
2142
|
}
|
|
2143
|
+
const mobileOptions = useMemo(() => allOptions, [allOptions]);
|
|
2144
|
+
const handleMobileValueChange = (value) => {
|
|
2145
|
+
if (marketOrderDisabled && value === OrderType.MARKET && marketOrderDisabledTooltip) {
|
|
2146
|
+
modal.alert({
|
|
2147
|
+
title: t("common.tips"),
|
|
2148
|
+
message: marketOrderDisabledTooltip
|
|
2149
|
+
});
|
|
2150
|
+
return;
|
|
2151
|
+
}
|
|
2152
|
+
props.onChange(value);
|
|
2153
|
+
};
|
|
1989
2154
|
return /* @__PURE__ */ jsx(
|
|
1990
2155
|
Select.options,
|
|
1991
2156
|
{
|
|
1992
2157
|
testid: "oui-testid-orderEntry-orderType-button",
|
|
1993
2158
|
currentValue: props.type,
|
|
1994
2159
|
value: props.type,
|
|
1995
|
-
options:
|
|
1996
|
-
onValueChange:
|
|
2160
|
+
options: mobileOptions,
|
|
2161
|
+
onValueChange: handleMobileValueChange,
|
|
1997
2162
|
contentProps: {
|
|
1998
2163
|
className: cn(
|
|
1999
2164
|
"oui-orderEntry-orderTypeSelect-content",
|
|
@@ -2096,10 +2261,11 @@ var MarginModeSwitch = (props) => {
|
|
|
2096
2261
|
{
|
|
2097
2262
|
className: "oui-tracking-[0.03em]",
|
|
2098
2263
|
rule: "symbol",
|
|
2099
|
-
formatString: "base
|
|
2264
|
+
formatString: "base",
|
|
2100
2265
|
size: "base",
|
|
2101
2266
|
weight: "semibold",
|
|
2102
2267
|
intensity: 98,
|
|
2268
|
+
suffix: /* @__PURE__ */ jsx(SymbolBadge, { symbol: props.symbol }),
|
|
2103
2269
|
children: props.symbol
|
|
2104
2270
|
}
|
|
2105
2271
|
)
|
|
@@ -2111,7 +2277,8 @@ var MarginModeSwitch = (props) => {
|
|
|
2111
2277
|
mode: MarginMode.CROSS,
|
|
2112
2278
|
selected: props.selectedMarginMode === MarginMode.CROSS,
|
|
2113
2279
|
isCurrent: props.currentMarginMode === MarginMode.CROSS,
|
|
2114
|
-
onClick: () => handleSelect(MarginMode.CROSS)
|
|
2280
|
+
onClick: () => handleSelect(MarginMode.CROSS),
|
|
2281
|
+
disabled: props.isPermissionlessListing
|
|
2115
2282
|
}
|
|
2116
2283
|
),
|
|
2117
2284
|
/* @__PURE__ */ jsx(
|
|
@@ -2174,9 +2341,11 @@ var OptionCard = (props) => {
|
|
|
2174
2341
|
"oui-relative oui-w-full oui-rounded-md oui-p-2",
|
|
2175
2342
|
"oui-bg-base-6",
|
|
2176
2343
|
"oui-text-left",
|
|
2177
|
-
props.selected ? "oui-border oui-border-[#38e2fe]" : "oui-border oui-border-transparent hover:oui-border-line-12"
|
|
2344
|
+
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"
|
|
2178
2345
|
),
|
|
2179
|
-
onClick: props.onClick,
|
|
2346
|
+
onClick: props.disabled ? void 0 : props.onClick,
|
|
2347
|
+
disabled: props.disabled,
|
|
2348
|
+
"aria-disabled": props.disabled,
|
|
2180
2349
|
"data-testid": `oui-testid-marginModeSwitch-option-${props.mode}`,
|
|
2181
2350
|
children: [
|
|
2182
2351
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, itemAlign: "start", className: "oui-w-full", children: [
|
|
@@ -2209,7 +2378,11 @@ var useMarginModeSwitchScript = (options2) => {
|
|
|
2209
2378
|
const { symbol, close } = options2;
|
|
2210
2379
|
const { isMobile } = useScreen();
|
|
2211
2380
|
const { t } = useTranslation();
|
|
2212
|
-
const {
|
|
2381
|
+
const {
|
|
2382
|
+
marginMode: currentMarginMode,
|
|
2383
|
+
update,
|
|
2384
|
+
isPermissionlessListing
|
|
2385
|
+
} = useMarginModeBySymbol(symbol);
|
|
2213
2386
|
const [selectedMarginMode, setSelectedMarginMode] = useState(currentMarginMode);
|
|
2214
2387
|
useEffect(() => {
|
|
2215
2388
|
setSelectedMarginMode(currentMarginMode);
|
|
@@ -2247,11 +2420,13 @@ var useMarginModeSwitchScript = (options2) => {
|
|
|
2247
2420
|
setSelectedMarginMode,
|
|
2248
2421
|
applyMarginMode,
|
|
2249
2422
|
close,
|
|
2250
|
-
onSelect
|
|
2423
|
+
onSelect,
|
|
2424
|
+
isPermissionlessListing
|
|
2251
2425
|
};
|
|
2252
2426
|
};
|
|
2253
2427
|
var useMarginModeSettingsScript = (options2) => {
|
|
2254
2428
|
const { isMobile } = useScreen();
|
|
2429
|
+
const { t } = useTranslation();
|
|
2255
2430
|
const [markets] = useMarkets(MarketsType.ALL);
|
|
2256
2431
|
const items = useMemo(() => {
|
|
2257
2432
|
if (!markets || markets.length === 0) {
|
|
@@ -2260,10 +2435,20 @@ var useMarginModeSettingsScript = (options2) => {
|
|
|
2260
2435
|
return markets.map((market) => ({
|
|
2261
2436
|
key: market.symbol,
|
|
2262
2437
|
// Original symbol: "PERP_BTC_USDC"
|
|
2263
|
-
symbol: formatSymbol(market.symbol, "base
|
|
2438
|
+
symbol: formatSymbol(market.symbol, "base"),
|
|
2264
2439
|
// Formatted: "BTC-PERP"
|
|
2440
|
+
brokerId: market.broker_id
|
|
2265
2441
|
}));
|
|
2266
2442
|
}, [markets]);
|
|
2443
|
+
const brokerLockedKeys = useMemo(() => {
|
|
2444
|
+
const locked = /* @__PURE__ */ new Set();
|
|
2445
|
+
for (const item of items) {
|
|
2446
|
+
if (item.brokerId) {
|
|
2447
|
+
locked.add(item.key);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
return locked;
|
|
2451
|
+
}, [items]);
|
|
2267
2452
|
const [searchKeyword, setSearchKeyword] = useState("");
|
|
2268
2453
|
const [selectedKeys, setSelectedKeys] = useState(
|
|
2269
2454
|
() => /* @__PURE__ */ new Set()
|
|
@@ -2284,11 +2469,15 @@ var useMarginModeSettingsScript = (options2) => {
|
|
|
2284
2469
|
const itemMarginModes = useMemo(() => {
|
|
2285
2470
|
const result = {};
|
|
2286
2471
|
for (const item of items) {
|
|
2472
|
+
if (brokerLockedKeys.has(item.key)) {
|
|
2473
|
+
result[item.key] = MarginMode.ISOLATED;
|
|
2474
|
+
continue;
|
|
2475
|
+
}
|
|
2287
2476
|
const marginMode = marginModes[item.key];
|
|
2288
2477
|
result[item.key] = marginMode ?? MarginMode.CROSS;
|
|
2289
2478
|
}
|
|
2290
2479
|
return result;
|
|
2291
|
-
}, [items, marginModes]);
|
|
2480
|
+
}, [brokerLockedKeys, items, marginModes]);
|
|
2292
2481
|
const filteredItems = useMemo(() => {
|
|
2293
2482
|
const keyword = searchKeyword.trim().toLowerCase();
|
|
2294
2483
|
if (!keyword) return items;
|
|
@@ -2324,17 +2513,21 @@ var useMarginModeSettingsScript = (options2) => {
|
|
|
2324
2513
|
const onSearchChange = useCallback((keyword) => {
|
|
2325
2514
|
setSearchKeyword(keyword);
|
|
2326
2515
|
}, []);
|
|
2327
|
-
const onToggleItem = useCallback(
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
next
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2516
|
+
const onToggleItem = useCallback(
|
|
2517
|
+
(key) => {
|
|
2518
|
+
if (brokerLockedKeys.has(key)) return;
|
|
2519
|
+
setSelectedKeys((prev) => {
|
|
2520
|
+
const next = new Set(prev);
|
|
2521
|
+
if (next.has(key)) {
|
|
2522
|
+
next.delete(key);
|
|
2523
|
+
} else {
|
|
2524
|
+
next.add(key);
|
|
2525
|
+
}
|
|
2526
|
+
return next;
|
|
2527
|
+
});
|
|
2528
|
+
},
|
|
2529
|
+
[brokerLockedKeys]
|
|
2530
|
+
);
|
|
2338
2531
|
const onToggleSelectAll = useCallback(() => {
|
|
2339
2532
|
setSelectedKeys((prev) => {
|
|
2340
2533
|
const next = new Set(prev);
|
|
@@ -2345,31 +2538,39 @@ var useMarginModeSettingsScript = (options2) => {
|
|
|
2345
2538
|
return next;
|
|
2346
2539
|
}
|
|
2347
2540
|
for (const item of filteredItems) {
|
|
2541
|
+
if (brokerLockedKeys.has(item.key)) continue;
|
|
2348
2542
|
next.add(item.key);
|
|
2349
2543
|
}
|
|
2350
2544
|
return next;
|
|
2351
2545
|
});
|
|
2352
|
-
}, [filteredItems, isSelectAll]);
|
|
2546
|
+
}, [brokerLockedKeys, filteredItems, isSelectAll]);
|
|
2353
2547
|
const onSetMarginMode = useCallback(
|
|
2354
2548
|
async (mode) => {
|
|
2355
2549
|
if (selectedKeys.size === 0) return;
|
|
2550
|
+
const editableSymbolList = Array.from(selectedKeys).filter(
|
|
2551
|
+
(key) => !brokerLockedKeys.has(key)
|
|
2552
|
+
);
|
|
2553
|
+
if (editableSymbolList.length === 0) {
|
|
2554
|
+
toast.error(t("marginMode.noEditableSymbolsSelected"));
|
|
2555
|
+
return;
|
|
2556
|
+
}
|
|
2356
2557
|
setIsOperationLoading(true);
|
|
2357
2558
|
try {
|
|
2358
2559
|
const payload = {
|
|
2359
|
-
symbol_list:
|
|
2560
|
+
symbol_list: editableSymbolList,
|
|
2360
2561
|
default_margin_mode: mode
|
|
2361
2562
|
};
|
|
2362
2563
|
await updateMarginMode(payload);
|
|
2363
|
-
toast.success("
|
|
2564
|
+
toast.success(t("marginMode.updatedSuccessfully"));
|
|
2364
2565
|
} catch (error) {
|
|
2365
2566
|
toast.error(
|
|
2366
|
-
error instanceof Error ? error.message : "
|
|
2567
|
+
error instanceof Error ? error.message : t("marginMode.failedToUpdateMarginMode")
|
|
2367
2568
|
);
|
|
2368
2569
|
} finally {
|
|
2369
2570
|
setIsOperationLoading(false);
|
|
2370
2571
|
}
|
|
2371
2572
|
},
|
|
2372
|
-
[selectedKeys, updateMarginMode]
|
|
2573
|
+
[brokerLockedKeys, selectedKeys, updateMarginMode]
|
|
2373
2574
|
);
|
|
2374
2575
|
const isLoading = isDataLoading || isMarginModesLoading || isOperationLoading || isSettingMarginMode;
|
|
2375
2576
|
return {
|
|
@@ -2517,7 +2718,8 @@ var MarginModeSettings = (props) => {
|
|
|
2517
2718
|
item,
|
|
2518
2719
|
checked: props.selectedKeys.has(item.key),
|
|
2519
2720
|
marginMode: props.itemMarginModes[item.key] ?? MarginMode.CROSS,
|
|
2520
|
-
onToggle: props.onToggleItem
|
|
2721
|
+
onToggle: props.onToggleItem,
|
|
2722
|
+
disabled: !!item.brokerId
|
|
2521
2723
|
},
|
|
2522
2724
|
item.key
|
|
2523
2725
|
))
|
|
@@ -2620,13 +2822,15 @@ var MarginModeSettings = (props) => {
|
|
|
2620
2822
|
var SymbolRow = (props) => {
|
|
2621
2823
|
const { t } = useTranslation();
|
|
2622
2824
|
const handleCheckedChange = useCallback(() => {
|
|
2825
|
+
if (props.disabled) return;
|
|
2623
2826
|
props.onToggle(props.item.key);
|
|
2624
2827
|
}, [props]);
|
|
2625
|
-
|
|
2828
|
+
const row = /* @__PURE__ */ jsx(Flex, { itemAlign: "center", className: "oui-w-full", children: /* @__PURE__ */ jsxs(
|
|
2626
2829
|
"label",
|
|
2627
2830
|
{
|
|
2628
2831
|
className: cn(
|
|
2629
|
-
"oui-flex oui-items-center oui-gap-2 oui-flex-1 oui-cursor-pointer oui-select-none oui-w-full"
|
|
2832
|
+
"oui-flex oui-items-center oui-gap-2 oui-flex-1 oui-cursor-pointer oui-select-none oui-w-full",
|
|
2833
|
+
props.disabled ? "oui-cursor-not-allowed oui-opacity-50" : ""
|
|
2630
2834
|
),
|
|
2631
2835
|
"data-testid": `oui-testid-marginModeSettings-item-${props.item.key}`,
|
|
2632
2836
|
children: [
|
|
@@ -2636,10 +2840,12 @@ var SymbolRow = (props) => {
|
|
|
2636
2840
|
color: "white",
|
|
2637
2841
|
checked: props.checked,
|
|
2638
2842
|
onCheckedChange: handleCheckedChange,
|
|
2639
|
-
"aria-label": props.item.symbol
|
|
2843
|
+
"aria-label": props.item.symbol,
|
|
2844
|
+
disabled: props.disabled
|
|
2640
2845
|
}
|
|
2641
2846
|
),
|
|
2642
2847
|
/* @__PURE__ */ jsx(Text, { className: "oui-text-sm oui-font-semibold oui-text-base-contrast-80", children: props.item.symbol }),
|
|
2848
|
+
/* @__PURE__ */ jsx(SymbolBadge, { symbol: props.item.key }),
|
|
2643
2849
|
/* @__PURE__ */ jsx(
|
|
2644
2850
|
"span",
|
|
2645
2851
|
{
|
|
@@ -2655,6 +2861,17 @@ var SymbolRow = (props) => {
|
|
|
2655
2861
|
]
|
|
2656
2862
|
}
|
|
2657
2863
|
) });
|
|
2864
|
+
if (props.disabled) {
|
|
2865
|
+
return /* @__PURE__ */ jsx(
|
|
2866
|
+
Tooltip,
|
|
2867
|
+
{
|
|
2868
|
+
content: t("marginMode.disabledSymbolTooltip"),
|
|
2869
|
+
className: "oui-max-w-[280px] oui-text-2xs oui-text-base-contrast-80",
|
|
2870
|
+
children: row
|
|
2871
|
+
}
|
|
2872
|
+
);
|
|
2873
|
+
}
|
|
2874
|
+
return row;
|
|
2658
2875
|
};
|
|
2659
2876
|
var SearchGlyph = (props) => {
|
|
2660
2877
|
return /* @__PURE__ */ jsx(
|
|
@@ -2846,7 +3063,9 @@ function OrderEntryHeader(props) {
|
|
|
2846
3063
|
canTrade,
|
|
2847
3064
|
onChange: (type) => {
|
|
2848
3065
|
setOrderValue("order_type", type);
|
|
2849
|
-
}
|
|
3066
|
+
},
|
|
3067
|
+
marketOrderDisabled: props.marketOrderDisabled,
|
|
3068
|
+
marketOrderDisabledTooltip: props.marketOrderDisabledTooltip
|
|
2850
3069
|
}
|
|
2851
3070
|
) }),
|
|
2852
3071
|
/* @__PURE__ */ jsxs(
|
|
@@ -4617,12 +4836,15 @@ var usePNLInputBuilder = (props) => {
|
|
|
4617
4836
|
}
|
|
4618
4837
|
if (value === "" || value === "-") return "";
|
|
4619
4838
|
if (mode === "Offset%" /* PERCENTAGE */) {
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4839
|
+
let normalized = value.replace(
|
|
4840
|
+
new RegExp(percentageSuffix.current.replace(".", "\\.") + "$"),
|
|
4841
|
+
""
|
|
4842
|
+
).replace(/,/g, "");
|
|
4843
|
+
normalized = normalized.replace(/\.$/, "");
|
|
4844
|
+
if (isNaN(Number(normalized)) || normalized === "" || normalized === "-") {
|
|
4845
|
+
return value;
|
|
4846
|
+
}
|
|
4847
|
+
return `${new Decimal(normalized).mul(100).todp(2, 4).toString()}${percentageSuffix.current}`;
|
|
4626
4848
|
} else if (mode === "Offset" /* OFFSET */) {
|
|
4627
4849
|
value = todpIfNeed(value, dp);
|
|
4628
4850
|
} else ;
|
|
@@ -4641,6 +4863,9 @@ var usePNLInputBuilder = (props) => {
|
|
|
4641
4863
|
} else {
|
|
4642
4864
|
percentageSuffix.current = "";
|
|
4643
4865
|
}
|
|
4866
|
+
if (isNaN(Number(value))) {
|
|
4867
|
+
return value;
|
|
4868
|
+
}
|
|
4644
4869
|
value = new Decimal(value).div(100).toString();
|
|
4645
4870
|
value = `${value}${percentageSuffix.current}`;
|
|
4646
4871
|
}
|
|
@@ -5176,6 +5401,7 @@ var OrderEntry = (props) => {
|
|
|
5176
5401
|
setOrderValue,
|
|
5177
5402
|
manualSetOrderValue,
|
|
5178
5403
|
setOrderValues,
|
|
5404
|
+
setOrderValuesRaw,
|
|
5179
5405
|
symbolInfo,
|
|
5180
5406
|
maxQty,
|
|
5181
5407
|
freeCollateral,
|
|
@@ -5191,9 +5417,13 @@ var OrderEntry = (props) => {
|
|
|
5191
5417
|
fillMiddleValue,
|
|
5192
5418
|
soundAlert,
|
|
5193
5419
|
setSoundAlert,
|
|
5194
|
-
currentFocusInput
|
|
5420
|
+
currentFocusInput,
|
|
5421
|
+
walletAddress,
|
|
5422
|
+
isPermissionlessListing,
|
|
5423
|
+
symbol
|
|
5195
5424
|
} = props;
|
|
5196
5425
|
const [maxQtyConfirmOpen, setMaxQtyConfirmOpen] = useState(false);
|
|
5426
|
+
const [permissionlessAcknowledgedKeys, setPermissionlessAcknowledgedKeys] = useLocalStorage("orderly-permissionless-market-notice", []);
|
|
5197
5427
|
const { t } = useTranslation();
|
|
5198
5428
|
const { isMobile } = useScreen();
|
|
5199
5429
|
const [hasAdvancedTPSLResult, setHasAdvancedTPSLResult] = useState(false);
|
|
@@ -5263,22 +5493,7 @@ var OrderEntry = (props) => {
|
|
|
5263
5493
|
helper.validate(isSlPriceError ? props.slPriceError : void 0).then(
|
|
5264
5494
|
// validate success, it return the order
|
|
5265
5495
|
// TODO: get order from other function
|
|
5266
|
-
(order) =>
|
|
5267
|
-
if (isScaledOrder) {
|
|
5268
|
-
return modal.show(scaledOrderConfirmDialogId, {
|
|
5269
|
-
order,
|
|
5270
|
-
symbolInfo,
|
|
5271
|
-
size: isMobile ? "sm" : "md"
|
|
5272
|
-
});
|
|
5273
|
-
}
|
|
5274
|
-
if (needConfirm) {
|
|
5275
|
-
return modal.show(orderConfirmDialogId, {
|
|
5276
|
-
order: formattedOrder,
|
|
5277
|
-
symbolInfo
|
|
5278
|
-
});
|
|
5279
|
-
}
|
|
5280
|
-
return true;
|
|
5281
|
-
},
|
|
5496
|
+
(order) => order,
|
|
5282
5497
|
// should catch validate error first, then submit
|
|
5283
5498
|
(errors2) => {
|
|
5284
5499
|
if (errors2.slippage) {
|
|
@@ -5287,7 +5502,38 @@ var OrderEntry = (props) => {
|
|
|
5287
5502
|
setErrorMsgVisible(true);
|
|
5288
5503
|
return Promise.reject();
|
|
5289
5504
|
}
|
|
5290
|
-
).then(() => {
|
|
5505
|
+
).then((order) => {
|
|
5506
|
+
const shouldShowPermissionlessNotice = isPermissionlessListing && walletAddress && !(permissionlessAcknowledgedKeys ?? []).includes(
|
|
5507
|
+
`${walletAddress}_${symbol}`
|
|
5508
|
+
);
|
|
5509
|
+
if (shouldShowPermissionlessNotice) {
|
|
5510
|
+
return modal.show(
|
|
5511
|
+
isMobile ? permissionlessMarketNoticeDialogId : permissionlessMarketNoticeDesktopDialogId
|
|
5512
|
+
).then(() => {
|
|
5513
|
+
setPermissionlessAcknowledgedKeys([
|
|
5514
|
+
...Array.isArray(permissionlessAcknowledgedKeys) ? permissionlessAcknowledgedKeys : [],
|
|
5515
|
+
`${walletAddress}_${symbol}`
|
|
5516
|
+
]);
|
|
5517
|
+
return order;
|
|
5518
|
+
});
|
|
5519
|
+
}
|
|
5520
|
+
return Promise.resolve(order);
|
|
5521
|
+
}).then((order) => {
|
|
5522
|
+
if (isScaledOrder) {
|
|
5523
|
+
return modal.show(scaledOrderConfirmDialogId, {
|
|
5524
|
+
order,
|
|
5525
|
+
symbolInfo,
|
|
5526
|
+
size: isMobile ? "sm" : "md"
|
|
5527
|
+
});
|
|
5528
|
+
}
|
|
5529
|
+
if (needConfirm) {
|
|
5530
|
+
return modal.show(orderConfirmDialogId, {
|
|
5531
|
+
order: formattedOrder,
|
|
5532
|
+
symbolInfo
|
|
5533
|
+
});
|
|
5534
|
+
}
|
|
5535
|
+
return true;
|
|
5536
|
+
}).then(() => {
|
|
5291
5537
|
return submit({ resetOnSuccess: false }).then((result) => {
|
|
5292
5538
|
if (!result.success && result.message) {
|
|
5293
5539
|
toast.error(result.message);
|
|
@@ -5355,7 +5601,7 @@ var OrderEntry = (props) => {
|
|
|
5355
5601
|
if (order.side !== formattedOrder.side) {
|
|
5356
5602
|
manualSetOrderValue("side", order.side);
|
|
5357
5603
|
}
|
|
5358
|
-
|
|
5604
|
+
setOrderValuesRaw({
|
|
5359
5605
|
position_type: order.position_type,
|
|
5360
5606
|
tp_order_type: order.tp_order_type,
|
|
5361
5607
|
tp_pnl: order.tp_pnl,
|
|
@@ -5454,7 +5700,11 @@ var OrderEntry = (props) => {
|
|
|
5454
5700
|
order_type: formattedOrder.order_type,
|
|
5455
5701
|
setOrderValue: manualSetOrderValue,
|
|
5456
5702
|
symbolLeverage: props.symbolLeverage,
|
|
5457
|
-
marginMode: props.marginMode
|
|
5703
|
+
marginMode: props.marginMode,
|
|
5704
|
+
marketOrderDisabled: props.isSymbolPostOnly,
|
|
5705
|
+
marketOrderDisabledTooltip: t(
|
|
5706
|
+
"orderEntry.orderType.symbolPostOnly.tooltip"
|
|
5707
|
+
)
|
|
5458
5708
|
}
|
|
5459
5709
|
),
|
|
5460
5710
|
/* @__PURE__ */ jsx(
|
|
@@ -5852,11 +6102,14 @@ var useOrderEntryScript = (inputs) => {
|
|
|
5852
6102
|
defaultSoundValue ?? null
|
|
5853
6103
|
);
|
|
5854
6104
|
const canTrade = useCanTrade();
|
|
5855
|
-
const {
|
|
6105
|
+
const { state: accountState } = useAccount();
|
|
6106
|
+
const { marginMode, isPermissionlessListing } = useMarginModeBySymbol(symbol);
|
|
6107
|
+
const walletAddress = accountState?.address;
|
|
5856
6108
|
const {
|
|
5857
6109
|
formattedOrder,
|
|
5858
6110
|
setValue,
|
|
5859
6111
|
setValues: setOrderValues,
|
|
6112
|
+
setValuesRaw: setOrderValuesRaw,
|
|
5860
6113
|
symbolInfo,
|
|
5861
6114
|
symbolLeverage,
|
|
5862
6115
|
...state
|
|
@@ -6052,6 +6305,16 @@ var useOrderEntryScript = (inputs) => {
|
|
|
6052
6305
|
setValue("distribution_type", DistributionType.FLAT);
|
|
6053
6306
|
}
|
|
6054
6307
|
}, [formattedOrder.order_type, formattedOrder.distribution_type]);
|
|
6308
|
+
const isSymbolPostOnly = symbolInfo?.status === "POST_ONLY";
|
|
6309
|
+
useEffect(() => {
|
|
6310
|
+
if (isSymbolPostOnly && (formattedOrder.order_type === OrderType.MARKET || formattedOrder.order_type === OrderType.STOP_MARKET)) {
|
|
6311
|
+
setLocalOrderType(OrderType.LIMIT);
|
|
6312
|
+
setOrderValues({
|
|
6313
|
+
order_type: OrderType.LIMIT,
|
|
6314
|
+
order_type_ext: void 0
|
|
6315
|
+
});
|
|
6316
|
+
}
|
|
6317
|
+
}, [isSymbolPostOnly, formattedOrder.order_type, setOrderValues]);
|
|
6055
6318
|
const currentLtv = useComputedLTV();
|
|
6056
6319
|
const askAndBid = useAskAndBid();
|
|
6057
6320
|
const fillMiddleValue = () => {
|
|
@@ -6115,6 +6378,7 @@ var useOrderEntryScript = (inputs) => {
|
|
|
6115
6378
|
setOrderValue,
|
|
6116
6379
|
manualSetOrderValue,
|
|
6117
6380
|
setOrderValues,
|
|
6381
|
+
setOrderValuesRaw,
|
|
6118
6382
|
// account-level leverage (for other consumers)
|
|
6119
6383
|
currentLeverage,
|
|
6120
6384
|
// symbol-level leverage & margin mode for this order entry
|
|
@@ -6143,7 +6407,10 @@ var useOrderEntryScript = (inputs) => {
|
|
|
6143
6407
|
symbol,
|
|
6144
6408
|
soundAlert,
|
|
6145
6409
|
setSoundAlert,
|
|
6146
|
-
currentFocusInput
|
|
6410
|
+
currentFocusInput,
|
|
6411
|
+
walletAddress,
|
|
6412
|
+
isPermissionlessListing,
|
|
6413
|
+
isSymbolPostOnly
|
|
6147
6414
|
};
|
|
6148
6415
|
};
|
|
6149
6416
|
var OrderEntryWidget = (props) => {
|
|
@@ -6158,6 +6425,6 @@ var OrderEntryWidget = (props) => {
|
|
|
6158
6425
|
);
|
|
6159
6426
|
};
|
|
6160
6427
|
|
|
6161
|
-
export { AdditionalInfo, FeesWidget, LTVRiskTooltipWidget, OrderConfirmDialog, OrderEntry, OrderEntryWidget, useOrderEntryScript };
|
|
6428
|
+
export { AdditionalInfo, FeesWidget, LTVRiskTooltipWidget, OrderConfirmDialog, OrderEntry, OrderEntryWidget, SymbolBadge, useOrderEntryScript };
|
|
6162
6429
|
//# sourceMappingURL=index.mjs.map
|
|
6163
6430
|
//# sourceMappingURL=index.mjs.map
|