@orderly.network/ui-positions 2.10.2 → 2.11.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.mjs CHANGED
@@ -1,12 +1,12 @@
1
- import { registerSimpleDialog, useModal, SimpleDialog, Flex, Text, Badge, Divider, CloseIcon, Button, ThrottledButton, useScreen, ArrowDownShortIcon, ArrowUpShortIcon, Grid, Statistic, ExclamationFillIcon, modal, Tooltip, DataTable, cn, ListView, SimpleSheet, usePagination, DataFilter, toast, PopoverRoot, PopoverTrigger, PopoverContent, Checkbox, formatAddress, Box, HoverCard, ArrowLeftRightIcon, capitalizeFirstLetter, ShareIcon, EditIcon, Input, inputFormatter, Select, Tips, Slider } from '@orderly.network/ui';
1
+ import { registerSimpleDialog, registerSimpleSheet, useModal, SimpleDialog, useScreen, Flex, Text, Badge, Divider, toast, modal, CloseIcon, Button, ThrottledButton, ArrowDownShortIcon, ArrowUpShortIcon, IconButton, TokenIcon, cn, Input, inputFormatter, Slider, Statistic, Grid, ExclamationFillIcon, Tooltip, DataTable, ListView, SimpleSheet, usePagination, DataFilter, PopoverRoot, PopoverTrigger, PopoverContent, Checkbox, formatAddress, Box, HoverCard, AddCircleIcon, ChevronRightIcon, ArrowLeftRightIcon, capitalizeFirstLetter, ShareIcon, EditIcon, Select, Tips } from '@orderly.network/ui';
2
2
  import React2, { createContext, useMemo, useState, useCallback, useContext, useEffect, useRef } from 'react';
3
3
  import { i18n, useTranslation } from '@orderly.network/i18n';
4
- import { OrderSide, OrderType, EMPTY_LIST, AccountStatusEnum, TrackerEventName, OrderStatus, AlgoOrderRootType, PositionType, AlgoOrderType } from '@orderly.network/types';
4
+ import { OrderSide, MarginMode, OrderType, EMPTY_LIST, AccountStatusEnum, TrackerEventName, OrderStatus, AlgoOrderRootType, PositionType, AlgoOrderType } from '@orderly.network/types';
5
5
  import { commifyOptional, Decimal, formatNum, getTimestamp, commify } from '@orderly.network/utils';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
- import { useLocalStorage, useSymbolsInfo, useMarkPrice, usePositionStream, useSubAccountMutation, usePrivateInfiniteQuery, useBoolean, useSessionStorage, useAccount, usePrivateQuery, useTrack, usePositionClose, useSWR, fetcher, useEventEmitter, useDebouncedCallback, useGetRwaSymbolOpenStatus, useTpslPriceChecker, useConfig, findPositionTPSLFromOrders, findTPSLFromOrder, useReferralInfo, useAccountInfo, useLeverageBySymbol, utils, useMaxLeverage } from '@orderly.network/hooks';
7
+ import { useLocalStorage, useSymbolsInfo, useMarkPrice, usePositionStream, useSubAccountMutation, useMutation, useCollateral, usePositions, useAppStore, usePrivateInfiniteQuery, useBoolean, useSessionStorage, useAccount, usePrivateQuery, useTrack, usePositionClose, useSWR, fetcher, useEventEmitter, useDebouncedCallback, useGetRwaSymbolOpenStatus, useTpslPriceChecker, useConfig, findPositionTPSLFromOrders, findTPSLFromOrder, useReferralInfo, useLeverageBySymbol, utils, useMaxLeverage } from '@orderly.network/hooks';
8
8
  import { useDataTap, useOrderEntryFormErrorMsg } from '@orderly.network/react-app';
9
- import { positions, account } from '@orderly.network/perp';
9
+ import { account, positions } from '@orderly.network/perp';
10
10
  import { AuthGuardDataTable } from '@orderly.network/ui-connector';
11
11
  import { SymbolLeverageDialogId, SymbolLeverageSheetId } from '@orderly.network/ui-leverage';
12
12
  import { SharePnLDialogId, SharePnLBottomSheetId } from '@orderly.network/ui-share';
@@ -592,7 +592,7 @@ var calculatePositions = (positions2, symbolsInfo, accountInfo, tpslOrders) => {
592
592
  return positions2.map((item) => {
593
593
  const info = symbolsInfo[item.symbol];
594
594
  const notional = positions.notional(item.position_qty, item.mark_price);
595
- const account2 = accountInfo.find(
595
+ const account3 = accountInfo.find(
596
596
  (acc) => acc.account_id === item.account_id
597
597
  );
598
598
  const baseMMR = info?.("base_mmr");
@@ -603,7 +603,7 @@ var calculatePositions = (positions2, symbolsInfo, accountInfo, tpslOrders) => {
603
603
  const MMR = positions.MMR({
604
604
  baseMMR,
605
605
  baseIMR,
606
- IMRFactor: account2?.imr_factor[item.symbol] ?? 0,
606
+ IMRFactor: account3?.imr_factor[item.symbol] ?? 0,
607
607
  positionNotional: notional,
608
608
  IMR_factor_power: 4 / 5
609
609
  });
@@ -621,7 +621,7 @@ var calculatePositions = (positions2, symbolsInfo, accountInfo, tpslOrders) => {
621
621
  const imr = account.IMR({
622
622
  maxLeverage,
623
623
  baseIMR,
624
- IMR_Factor: account2?.imr_factor[item.symbol] ?? 0,
624
+ IMR_Factor: account3?.imr_factor[item.symbol] ?? 0,
625
625
  positionNotional: notional,
626
626
  ordersNotional: 0,
627
627
  IMR_factor_power: 4 / 5
@@ -650,7 +650,7 @@ var calculatePositions = (positions2, symbolsInfo, accountInfo, tpslOrders) => {
650
650
  const filteredTPSLOrders = tpslOrders.filter(
651
651
  (tpslOrder) => tpslOrder.account_id === item.account_id
652
652
  );
653
- const tpsl = formatTPSL(filteredTPSLOrders, item.symbol);
653
+ const tpsl = formatTPSL(filteredTPSLOrders, item.symbol, item.margin_mode);
654
654
  return {
655
655
  ...item,
656
656
  ...tpsl,
@@ -663,9 +663,9 @@ var calculatePositions = (positions2, symbolsInfo, accountInfo, tpslOrders) => {
663
663
  };
664
664
  });
665
665
  };
666
- function formatTPSL(tpslOrders, symbol) {
666
+ function formatTPSL(tpslOrders, symbol, marginMode) {
667
667
  if (Array.isArray(tpslOrders) && tpslOrders.length) {
668
- const { fullPositionOrder, partialPositionOrders } = findPositionTPSLFromOrders(tpslOrders, symbol);
668
+ const { fullPositionOrder, partialPositionOrders } = findPositionTPSLFromOrders(tpslOrders, symbol, marginMode);
669
669
  const full_tp_sl = fullPositionOrder ? findTPSLFromOrder(fullPositionOrder) : void 0;
670
670
  const partialPossitionOrder = partialPositionOrders && partialPositionOrders.length ? partialPositionOrders[0] : void 0;
671
671
  const partial_tp_sl = partialPossitionOrder ? findTPSLFromOrder(partialPossitionOrder) : void 0;
@@ -684,7 +684,7 @@ function formatTPSL(tpslOrders, symbol) {
684
684
  };
685
685
  }
686
686
  }
687
- var signatureMiddleware = (account2, accountId) => {
687
+ var signatureMiddleware = (account3, accountId) => {
688
688
  const apiBaseUrl = useConfig("apiBaseUrl");
689
689
  return (useSWRNext) => {
690
690
  return (key, fetcher2, config) => {
@@ -692,7 +692,7 @@ var signatureMiddleware = (account2, accountId) => {
692
692
  const extendedFetcher = async (args) => {
693
693
  const url = Array.isArray(args) ? args[0] : args;
694
694
  const fullUrl = `${apiBaseUrl}${url}`;
695
- const signer = account2.signer;
695
+ const signer = account3.signer;
696
696
  const payload = { method: "GET", url };
697
697
  const signature = await signer.sign(payload, getTimestamp());
698
698
  const ids = Array.isArray(accountId) ? accountId : [accountId];
@@ -716,7 +716,7 @@ var signatureMiddleware = (account2, accountId) => {
716
716
  };
717
717
  var useSubAccountQuery = (query, options) => {
718
718
  const { formatter, accountId, ...swrOptions } = options || {};
719
- const { state, account: account2 } = useAccount();
719
+ const { state, account: account3 } = useAccount();
720
720
  const middleware = Array.isArray(options?.use) ? options?.use ?? [] : [];
721
721
  const ids = Array.isArray(accountId) ? accountId : [accountId];
722
722
  const shouldFetch = ids.filter(Boolean).length && (state.status >= AccountStatusEnum.EnableTrading || state.status === AccountStatusEnum.EnableTradingWithoutConnected);
@@ -727,7 +727,7 @@ var useSubAccountQuery = (query, options) => {
727
727
  },
728
728
  {
729
729
  ...swrOptions,
730
- use: [...middleware, signatureMiddleware(account2, ids)],
730
+ use: [...middleware, signatureMiddleware(account3, ids)],
731
731
  onError: () => {
732
732
  }
733
733
  }
@@ -1262,7 +1262,9 @@ var useReversePositionScript = (options) => {
1262
1262
  order_type: OrderType.MARKET,
1263
1263
  side,
1264
1264
  order_quantity: new Decimal(qty).todp(baseDp).toString(),
1265
- reduce_only: reduceOnly
1265
+ reduce_only: reduceOnly,
1266
+ // Use position's margin_mode or default to CROSS for backward compatibility
1267
+ margin_mode: position.margin_mode || MarginMode.CROSS
1266
1268
  };
1267
1269
  };
1268
1270
  const closeSide = isLong ? OrderSide.SELL : OrderSide.BUY;
@@ -1598,6 +1600,610 @@ var RwaStatusTag = ({ symbol }) => {
1598
1600
  }
1599
1601
  );
1600
1602
  };
1603
+ var usePositionMargin = (symbol, isAdd, isolatedMargin, finalMargin) => {
1604
+ const { freeCollateral, freeCollateralUSDCOnly, usdcHolding } = useCollateral(
1605
+ {
1606
+ dp: 2
1607
+ }
1608
+ );
1609
+ const positions2 = usePositions();
1610
+ const total_cross_unsettled_pnl = useMemo(() => {
1611
+ return positions2?.filter((item) => (item.margin_mode ?? "CROSS") === "CROSS").reduce((acc, item) => acc.add(item.unsettled_pnl), new Decimal(0));
1612
+ }, [positions2]);
1613
+ const fundingRates = useAppStore((state) => state.fundingRates);
1614
+ const symbolsInfo = useAppStore((state) => state.symbolsInfo);
1615
+ const accountInfo = useAppStore((state) => state.accountInfo);
1616
+ const { data: markPrice } = useMarkPrice(symbol);
1617
+ const totalUnsettlementPnl = useMemo(() => {
1618
+ if (!positions2?.length) {
1619
+ return null;
1620
+ }
1621
+ return positions2.reduce((acc, item) => {
1622
+ const itemAny = item;
1623
+ const positionUnsettlementPnl = itemAny["unsettlement_pnl"] ?? item.unsettled_pnl ?? 0;
1624
+ return acc.add(positionUnsettlementPnl);
1625
+ }, new Decimal(0));
1626
+ }, [positions2]);
1627
+ const currentPosition = useMemo(() => {
1628
+ return positions2?.find(
1629
+ (item) => item.symbol === symbol && item.margin_mode === MarginMode.ISOLATED
1630
+ );
1631
+ }, [positions2]);
1632
+ const notional = useMemo(() => {
1633
+ if (!currentPosition) return null;
1634
+ return new Decimal(currentPosition.notional);
1635
+ }, [currentPosition]);
1636
+ const unSettledPnl = currentPosition?.unsettled_pnl;
1637
+ const imr = useMemo(() => {
1638
+ if (!currentPosition || !symbolsInfo?.[symbol] || !notional) {
1639
+ return null;
1640
+ }
1641
+ const currentSymbolInfo = symbolsInfo[symbol];
1642
+ const maxLeverage = Math.max(currentPosition.leverage ?? 1, 1);
1643
+ const IMR_Factor = accountInfo?.imr_factor?.[symbol] ?? currentSymbolInfo.imr_factor ?? 0;
1644
+ return new Decimal(
1645
+ account.IMR({
1646
+ maxLeverage,
1647
+ baseIMR: currentSymbolInfo.base_imr ?? 0,
1648
+ IMR_Factor,
1649
+ positionNotional: notional.toNumber(),
1650
+ ordersNotional: 0
1651
+ })
1652
+ );
1653
+ }, [currentPosition, symbolsInfo, symbol, notional, accountInfo]);
1654
+ const maxAmount = useMemo(() => {
1655
+ if (isAdd) {
1656
+ if (!freeCollateralUSDCOnly) return null;
1657
+ return Math.max(0, freeCollateralUSDCOnly);
1658
+ }
1659
+ if (!imr || !notional || isolatedMargin === void 0 || isolatedMargin === null || !currentPosition) {
1660
+ return null;
1661
+ }
1662
+ const positionNotional = notional;
1663
+ const imrValue = imr;
1664
+ const unsettledPnlValue = unSettledPnl ?? 0;
1665
+ return account.maxReduce({
1666
+ isolatedPositionMargin: isolatedMargin,
1667
+ positionNotional: positionNotional.toNumber(),
1668
+ imr: imrValue.toNumber(),
1669
+ positionUnsettledPnL: unsettledPnlValue
1670
+ });
1671
+ }, [
1672
+ total_cross_unsettled_pnl,
1673
+ usdcHolding,
1674
+ isAdd,
1675
+ freeCollateral,
1676
+ unSettledPnl,
1677
+ isolatedMargin
1678
+ ]);
1679
+ const liquidationPrice = useMemo(() => {
1680
+ if (!totalUnsettlementPnl || !currentPosition || !symbolsInfo?.[symbol] || !accountInfo?.imr_factor) {
1681
+ return null;
1682
+ }
1683
+ const currentSymbolInfo = symbolsInfo[symbol];
1684
+ const currentPositionNotional = notional?.toNumber() ?? 0;
1685
+ const currentPositionIMRFactor = accountInfo.imr_factor[symbol] ?? currentSymbolInfo.imr_factor ?? 0;
1686
+ positions.MMR({
1687
+ baseMMR: currentSymbolInfo.base_mmr ?? 0,
1688
+ baseIMR: currentSymbolInfo.base_imr ?? 0,
1689
+ IMRFactor: currentPositionIMRFactor,
1690
+ positionNotional: currentPositionNotional,
1691
+ IMR_factor_power: 4 / 5
1692
+ });
1693
+ positions2?.filter((item) => item.symbol !== symbol).map((item) => {
1694
+ const itemSymbolInfo = symbolsInfo[item.symbol];
1695
+ const itemIMRFactor = accountInfo.imr_factor[item.symbol] ?? itemSymbolInfo?.imr_factor ?? 0;
1696
+ const itemNotional = item.notional ?? new Decimal(item.position_qty).mul(item.mark_price).abs().toNumber();
1697
+ const itemMMR = item.mmr ?? positions.MMR({
1698
+ baseMMR: itemSymbolInfo?.base_mmr ?? 0,
1699
+ baseIMR: itemSymbolInfo?.base_imr ?? 0,
1700
+ IMRFactor: itemIMRFactor,
1701
+ positionNotional: itemNotional,
1702
+ IMR_factor_power: 4 / 5
1703
+ });
1704
+ return {
1705
+ symbol: item.symbol,
1706
+ position_qty: item.position_qty,
1707
+ mark_price: item.mark_price,
1708
+ mmr: itemMMR
1709
+ };
1710
+ }) ?? [];
1711
+ new Decimal(finalMargin).add(currentPosition.unsettled_pnl ?? 0).toNumber();
1712
+ const sumUnitaryFunding = fundingRates?.[symbol]?.sum_unitary_funding ?? 0;
1713
+ const liqPrice = positions.liquidationPriceIsolated({
1714
+ isolatedPositionMargin: finalMargin,
1715
+ costPosition: currentPosition.cost_position ?? 0,
1716
+ positionQty: currentPosition.position_qty ?? 0,
1717
+ sumUnitaryFunding,
1718
+ lastSumUnitaryFunding: currentPosition.last_sum_unitary_funding ?? 0,
1719
+ baseMMR: currentSymbolInfo.base_mmr ?? 0,
1720
+ baseIMR: currentSymbolInfo.base_imr ?? 0,
1721
+ IMRFactor: currentPositionIMRFactor,
1722
+ referencePrice: markPrice,
1723
+ leverage: currentPosition.leverage ?? 0
1724
+ });
1725
+ return liqPrice;
1726
+ }, [
1727
+ totalUnsettlementPnl,
1728
+ currentPosition,
1729
+ symbolsInfo,
1730
+ symbol,
1731
+ accountInfo,
1732
+ notional,
1733
+ positions2,
1734
+ finalMargin,
1735
+ markPrice
1736
+ ]);
1737
+ const total_collateral_value = useMemo(() => {
1738
+ if (!unSettledPnl) return null;
1739
+ return new Decimal(finalMargin).add(unSettledPnl).toNumber();
1740
+ }, [unSettledPnl, finalMargin]);
1741
+ const effectiveLeverage = useMemo(() => {
1742
+ if (!notional || !total_collateral_value) return null;
1743
+ return notional.div(total_collateral_value).toNumber();
1744
+ }, [notional, total_collateral_value]);
1745
+ return {
1746
+ maxAmount,
1747
+ liquidationPrice,
1748
+ effectiveLeverage
1749
+ };
1750
+ };
1751
+ var usePositionMargin_default = usePositionMargin;
1752
+
1753
+ // src/components/positions/adjustMargin/adjustMargin.script.tsx
1754
+ var useAdjustMarginScript = (props) => {
1755
+ const { position, symbol, close } = props;
1756
+ const { t } = useTranslation();
1757
+ const [tab, setTab] = useState("add");
1758
+ const [inputValue, setInputValue] = useState("");
1759
+ const [sliderValue, setSliderValue] = useState(0);
1760
+ const [updateMargin, { isMutating: isLoading }] = useMutation(
1761
+ "/v1/position_margin",
1762
+ "POST"
1763
+ );
1764
+ const isAdd = useMemo(() => {
1765
+ return tab === "add";
1766
+ }, [tab]);
1767
+ const currentMargin = position.margin ?? 0;
1768
+ const finalMargin = useMemo(() => {
1769
+ const delta = new Decimal(inputValue || 0);
1770
+ if (tab === "add") return currentMargin + delta.toNumber();
1771
+ return currentMargin - delta.toNumber();
1772
+ }, [currentMargin, inputValue, tab]);
1773
+ const { maxAmount, liquidationPrice, effectiveLeverage } = usePositionMargin_default(
1774
+ symbol,
1775
+ isAdd,
1776
+ currentMargin,
1777
+ finalMargin
1778
+ );
1779
+ const syncSliderFromInput = useCallback(
1780
+ (value) => {
1781
+ if (!value) {
1782
+ setSliderValue(0);
1783
+ return;
1784
+ }
1785
+ if (!maxAmount) return;
1786
+ const val = new Decimal(value);
1787
+ if (maxAmount === 0) {
1788
+ setSliderValue(0);
1789
+ return;
1790
+ }
1791
+ const percent = val.div(maxAmount).mul(100).toNumber();
1792
+ setSliderValue(Math.min(100, Math.max(0, percent)));
1793
+ },
1794
+ [maxAmount]
1795
+ );
1796
+ const syncInputFromSlider = useCallback(
1797
+ (value) => {
1798
+ if (!maxAmount) return;
1799
+ const val = new Decimal(maxAmount).mul(value).div(100);
1800
+ setInputValue(val.toFixed(2, Decimal.ROUND_DOWN));
1801
+ },
1802
+ [maxAmount]
1803
+ );
1804
+ const onInputChange = useCallback(
1805
+ (value) => {
1806
+ let finalValue = value;
1807
+ if (maxAmount && value) {
1808
+ const inputDecimal = new Decimal(value);
1809
+ if (inputDecimal.gt(maxAmount)) {
1810
+ finalValue = new Decimal(maxAmount).toFixed(2, Decimal.ROUND_DOWN);
1811
+ }
1812
+ }
1813
+ setInputValue(finalValue);
1814
+ syncSliderFromInput(finalValue);
1815
+ },
1816
+ [syncSliderFromInput, maxAmount]
1817
+ );
1818
+ const onSliderChange = useCallback(
1819
+ (value) => {
1820
+ setSliderValue(value);
1821
+ syncInputFromSlider(value);
1822
+ },
1823
+ [syncInputFromSlider]
1824
+ );
1825
+ const onTabChange = useCallback((nextTab) => {
1826
+ setTab(nextTab);
1827
+ setInputValue("");
1828
+ setSliderValue(0);
1829
+ }, []);
1830
+ const canConfirm = useMemo(() => {
1831
+ if (!inputValue) return false;
1832
+ const value = new Decimal(inputValue);
1833
+ return !value.isZero() && value.isPositive();
1834
+ }, [inputValue]);
1835
+ const onConfirm = useCallback(async () => {
1836
+ if (!inputValue || new Decimal(inputValue).isZero()) return;
1837
+ if (maxAmount) {
1838
+ const inputDecimal = new Decimal(inputValue);
1839
+ if (inputDecimal.gt(maxAmount)) {
1840
+ toast.error(t("positions.adjustMargin.marginCannotMoreThanMax"));
1841
+ return;
1842
+ }
1843
+ }
1844
+ try {
1845
+ const payload = {
1846
+ symbol,
1847
+ amount: new Decimal(inputValue).toString(),
1848
+ type: tab === "add" ? "ADD" : "REDUCE"
1849
+ };
1850
+ const response = await updateMargin(payload);
1851
+ if (!response?.success) {
1852
+ toast.error(response?.message || t("positions.adjustMargin.failed"));
1853
+ return;
1854
+ }
1855
+ toast.success(t("positions.adjustMargin.success"));
1856
+ close();
1857
+ } catch (error) {
1858
+ const message = error instanceof Error ? error.message : void 0;
1859
+ toast.error(message || t("positions.adjustMargin.failed"));
1860
+ }
1861
+ }, [close, inputValue, symbol, t, tab, updateMargin, maxAmount]);
1862
+ return {
1863
+ symbol,
1864
+ tab,
1865
+ inputValue,
1866
+ sliderValue,
1867
+ maxAmount: maxAmount ?? 0,
1868
+ currentMargin,
1869
+ liquidationPrice,
1870
+ effectiveLeverage: effectiveLeverage ?? 0,
1871
+ isLoading,
1872
+ isAdd,
1873
+ canConfirm,
1874
+ onTabChange,
1875
+ onInputChange,
1876
+ onSliderChange,
1877
+ onConfirm,
1878
+ close
1879
+ };
1880
+ };
1881
+ var Footer = (props) => {
1882
+ const { t } = useTranslation();
1883
+ return /* @__PURE__ */ jsxs(Flex, { gap: 3, className: "oui-w-full oui-pt-5", children: [
1884
+ /* @__PURE__ */ jsx(
1885
+ Button,
1886
+ {
1887
+ variant: "contained",
1888
+ fullWidth: true,
1889
+ size: "lg",
1890
+ color: "secondary",
1891
+ className: "oui-h-10",
1892
+ onClick: props.close,
1893
+ children: t("common.cancel")
1894
+ }
1895
+ ),
1896
+ /* @__PURE__ */ jsx(
1897
+ Button,
1898
+ {
1899
+ variant: "contained",
1900
+ color: "primary",
1901
+ fullWidth: true,
1902
+ size: "lg",
1903
+ className: "oui-h-10",
1904
+ loading: props.isLoading,
1905
+ disabled: !props.canConfirm,
1906
+ onClick: props.onConfirm,
1907
+ children: t("common.confirm")
1908
+ }
1909
+ )
1910
+ ] });
1911
+ };
1912
+ var fotter_default = Footer;
1913
+ var Infos = ({
1914
+ currentMargin,
1915
+ liquidationPrice,
1916
+ effectiveLeverage
1917
+ }) => {
1918
+ const { t } = useTranslation();
1919
+ return /* @__PURE__ */ jsxs(
1920
+ Flex,
1921
+ {
1922
+ direction: "column",
1923
+ gap: 1,
1924
+ className: "oui-w-full oui-rounded-[6px] oui-bg-base-6 oui-p-3 oui-text-2xs oui-font-semibold",
1925
+ children: [
1926
+ /* @__PURE__ */ jsx(
1927
+ Statistic,
1928
+ {
1929
+ label: t("positions.adjustMargin.currentMargin"),
1930
+ valueProps: { dp: 2, unit: " USDC", padding: false },
1931
+ classNames: {
1932
+ root: "oui-flex-row oui-justify-between oui-items-center oui-w-full oui-text-2xs oui-h-5",
1933
+ label: "oui-text-2xs"
1934
+ },
1935
+ children: currentMargin
1936
+ }
1937
+ ),
1938
+ /* @__PURE__ */ jsx(
1939
+ Statistic,
1940
+ {
1941
+ label: t("positions.adjustMargin.liqPriceAfter"),
1942
+ valueProps: { dp: 2, unit: " USDC", padding: false },
1943
+ classNames: {
1944
+ root: "oui-flex-row oui-justify-between oui-items-center oui-w-full oui-text-2xs oui-h-5",
1945
+ label: "oui-text-2xs"
1946
+ },
1947
+ children: liquidationPrice ?? "--"
1948
+ }
1949
+ ),
1950
+ /* @__PURE__ */ jsx(
1951
+ Statistic,
1952
+ {
1953
+ label: t("positions.adjustMargin.leverageAfter"),
1954
+ valueProps: { dp: 2, unit: " x" },
1955
+ classNames: {
1956
+ root: "oui-flex-row oui-justify-between oui-items-center oui-w-full oui-text-2xs oui-h-5",
1957
+ label: "oui-text-2xs"
1958
+ },
1959
+ children: effectiveLeverage ?? "--"
1960
+ }
1961
+ )
1962
+ ]
1963
+ }
1964
+ );
1965
+ };
1966
+ var MarginActions = ({
1967
+ isAdd,
1968
+ onTabChange
1969
+ }) => {
1970
+ const { t } = useTranslation();
1971
+ const tabBase = "oui-h-7 oui-rounded-[4px] oui-text-xs oui-font-semibold oui-transition-colors";
1972
+ return /* @__PURE__ */ jsxs(Flex, { className: "oui-w-full oui-gap-[6px]", children: [
1973
+ /* @__PURE__ */ jsx(
1974
+ Button,
1975
+ {
1976
+ size: "md",
1977
+ fullWidth: true,
1978
+ variant: "contained",
1979
+ color: "secondary",
1980
+ className: cn(
1981
+ tabBase,
1982
+ isAdd && "oui-bg-base-5 oui-text-base-contrast-98",
1983
+ !isAdd && "oui-bg-base-7 oui-text-base-contrast-54 hover:oui-text-base-contrast-80"
1984
+ ),
1985
+ onClick: () => onTabChange("add"),
1986
+ children: t("positions.adjustMargin.add")
1987
+ }
1988
+ ),
1989
+ /* @__PURE__ */ jsx(
1990
+ Button,
1991
+ {
1992
+ size: "sm",
1993
+ fullWidth: true,
1994
+ variant: "contained",
1995
+ color: "secondary",
1996
+ className: cn(
1997
+ tabBase,
1998
+ !isAdd && "oui-bg-base-5 oui-text-base-contrast-98 hover:oui-text-base-contrast-80",
1999
+ isAdd && "oui-bg-base-7 oui-text-base-contrast-54 hover:oui-text-base-contrast-80"
2000
+ ),
2001
+ onClick: () => onTabChange("reduce"),
2002
+ children: t("positions.adjustMargin.reduce")
2003
+ }
2004
+ )
2005
+ ] });
2006
+ };
2007
+ var Quantity = ({
2008
+ inputValue,
2009
+ sliderValue,
2010
+ maxAmount,
2011
+ onInputChange,
2012
+ onSliderChange
2013
+ }) => {
2014
+ const { t } = useTranslation();
2015
+ const percentMarks = useMemo(
2016
+ () => [0, 25, 50, 75, 100].map((m) => ({ value: m, label: `${m}%` })),
2017
+ []
2018
+ );
2019
+ const isMaxClickable = maxAmount > 0;
2020
+ const handleSetToMax = useCallback(() => {
2021
+ if (!isMaxClickable) return;
2022
+ onSliderChange(100);
2023
+ }, [isMaxClickable, onSliderChange]);
2024
+ const handleKeyDown = useCallback(
2025
+ (e) => {
2026
+ if (e.key === "Enter" || e.key === " ") {
2027
+ e.preventDefault();
2028
+ handleSetToMax();
2029
+ }
2030
+ },
2031
+ [handleSetToMax]
2032
+ );
2033
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, className: "oui-w-full", children: [
2034
+ /* @__PURE__ */ jsx(
2035
+ Input,
2036
+ {
2037
+ value: inputValue,
2038
+ onValueChange: onInputChange,
2039
+ type: "text",
2040
+ fullWidth: true,
2041
+ size: "lg",
2042
+ align: "right",
2043
+ prefix: t("positions.adjustMargin.quantity"),
2044
+ suffix: "USDC",
2045
+ formatters: [
2046
+ inputFormatter.numberFormatter,
2047
+ inputFormatter.dpFormatter(2)
2048
+ ],
2049
+ disabled: maxAmount === null || maxAmount <= 0,
2050
+ autoComplete: "off",
2051
+ classNames: {
2052
+ // Keep border color stable and remove focus ring (Input has focus-within:outline-primary-light by default)
2053
+ root: "oui-rounded-[6px] oui-bg-base-6 oui-border oui-border-solid oui-border-white/[0.12] oui-outline oui-outline-1 oui-outline-offset-0 oui-outline-transparent focus-within:oui-outline-transparent",
2054
+ // keep value aligned to suffix side and match design emphasis
2055
+ input: "oui-text-sm oui-font-semibold oui-text-base-contrast-98",
2056
+ // override default additional padding so value can sit closer to suffix
2057
+ additional: "oui-px-0",
2058
+ prefix: "oui-pl-3 oui-pr-2 oui-text-sm oui-text-base-contrast-54",
2059
+ suffix: "oui-pl-2 oui-pr-3 oui-text-sm oui-text-base-contrast-54"
2060
+ }
2061
+ }
2062
+ ),
2063
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, className: "oui-w-full", children: [
2064
+ /* @__PURE__ */ jsx(
2065
+ Slider,
2066
+ {
2067
+ value: [sliderValue],
2068
+ onValueChange: (val) => onSliderChange(val[0]),
2069
+ max: 100,
2070
+ min: 0,
2071
+ step: 1,
2072
+ color: "primary",
2073
+ showTip: true,
2074
+ tipFormatter: (v, _min, _max, percent) => `${percent.toFixed(0)}%`,
2075
+ marks: percentMarks,
2076
+ markLabelVisible: false,
2077
+ disabled: maxAmount === null || maxAmount <= 0
2078
+ }
2079
+ ),
2080
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-w-full", children: [
2081
+ /* @__PURE__ */ jsx(Text, { size: "2xs", className: "oui-text-primary", children: `${sliderValue.toFixed(0)}%` }),
2082
+ /* @__PURE__ */ jsxs(
2083
+ Flex,
2084
+ {
2085
+ gap: 1,
2086
+ itemAlign: "baseline",
2087
+ role: isMaxClickable ? "button" : void 0,
2088
+ tabIndex: isMaxClickable ? 0 : void 0,
2089
+ onClick: isMaxClickable ? handleSetToMax : void 0,
2090
+ onKeyDown: isMaxClickable ? handleKeyDown : void 0,
2091
+ className: isMaxClickable ? "oui-cursor-pointer oui-opacity-90 hover:oui-opacity-100" : void 0,
2092
+ children: [
2093
+ /* @__PURE__ */ jsx(Text, { size: "2xs", className: "oui-text-primary", children: t("positions.adjustMargin.max") }),
2094
+ /* @__PURE__ */ jsx(Text.numeral, { size: "2xs", intensity: 54, dp: 2, children: maxAmount })
2095
+ ]
2096
+ }
2097
+ )
2098
+ ] })
2099
+ ] })
2100
+ ] });
2101
+ };
2102
+ var SymbolInfo = ({ symbol }) => {
2103
+ return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-items-center oui-gap-2", children: [
2104
+ /* @__PURE__ */ jsx(TokenIcon, { symbol, className: "oui-size-5" }),
2105
+ /* @__PURE__ */ jsx(
2106
+ Text.formatted,
2107
+ {
2108
+ rule: "symbol",
2109
+ formatString: "base-type",
2110
+ size: "base",
2111
+ weight: "semibold",
2112
+ intensity: 98,
2113
+ children: symbol
2114
+ }
2115
+ )
2116
+ ] });
2117
+ };
2118
+ var Title = ({ close }) => {
2119
+ const { t } = useTranslation();
2120
+ return /* @__PURE__ */ jsxs("div", { className: "oui-w-full", children: [
2121
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", itemAlign: "center", children: [
2122
+ /* @__PURE__ */ jsx(
2123
+ Text,
2124
+ {
2125
+ className: "oui-text-base oui-leading-6 oui-font-semibold oui-tracking-[0.48px]",
2126
+ intensity: 98,
2127
+ children: t("positions.adjustMargin.title")
2128
+ }
2129
+ ),
2130
+ /* @__PURE__ */ jsx(IconButton, { onClick: close, color: "secondary", children: /* @__PURE__ */ jsx(CloseIcon, { size: 18, color: "white", opacity: 0.98 }) })
2131
+ ] }),
2132
+ /* @__PURE__ */ jsx(Divider, { className: "oui-mt-[9px] oui-w-full" })
2133
+ ] });
2134
+ };
2135
+ var title_default = Title;
2136
+ var AdjustMargin = (props) => {
2137
+ const {
2138
+ symbol,
2139
+ inputValue,
2140
+ sliderValue,
2141
+ maxAmount,
2142
+ currentMargin,
2143
+ liquidationPrice,
2144
+ effectiveLeverage,
2145
+ onTabChange,
2146
+ onInputChange,
2147
+ onSliderChange,
2148
+ close,
2149
+ isAdd
2150
+ } = props;
2151
+ return /* @__PURE__ */ jsxs(
2152
+ Flex,
2153
+ {
2154
+ direction: "column",
2155
+ className: "oui-w-full oui-rounded-[12px] oui-bg-base-8 oui-font-semibold",
2156
+ children: [
2157
+ /* @__PURE__ */ jsx(title_default, { close }),
2158
+ /* @__PURE__ */ jsxs("div", { className: "oui-w-full oui-pt-5", children: [
2159
+ /* @__PURE__ */ jsx(SymbolInfo, { symbol }),
2160
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, className: "oui-mt-4 oui-w-full", children: [
2161
+ /* @__PURE__ */ jsx(MarginActions, { isAdd, onTabChange }),
2162
+ /* @__PURE__ */ jsx(
2163
+ Quantity,
2164
+ {
2165
+ inputValue,
2166
+ sliderValue,
2167
+ maxAmount,
2168
+ onInputChange,
2169
+ onSliderChange
2170
+ }
2171
+ ),
2172
+ /* @__PURE__ */ jsx(
2173
+ Infos,
2174
+ {
2175
+ currentMargin,
2176
+ liquidationPrice,
2177
+ effectiveLeverage
2178
+ }
2179
+ )
2180
+ ] })
2181
+ ] }),
2182
+ /* @__PURE__ */ jsx(fotter_default, { ...props })
2183
+ ]
2184
+ }
2185
+ );
2186
+ };
2187
+ var AdjustMarginDialogId = "AdjustMarginDialog";
2188
+ var AdjustMarginSheetId = "AdjustMarginSheet";
2189
+ var AdjustMarginWidget = (props) => {
2190
+ const { isMobile } = useScreen();
2191
+ const state = useAdjustMarginScript({
2192
+ position: props.position,
2193
+ symbol: props.symbol,
2194
+ close: () => modal.hide(isMobile ? AdjustMarginSheetId : AdjustMarginDialogId)
2195
+ });
2196
+ return /* @__PURE__ */ jsx(AdjustMargin, { ...state });
2197
+ };
2198
+ registerSimpleDialog(AdjustMarginDialogId, AdjustMarginWidget, {
2199
+ title: void 0,
2200
+ closable: false,
2201
+ size: "sm"
2202
+ });
2203
+ registerSimpleSheet(AdjustMarginSheetId, AdjustMarginWidget, {
2204
+ title: void 0,
2205
+ closable: false
2206
+ });
1601
2207
  var QuantitySlider = (props) => {
1602
2208
  const { t } = useTranslation();
1603
2209
  const [sliderValue, setSliderValue] = useState(props.value);
@@ -2254,29 +2860,59 @@ var AddIcon = (props) => {
2254
2860
  );
2255
2861
  };
2256
2862
  var LeverageBadge = (props) => {
2257
- const { symbol, leverage } = props;
2863
+ const { symbol, leverage, marginMode } = props;
2864
+ const { t } = useTranslation();
2865
+ const resolvedMarginMode = marginMode;
2258
2866
  const showModal = () => {
2259
2867
  modal.show(props.modalId, {
2260
2868
  symbol,
2261
- curLeverage: Number(leverage)
2869
+ curLeverage: leverage,
2870
+ marginMode: resolvedMarginMode
2262
2871
  });
2263
2872
  };
2264
- return /* @__PURE__ */ jsx(
2265
- "div",
2266
- {
2267
- className: cn(
2268
- "oui-flex oui-h-[18px] oui-items-center oui-gap-1",
2269
- "oui-cursor-pointer oui-rounded oui-bg-line-6 oui-px-2",
2270
- "oui-text-2xs oui-font-semibold oui-text-base-contrast-36"
2271
- ),
2272
- onClick: showModal,
2273
- children: leverage ? /* @__PURE__ */ jsx(Text.numeral, { dp: 0, rm: Decimal.ROUND_DOWN, size: "2xs", unit: "X", children: leverage }) : /* @__PURE__ */ jsx(LeverageDisplay, { symbol })
2274
- }
2275
- );
2873
+ return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-items-center oui-gap-1", children: [
2874
+ /* @__PURE__ */ jsx(
2875
+ "div",
2876
+ {
2877
+ className: cn(
2878
+ "oui-flex oui-h-[18px] oui-items-center",
2879
+ "oui-rounded oui-bg-line-6 oui-px-2",
2880
+ "oui-text-2xs oui-font-semibold oui-text-base-contrast-36"
2881
+ ),
2882
+ children: /* @__PURE__ */ jsx(Text, { children: resolvedMarginMode === void 0 ? "--" : resolvedMarginMode === MarginMode.ISOLATED ? t("marginMode.isolated") : t("marginMode.cross") })
2883
+ }
2884
+ ),
2885
+ /* @__PURE__ */ jsxs(
2886
+ "div",
2887
+ {
2888
+ className: cn(
2889
+ "oui-flex oui-h-[18px] oui-items-center oui-gap-1",
2890
+ "oui-rounded oui-bg-line-6 oui-px-2",
2891
+ "oui-text-2xs oui-font-semibold oui-text-base-contrast-36",
2892
+ "oui-cursor-pointer"
2893
+ ),
2894
+ onClick: showModal,
2895
+ children: [
2896
+ leverage === void 0 ? /* @__PURE__ */ jsx(LeverageDisplay, { symbol, marginMode }) : /* @__PURE__ */ jsx(Text.numeral, { dp: 0, rm: Decimal.ROUND_DOWN, size: "2xs", unit: "X", children: leverage }),
2897
+ /* @__PURE__ */ jsx(
2898
+ ChevronRightIcon,
2899
+ {
2900
+ size: 12,
2901
+ className: "oui-text-base-contrast-36",
2902
+ opacity: 1
2903
+ }
2904
+ )
2905
+ ]
2906
+ }
2907
+ )
2908
+ ] });
2276
2909
  };
2277
- var LeverageDisplay = ({ symbol }) => {
2278
- const leverage = useLeverageBySymbol(symbol);
2279
- return /* @__PURE__ */ jsx(Text.numeral, { dp: 0, rm: Decimal.ROUND_DOWN, size: "2xs", unit: "X", children: leverage || 1 });
2910
+ var LeverageDisplay = ({
2911
+ symbol,
2912
+ marginMode
2913
+ }) => {
2914
+ const leverage = useLeverageBySymbol(symbol, marginMode);
2915
+ return /* @__PURE__ */ jsx(Fragment, { children: leverage === void 0 ? /* @__PURE__ */ jsx(Text, { size: "2xs", children: "--" }) : /* @__PURE__ */ jsx(Text.numeral, { dp: 0, rm: Decimal.ROUND_DOWN, size: "2xs", unit: "X", children: leverage }) });
2280
2916
  };
2281
2917
  var renderQuantity = (value) => {
2282
2918
  const symbolInfo = useSymbolContext();
@@ -2430,11 +3066,13 @@ var useShareButtonScript = (props) => {
2430
3066
  const { position, sharePnLConfig, iconSize } = props;
2431
3067
  const { getFirstRefCode } = useReferralInfo();
2432
3068
  const symbolsInfo = useSymbolsInfo();
2433
- const { data: accountInfo } = useAccountInfo();
2434
3069
  const refCode = useMemo(() => {
2435
3070
  return getFirstRefCode()?.code;
2436
3071
  }, [getFirstRefCode]);
2437
- const symbolLeverage = useLeverageBySymbol(position.symbol);
3072
+ const symbolLeverage = useLeverageBySymbol(
3073
+ position.symbol,
3074
+ position.margin_mode ?? MarginMode.CROSS
3075
+ );
2438
3076
  const getHistoryEntity = () => {
2439
3077
  const netPnL = position.netPnL || 0;
2440
3078
  const openPrice = Math.abs(position.avg_open_price);
@@ -2443,10 +3081,22 @@ var useShareButtonScript = (props) => {
2443
3081
  const symbolInfo = symbolsInfo[position.symbol];
2444
3082
  const baseIMR = symbolInfo("base_imr");
2445
3083
  const IMR_Factor = symbolInfo("imr_factor");
2446
- if (netPnL !== 0 && quantity !== 0 && openPrice !== 0 && accountInfo?.max_leverage && baseIMR && // IMR_Factor is possible to be 0
3084
+ if (netPnL !== 0 && quantity !== 0 && openPrice !== 0 && baseIMR && // IMR_Factor is possible to be 0
2447
3085
  typeof IMR_Factor !== "undefined") {
2448
3086
  const notional = positions.notional(quantity, openPrice);
2449
- const maxLeverage = position.leverage ? position.leverage : accountInfo.max_leverage;
3087
+ const maxLeverage = position.leverage || symbolLeverage;
3088
+ if (!maxLeverage) {
3089
+ return {
3090
+ side: position.side,
3091
+ pnl: netPnL,
3092
+ roi,
3093
+ openPrice,
3094
+ closePrice: Math.abs(position.avg_close_price),
3095
+ openTime: position.open_timestamp,
3096
+ closeTime: position.close_timestamp,
3097
+ quantity: position.closed_position_qty
3098
+ };
3099
+ }
2450
3100
  const imr = account.IMR({
2451
3101
  maxLeverage,
2452
3102
  baseIMR,
@@ -2490,7 +3140,8 @@ var useShareButtonScript = (props) => {
2490
3140
  symbol: position.symbol,
2491
3141
  // when position.leverage is empty, use leverage from useSymbolLeverage
2492
3142
  leverage: position.leverage || symbolLeverage,
2493
- ...entity
3143
+ ...entity,
3144
+ marginMode: position.margin_mode
2494
3145
  },
2495
3146
  refCode,
2496
3147
  ...sharePnLConfig
@@ -2805,7 +3456,7 @@ var useColumn = (config) => {
2805
3456
  positionReverse
2806
3457
  } = config;
2807
3458
  const { t } = useTranslation();
2808
- useRef(Date.now().toString());
3459
+ const { isMobile } = useScreen();
2809
3460
  const column = useMemo(
2810
3461
  () => [
2811
3462
  {
@@ -2848,7 +3499,8 @@ var useColumn = (config) => {
2848
3499
  {
2849
3500
  symbol: value,
2850
3501
  leverage: record.leverage,
2851
- modalId: SymbolLeverageDialogId
3502
+ modalId: SymbolLeverageDialogId,
3503
+ marginMode: record.margin_mode
2852
3504
  }
2853
3505
  ),
2854
3506
  /* @__PURE__ */ jsx(RwaStatusTag, { symbol: value })
@@ -3037,17 +3689,13 @@ var useColumn = (config) => {
3037
3689
  Tooltip,
3038
3690
  {
3039
3691
  className: "oui-max-w-[280px] oui-bg-base-8 oui-p-3 oui-text-2xs oui-text-base-contrast-54",
3040
- content: /* @__PURE__ */ jsxs(
3692
+ content: /* @__PURE__ */ jsx(
3041
3693
  Flex,
3042
3694
  {
3043
3695
  direction: "column",
3044
3696
  gap: 3,
3045
3697
  className: "oui-rounded-sm oui-bg-base-8 oui-text-base-contrast-54",
3046
- children: [
3047
- /* @__PURE__ */ jsx("span", { children: t("positions.column.margin.tooltip") }),
3048
- /* @__PURE__ */ jsx(Divider, { className: "oui-w-full" }),
3049
- /* @__PURE__ */ jsx("span", { children: t("positions.column.margin.formula") })
3050
- ]
3698
+ children: /* @__PURE__ */ jsx("span", { children: t("positions.column.margin.tooltip") })
3051
3699
  }
3052
3700
  ),
3053
3701
  children: /* @__PURE__ */ jsx(Text, { className: "oui-underline oui-decoration-dotted", children: t("positions.column.margin") })
@@ -3057,7 +3705,26 @@ var useColumn = (config) => {
3057
3705
  onSort: true,
3058
3706
  width: 140,
3059
3707
  rule: "price",
3060
- render: (value) => /* @__PURE__ */ jsx(Text.numeral, { children: value })
3708
+ render: (value, record) => {
3709
+ const isIsolated = record.margin_mode === "ISOLATED";
3710
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, itemAlign: "center", children: [
3711
+ /* @__PURE__ */ jsx(Text.numeral, { children: isIsolated ? record.margin ?? "--" : "--" }),
3712
+ isIsolated && /* @__PURE__ */ jsx(
3713
+ IconButton,
3714
+ {
3715
+ color: "secondary",
3716
+ onClick: (e) => {
3717
+ e.stopPropagation();
3718
+ modal.show(AdjustMarginDialogId, {
3719
+ position: record,
3720
+ symbol: record.symbol
3721
+ });
3722
+ },
3723
+ children: /* @__PURE__ */ jsx(AddCircleIcon, { size: 16, fill: "currentColor", opacity: 1 })
3724
+ }
3725
+ )
3726
+ ] });
3727
+ }
3061
3728
  },
3062
3729
  // {
3063
3730
  // title: t("funding.fundingFee"),
@@ -3122,7 +3789,8 @@ var SymbolToken = (props) => {
3122
3789
  {
3123
3790
  symbol: item.symbol,
3124
3791
  leverage: item.leverage,
3125
- modalId: SymbolLeverageSheetId
3792
+ modalId: SymbolLeverageSheetId,
3793
+ marginMode: item.margin_mode
3126
3794
  }
3127
3795
  )
3128
3796
  ] }),
@@ -3205,11 +3873,8 @@ var Qty = (props) => {
3205
3873
  var Margin = (props) => {
3206
3874
  const { item } = props;
3207
3875
  const { t } = useTranslation();
3208
- const marginTipsContent = /* @__PURE__ */ jsxs("div", { className: "oui-text-2xs oui-text-base-contrast-80", children: [
3209
- /* @__PURE__ */ jsx("div", { children: t("positions.column.margin.tooltip") }),
3210
- /* @__PURE__ */ jsx("div", { className: "oui-my-2 oui-h-px oui-w-full oui-bg-base-8" }),
3211
- /* @__PURE__ */ jsx("div", { children: t("positions.column.margin.formula") })
3212
- ] });
3876
+ const isIsolated = item.margin_mode === "ISOLATED";
3877
+ const marginTipsContent = /* @__PURE__ */ jsx("div", { className: "oui-text-2xs oui-text-base-contrast-80", children: /* @__PURE__ */ jsx("div", { children: t("positions.column.margin.tooltip") }) });
3213
3878
  const marginLabel = /* @__PURE__ */ jsx(Text, { className: "oui-underline oui-decoration-dotted", children: t("positions.column.margin") });
3214
3879
  return /* @__PURE__ */ jsx(
3215
3880
  Statistic,
@@ -3226,7 +3891,23 @@ var Margin = (props) => {
3226
3891
  root: "oui-text-xs",
3227
3892
  label: "oui-text-2xs"
3228
3893
  },
3229
- children: /* @__PURE__ */ jsx(Text.numeral, { dp: 2, intensity: 80, children: item.mm })
3894
+ children: /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
3895
+ /* @__PURE__ */ jsx(Text.numeral, { dp: 2, intensity: 80, children: isIsolated ? item.margin ?? "--" : "--" }),
3896
+ isIsolated && /* @__PURE__ */ jsx(
3897
+ IconButton,
3898
+ {
3899
+ color: "secondary",
3900
+ onClick: (e) => {
3901
+ e.stopPropagation();
3902
+ modal.show(AdjustMarginSheetId, {
3903
+ position: item,
3904
+ symbol: item.symbol
3905
+ });
3906
+ },
3907
+ children: /* @__PURE__ */ jsx(AddCircleIcon, { size: 16, fill: "currentColor", opacity: 1 })
3908
+ }
3909
+ )
3910
+ ] })
3230
3911
  }
3231
3912
  );
3232
3913
  };
@@ -3631,7 +4312,7 @@ var Positions = (props) => {
3631
4312
  columns,
3632
4313
  bordered: true,
3633
4314
  dataSource,
3634
- generatedRowKey: (record) => record.symbol,
4315
+ generatedRowKey: (record, index) => `${record.symbol}-${index}`,
3635
4316
  renderRowContainer: (record, index, children) => {
3636
4317
  return /* @__PURE__ */ jsx(SymbolProvider, { symbol: record.symbol, children: /* @__PURE__ */ jsx(PositionsRowProvider, { position: record, children }) });
3637
4318
  },
@@ -3703,7 +4384,7 @@ var CombinePositions = (props) => {
3703
4384
  dataSource,
3704
4385
  expanded: true,
3705
4386
  getSubRows: (row) => row.children,
3706
- generatedRowKey: (record) => `${record.account_id}${record.symbol || ""}`,
4387
+ generatedRowKey: (record, index) => `${record.account_id}${record.symbol || ""}-${index}`,
3707
4388
  onCell: (column, record) => {
3708
4389
  const isGroup = (record.children ?? []).length > 0;
3709
4390
  if (isGroup) {
@@ -3762,14 +4443,14 @@ var usePositionHistoryColumn = (props) => {
3762
4443
  onSort: (r1, r2) => {
3763
4444
  return r1.symbol?.localeCompare(r2.symbol || "");
3764
4445
  },
3765
- render: (value, record) => /* @__PURE__ */ jsx(SymbolInfo, { record, onSymbolChange })
4446
+ render: (value, record) => /* @__PURE__ */ jsx(SymbolInfo2, { record, onSymbolChange })
3766
4447
  },
3767
4448
  // quantity
3768
4449
  {
3769
4450
  title: t("positions.history.column.closed&maxClosed"),
3770
4451
  dataIndex: "close_maxClose",
3771
4452
  width: 200,
3772
- render: (value, record) => /* @__PURE__ */ jsx(Quantity, { record })
4453
+ render: (value, record) => /* @__PURE__ */ jsx(Quantity2, { record })
3773
4454
  },
3774
4455
  // net pnl
3775
4456
  {
@@ -3877,7 +4558,7 @@ var usePositionHistoryColumn = (props) => {
3877
4558
  );
3878
4559
  return column;
3879
4560
  };
3880
- var SymbolInfo = (props) => {
4561
+ var SymbolInfo2 = (props) => {
3881
4562
  const { record, onSymbolChange } = props;
3882
4563
  const { t } = useTranslation();
3883
4564
  const tags = useMemo(() => {
@@ -3991,7 +4672,7 @@ var SymbolInfo = (props) => {
3991
4672
  ] })
3992
4673
  ] });
3993
4674
  };
3994
- var Quantity = (props) => {
4675
+ var Quantity2 = (props) => {
3995
4676
  const { record } = props;
3996
4677
  const { base_dp } = useSymbolContext();
3997
4678
  return /* @__PURE__ */ jsxs(
@@ -4124,6 +4805,8 @@ var usePositionHistoryScript = (props) => {
4124
4805
  const netPnL = item.realized_pnl - item.accumulated_funding_fee - item.trading_fee;
4125
4806
  return {
4126
4807
  ...item,
4808
+ // convert margin_mode to MarginMode
4809
+ margin_mode: item.margin_mode === 1 || item.margin_mode === MarginMode.ISOLATED ? MarginMode.ISOLATED : MarginMode.CROSS,
4127
4810
  netPnL
4128
4811
  };
4129
4812
  }
@@ -4737,7 +5420,7 @@ var PositionHistory = (props) => {
4737
5420
  columns: column,
4738
5421
  bordered: true,
4739
5422
  dataSource: props.dataSource,
4740
- generatedRowKey: (record) => `${record.symbol}_${record.position_id}`,
5423
+ generatedRowKey: (record, index) => `${record.symbol}_${record.position_id}_${index}`,
4741
5424
  renderRowContainer: (record, index, children) => /* @__PURE__ */ jsx(SymbolProvider, { symbol: record.symbol, children }),
4742
5425
  manualPagination: false,
4743
5426
  pagination,
@@ -5530,7 +6213,8 @@ var useCloseAllPositionsScript = (options) => {
5530
6213
  order_type: OrderType.MARKET,
5531
6214
  side,
5532
6215
  order_quantity: quantity,
5533
- reduce_only: true
6216
+ reduce_only: true,
6217
+ margin_mode: position.margin_mode
5534
6218
  };
5535
6219
  }),
5536
6220
  []