@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.js CHANGED
@@ -598,7 +598,7 @@ var calculatePositions = (positions2, symbolsInfo, accountInfo, tpslOrders) => {
598
598
  return positions2.map((item) => {
599
599
  const info = symbolsInfo[item.symbol];
600
600
  const notional = perp.positions.notional(item.position_qty, item.mark_price);
601
- const account2 = accountInfo.find(
601
+ const account3 = accountInfo.find(
602
602
  (acc) => acc.account_id === item.account_id
603
603
  );
604
604
  const baseMMR = info?.("base_mmr");
@@ -609,7 +609,7 @@ var calculatePositions = (positions2, symbolsInfo, accountInfo, tpslOrders) => {
609
609
  const MMR = perp.positions.MMR({
610
610
  baseMMR,
611
611
  baseIMR,
612
- IMRFactor: account2?.imr_factor[item.symbol] ?? 0,
612
+ IMRFactor: account3?.imr_factor[item.symbol] ?? 0,
613
613
  positionNotional: notional,
614
614
  IMR_factor_power: 4 / 5
615
615
  });
@@ -627,7 +627,7 @@ var calculatePositions = (positions2, symbolsInfo, accountInfo, tpslOrders) => {
627
627
  const imr = perp.account.IMR({
628
628
  maxLeverage,
629
629
  baseIMR,
630
- IMR_Factor: account2?.imr_factor[item.symbol] ?? 0,
630
+ IMR_Factor: account3?.imr_factor[item.symbol] ?? 0,
631
631
  positionNotional: notional,
632
632
  ordersNotional: 0,
633
633
  IMR_factor_power: 4 / 5
@@ -656,7 +656,7 @@ var calculatePositions = (positions2, symbolsInfo, accountInfo, tpslOrders) => {
656
656
  const filteredTPSLOrders = tpslOrders.filter(
657
657
  (tpslOrder) => tpslOrder.account_id === item.account_id
658
658
  );
659
- const tpsl = formatTPSL(filteredTPSLOrders, item.symbol);
659
+ const tpsl = formatTPSL(filteredTPSLOrders, item.symbol, item.margin_mode);
660
660
  return {
661
661
  ...item,
662
662
  ...tpsl,
@@ -669,9 +669,9 @@ var calculatePositions = (positions2, symbolsInfo, accountInfo, tpslOrders) => {
669
669
  };
670
670
  });
671
671
  };
672
- function formatTPSL(tpslOrders, symbol) {
672
+ function formatTPSL(tpslOrders, symbol, marginMode) {
673
673
  if (Array.isArray(tpslOrders) && tpslOrders.length) {
674
- const { fullPositionOrder, partialPositionOrders } = hooks.findPositionTPSLFromOrders(tpslOrders, symbol);
674
+ const { fullPositionOrder, partialPositionOrders } = hooks.findPositionTPSLFromOrders(tpslOrders, symbol, marginMode);
675
675
  const full_tp_sl = fullPositionOrder ? hooks.findTPSLFromOrder(fullPositionOrder) : void 0;
676
676
  const partialPossitionOrder = partialPositionOrders && partialPositionOrders.length ? partialPositionOrders[0] : void 0;
677
677
  const partial_tp_sl = partialPossitionOrder ? hooks.findTPSLFromOrder(partialPossitionOrder) : void 0;
@@ -690,7 +690,7 @@ function formatTPSL(tpslOrders, symbol) {
690
690
  };
691
691
  }
692
692
  }
693
- var signatureMiddleware = (account2, accountId) => {
693
+ var signatureMiddleware = (account3, accountId) => {
694
694
  const apiBaseUrl = hooks.useConfig("apiBaseUrl");
695
695
  return (useSWRNext) => {
696
696
  return (key, fetcher2, config) => {
@@ -698,7 +698,7 @@ var signatureMiddleware = (account2, accountId) => {
698
698
  const extendedFetcher = async (args) => {
699
699
  const url = Array.isArray(args) ? args[0] : args;
700
700
  const fullUrl = `${apiBaseUrl}${url}`;
701
- const signer = account2.signer;
701
+ const signer = account3.signer;
702
702
  const payload = { method: "GET", url };
703
703
  const signature = await signer.sign(payload, utils.getTimestamp());
704
704
  const ids = Array.isArray(accountId) ? accountId : [accountId];
@@ -722,7 +722,7 @@ var signatureMiddleware = (account2, accountId) => {
722
722
  };
723
723
  var useSubAccountQuery = (query, options) => {
724
724
  const { formatter, accountId, ...swrOptions } = options || {};
725
- const { state, account: account2 } = hooks.useAccount();
725
+ const { state, account: account3 } = hooks.useAccount();
726
726
  const middleware = Array.isArray(options?.use) ? options?.use ?? [] : [];
727
727
  const ids = Array.isArray(accountId) ? accountId : [accountId];
728
728
  const shouldFetch = ids.filter(Boolean).length && (state.status >= types.AccountStatusEnum.EnableTrading || state.status === types.AccountStatusEnum.EnableTradingWithoutConnected);
@@ -733,7 +733,7 @@ var useSubAccountQuery = (query, options) => {
733
733
  },
734
734
  {
735
735
  ...swrOptions,
736
- use: [...middleware, signatureMiddleware(account2, ids)],
736
+ use: [...middleware, signatureMiddleware(account3, ids)],
737
737
  onError: () => {
738
738
  }
739
739
  }
@@ -1268,7 +1268,9 @@ var useReversePositionScript = (options) => {
1268
1268
  order_type: types.OrderType.MARKET,
1269
1269
  side,
1270
1270
  order_quantity: new utils.Decimal(qty).todp(baseDp).toString(),
1271
- reduce_only: reduceOnly
1271
+ reduce_only: reduceOnly,
1272
+ // Use position's margin_mode or default to CROSS for backward compatibility
1273
+ margin_mode: position.margin_mode || types.MarginMode.CROSS
1272
1274
  };
1273
1275
  };
1274
1276
  const closeSide = isLong ? types.OrderSide.SELL : types.OrderSide.BUY;
@@ -1604,6 +1606,610 @@ var RwaStatusTag = ({ symbol }) => {
1604
1606
  }
1605
1607
  );
1606
1608
  };
1609
+ var usePositionMargin = (symbol, isAdd, isolatedMargin, finalMargin) => {
1610
+ const { freeCollateral, freeCollateralUSDCOnly, usdcHolding } = hooks.useCollateral(
1611
+ {
1612
+ dp: 2
1613
+ }
1614
+ );
1615
+ const positions2 = hooks.usePositions();
1616
+ const total_cross_unsettled_pnl = React2.useMemo(() => {
1617
+ return positions2?.filter((item) => (item.margin_mode ?? "CROSS") === "CROSS").reduce((acc, item) => acc.add(item.unsettled_pnl), new utils.Decimal(0));
1618
+ }, [positions2]);
1619
+ const fundingRates = hooks.useAppStore((state) => state.fundingRates);
1620
+ const symbolsInfo = hooks.useAppStore((state) => state.symbolsInfo);
1621
+ const accountInfo = hooks.useAppStore((state) => state.accountInfo);
1622
+ const { data: markPrice } = hooks.useMarkPrice(symbol);
1623
+ const totalUnsettlementPnl = React2.useMemo(() => {
1624
+ if (!positions2?.length) {
1625
+ return null;
1626
+ }
1627
+ return positions2.reduce((acc, item) => {
1628
+ const itemAny = item;
1629
+ const positionUnsettlementPnl = itemAny["unsettlement_pnl"] ?? item.unsettled_pnl ?? 0;
1630
+ return acc.add(positionUnsettlementPnl);
1631
+ }, new utils.Decimal(0));
1632
+ }, [positions2]);
1633
+ const currentPosition = React2.useMemo(() => {
1634
+ return positions2?.find(
1635
+ (item) => item.symbol === symbol && item.margin_mode === types.MarginMode.ISOLATED
1636
+ );
1637
+ }, [positions2]);
1638
+ const notional = React2.useMemo(() => {
1639
+ if (!currentPosition) return null;
1640
+ return new utils.Decimal(currentPosition.notional);
1641
+ }, [currentPosition]);
1642
+ const unSettledPnl = currentPosition?.unsettled_pnl;
1643
+ const imr = React2.useMemo(() => {
1644
+ if (!currentPosition || !symbolsInfo?.[symbol] || !notional) {
1645
+ return null;
1646
+ }
1647
+ const currentSymbolInfo = symbolsInfo[symbol];
1648
+ const maxLeverage = Math.max(currentPosition.leverage ?? 1, 1);
1649
+ const IMR_Factor = accountInfo?.imr_factor?.[symbol] ?? currentSymbolInfo.imr_factor ?? 0;
1650
+ return new utils.Decimal(
1651
+ perp.account.IMR({
1652
+ maxLeverage,
1653
+ baseIMR: currentSymbolInfo.base_imr ?? 0,
1654
+ IMR_Factor,
1655
+ positionNotional: notional.toNumber(),
1656
+ ordersNotional: 0
1657
+ })
1658
+ );
1659
+ }, [currentPosition, symbolsInfo, symbol, notional, accountInfo]);
1660
+ const maxAmount = React2.useMemo(() => {
1661
+ if (isAdd) {
1662
+ if (!freeCollateralUSDCOnly) return null;
1663
+ return Math.max(0, freeCollateralUSDCOnly);
1664
+ }
1665
+ if (!imr || !notional || isolatedMargin === void 0 || isolatedMargin === null || !currentPosition) {
1666
+ return null;
1667
+ }
1668
+ const positionNotional = notional;
1669
+ const imrValue = imr;
1670
+ const unsettledPnlValue = unSettledPnl ?? 0;
1671
+ return perp.account.maxReduce({
1672
+ isolatedPositionMargin: isolatedMargin,
1673
+ positionNotional: positionNotional.toNumber(),
1674
+ imr: imrValue.toNumber(),
1675
+ positionUnsettledPnL: unsettledPnlValue
1676
+ });
1677
+ }, [
1678
+ total_cross_unsettled_pnl,
1679
+ usdcHolding,
1680
+ isAdd,
1681
+ freeCollateral,
1682
+ unSettledPnl,
1683
+ isolatedMargin
1684
+ ]);
1685
+ const liquidationPrice = React2.useMemo(() => {
1686
+ if (!totalUnsettlementPnl || !currentPosition || !symbolsInfo?.[symbol] || !accountInfo?.imr_factor) {
1687
+ return null;
1688
+ }
1689
+ const currentSymbolInfo = symbolsInfo[symbol];
1690
+ const currentPositionNotional = notional?.toNumber() ?? 0;
1691
+ const currentPositionIMRFactor = accountInfo.imr_factor[symbol] ?? currentSymbolInfo.imr_factor ?? 0;
1692
+ perp.positions.MMR({
1693
+ baseMMR: currentSymbolInfo.base_mmr ?? 0,
1694
+ baseIMR: currentSymbolInfo.base_imr ?? 0,
1695
+ IMRFactor: currentPositionIMRFactor,
1696
+ positionNotional: currentPositionNotional,
1697
+ IMR_factor_power: 4 / 5
1698
+ });
1699
+ positions2?.filter((item) => item.symbol !== symbol).map((item) => {
1700
+ const itemSymbolInfo = symbolsInfo[item.symbol];
1701
+ const itemIMRFactor = accountInfo.imr_factor[item.symbol] ?? itemSymbolInfo?.imr_factor ?? 0;
1702
+ const itemNotional = item.notional ?? new utils.Decimal(item.position_qty).mul(item.mark_price).abs().toNumber();
1703
+ const itemMMR = item.mmr ?? perp.positions.MMR({
1704
+ baseMMR: itemSymbolInfo?.base_mmr ?? 0,
1705
+ baseIMR: itemSymbolInfo?.base_imr ?? 0,
1706
+ IMRFactor: itemIMRFactor,
1707
+ positionNotional: itemNotional,
1708
+ IMR_factor_power: 4 / 5
1709
+ });
1710
+ return {
1711
+ symbol: item.symbol,
1712
+ position_qty: item.position_qty,
1713
+ mark_price: item.mark_price,
1714
+ mmr: itemMMR
1715
+ };
1716
+ }) ?? [];
1717
+ new utils.Decimal(finalMargin).add(currentPosition.unsettled_pnl ?? 0).toNumber();
1718
+ const sumUnitaryFunding = fundingRates?.[symbol]?.sum_unitary_funding ?? 0;
1719
+ const liqPrice = perp.positions.liquidationPriceIsolated({
1720
+ isolatedPositionMargin: finalMargin,
1721
+ costPosition: currentPosition.cost_position ?? 0,
1722
+ positionQty: currentPosition.position_qty ?? 0,
1723
+ sumUnitaryFunding,
1724
+ lastSumUnitaryFunding: currentPosition.last_sum_unitary_funding ?? 0,
1725
+ baseMMR: currentSymbolInfo.base_mmr ?? 0,
1726
+ baseIMR: currentSymbolInfo.base_imr ?? 0,
1727
+ IMRFactor: currentPositionIMRFactor,
1728
+ referencePrice: markPrice,
1729
+ leverage: currentPosition.leverage ?? 0
1730
+ });
1731
+ return liqPrice;
1732
+ }, [
1733
+ totalUnsettlementPnl,
1734
+ currentPosition,
1735
+ symbolsInfo,
1736
+ symbol,
1737
+ accountInfo,
1738
+ notional,
1739
+ positions2,
1740
+ finalMargin,
1741
+ markPrice
1742
+ ]);
1743
+ const total_collateral_value = React2.useMemo(() => {
1744
+ if (!unSettledPnl) return null;
1745
+ return new utils.Decimal(finalMargin).add(unSettledPnl).toNumber();
1746
+ }, [unSettledPnl, finalMargin]);
1747
+ const effectiveLeverage = React2.useMemo(() => {
1748
+ if (!notional || !total_collateral_value) return null;
1749
+ return notional.div(total_collateral_value).toNumber();
1750
+ }, [notional, total_collateral_value]);
1751
+ return {
1752
+ maxAmount,
1753
+ liquidationPrice,
1754
+ effectiveLeverage
1755
+ };
1756
+ };
1757
+ var usePositionMargin_default = usePositionMargin;
1758
+
1759
+ // src/components/positions/adjustMargin/adjustMargin.script.tsx
1760
+ var useAdjustMarginScript = (props) => {
1761
+ const { position, symbol, close } = props;
1762
+ const { t } = i18n.useTranslation();
1763
+ const [tab, setTab] = React2.useState("add");
1764
+ const [inputValue, setInputValue] = React2.useState("");
1765
+ const [sliderValue, setSliderValue] = React2.useState(0);
1766
+ const [updateMargin, { isMutating: isLoading }] = hooks.useMutation(
1767
+ "/v1/position_margin",
1768
+ "POST"
1769
+ );
1770
+ const isAdd = React2.useMemo(() => {
1771
+ return tab === "add";
1772
+ }, [tab]);
1773
+ const currentMargin = position.margin ?? 0;
1774
+ const finalMargin = React2.useMemo(() => {
1775
+ const delta = new utils.Decimal(inputValue || 0);
1776
+ if (tab === "add") return currentMargin + delta.toNumber();
1777
+ return currentMargin - delta.toNumber();
1778
+ }, [currentMargin, inputValue, tab]);
1779
+ const { maxAmount, liquidationPrice, effectiveLeverage } = usePositionMargin_default(
1780
+ symbol,
1781
+ isAdd,
1782
+ currentMargin,
1783
+ finalMargin
1784
+ );
1785
+ const syncSliderFromInput = React2.useCallback(
1786
+ (value) => {
1787
+ if (!value) {
1788
+ setSliderValue(0);
1789
+ return;
1790
+ }
1791
+ if (!maxAmount) return;
1792
+ const val = new utils.Decimal(value);
1793
+ if (maxAmount === 0) {
1794
+ setSliderValue(0);
1795
+ return;
1796
+ }
1797
+ const percent = val.div(maxAmount).mul(100).toNumber();
1798
+ setSliderValue(Math.min(100, Math.max(0, percent)));
1799
+ },
1800
+ [maxAmount]
1801
+ );
1802
+ const syncInputFromSlider = React2.useCallback(
1803
+ (value) => {
1804
+ if (!maxAmount) return;
1805
+ const val = new utils.Decimal(maxAmount).mul(value).div(100);
1806
+ setInputValue(val.toFixed(2, utils.Decimal.ROUND_DOWN));
1807
+ },
1808
+ [maxAmount]
1809
+ );
1810
+ const onInputChange = React2.useCallback(
1811
+ (value) => {
1812
+ let finalValue = value;
1813
+ if (maxAmount && value) {
1814
+ const inputDecimal = new utils.Decimal(value);
1815
+ if (inputDecimal.gt(maxAmount)) {
1816
+ finalValue = new utils.Decimal(maxAmount).toFixed(2, utils.Decimal.ROUND_DOWN);
1817
+ }
1818
+ }
1819
+ setInputValue(finalValue);
1820
+ syncSliderFromInput(finalValue);
1821
+ },
1822
+ [syncSliderFromInput, maxAmount]
1823
+ );
1824
+ const onSliderChange = React2.useCallback(
1825
+ (value) => {
1826
+ setSliderValue(value);
1827
+ syncInputFromSlider(value);
1828
+ },
1829
+ [syncInputFromSlider]
1830
+ );
1831
+ const onTabChange = React2.useCallback((nextTab) => {
1832
+ setTab(nextTab);
1833
+ setInputValue("");
1834
+ setSliderValue(0);
1835
+ }, []);
1836
+ const canConfirm = React2.useMemo(() => {
1837
+ if (!inputValue) return false;
1838
+ const value = new utils.Decimal(inputValue);
1839
+ return !value.isZero() && value.isPositive();
1840
+ }, [inputValue]);
1841
+ const onConfirm = React2.useCallback(async () => {
1842
+ if (!inputValue || new utils.Decimal(inputValue).isZero()) return;
1843
+ if (maxAmount) {
1844
+ const inputDecimal = new utils.Decimal(inputValue);
1845
+ if (inputDecimal.gt(maxAmount)) {
1846
+ ui.toast.error(t("positions.adjustMargin.marginCannotMoreThanMax"));
1847
+ return;
1848
+ }
1849
+ }
1850
+ try {
1851
+ const payload = {
1852
+ symbol,
1853
+ amount: new utils.Decimal(inputValue).toString(),
1854
+ type: tab === "add" ? "ADD" : "REDUCE"
1855
+ };
1856
+ const response = await updateMargin(payload);
1857
+ if (!response?.success) {
1858
+ ui.toast.error(response?.message || t("positions.adjustMargin.failed"));
1859
+ return;
1860
+ }
1861
+ ui.toast.success(t("positions.adjustMargin.success"));
1862
+ close();
1863
+ } catch (error) {
1864
+ const message = error instanceof Error ? error.message : void 0;
1865
+ ui.toast.error(message || t("positions.adjustMargin.failed"));
1866
+ }
1867
+ }, [close, inputValue, symbol, t, tab, updateMargin, maxAmount]);
1868
+ return {
1869
+ symbol,
1870
+ tab,
1871
+ inputValue,
1872
+ sliderValue,
1873
+ maxAmount: maxAmount ?? 0,
1874
+ currentMargin,
1875
+ liquidationPrice,
1876
+ effectiveLeverage: effectiveLeverage ?? 0,
1877
+ isLoading,
1878
+ isAdd,
1879
+ canConfirm,
1880
+ onTabChange,
1881
+ onInputChange,
1882
+ onSliderChange,
1883
+ onConfirm,
1884
+ close
1885
+ };
1886
+ };
1887
+ var Footer = (props) => {
1888
+ const { t } = i18n.useTranslation();
1889
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gap: 3, className: "oui-w-full oui-pt-5", children: [
1890
+ /* @__PURE__ */ jsxRuntime.jsx(
1891
+ ui.Button,
1892
+ {
1893
+ variant: "contained",
1894
+ fullWidth: true,
1895
+ size: "lg",
1896
+ color: "secondary",
1897
+ className: "oui-h-10",
1898
+ onClick: props.close,
1899
+ children: t("common.cancel")
1900
+ }
1901
+ ),
1902
+ /* @__PURE__ */ jsxRuntime.jsx(
1903
+ ui.Button,
1904
+ {
1905
+ variant: "contained",
1906
+ color: "primary",
1907
+ fullWidth: true,
1908
+ size: "lg",
1909
+ className: "oui-h-10",
1910
+ loading: props.isLoading,
1911
+ disabled: !props.canConfirm,
1912
+ onClick: props.onConfirm,
1913
+ children: t("common.confirm")
1914
+ }
1915
+ )
1916
+ ] });
1917
+ };
1918
+ var fotter_default = Footer;
1919
+ var Infos = ({
1920
+ currentMargin,
1921
+ liquidationPrice,
1922
+ effectiveLeverage
1923
+ }) => {
1924
+ const { t } = i18n.useTranslation();
1925
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1926
+ ui.Flex,
1927
+ {
1928
+ direction: "column",
1929
+ gap: 1,
1930
+ className: "oui-w-full oui-rounded-[6px] oui-bg-base-6 oui-p-3 oui-text-2xs oui-font-semibold",
1931
+ children: [
1932
+ /* @__PURE__ */ jsxRuntime.jsx(
1933
+ ui.Statistic,
1934
+ {
1935
+ label: t("positions.adjustMargin.currentMargin"),
1936
+ valueProps: { dp: 2, unit: " USDC", padding: false },
1937
+ classNames: {
1938
+ root: "oui-flex-row oui-justify-between oui-items-center oui-w-full oui-text-2xs oui-h-5",
1939
+ label: "oui-text-2xs"
1940
+ },
1941
+ children: currentMargin
1942
+ }
1943
+ ),
1944
+ /* @__PURE__ */ jsxRuntime.jsx(
1945
+ ui.Statistic,
1946
+ {
1947
+ label: t("positions.adjustMargin.liqPriceAfter"),
1948
+ valueProps: { dp: 2, unit: " USDC", padding: false },
1949
+ classNames: {
1950
+ root: "oui-flex-row oui-justify-between oui-items-center oui-w-full oui-text-2xs oui-h-5",
1951
+ label: "oui-text-2xs"
1952
+ },
1953
+ children: liquidationPrice ?? "--"
1954
+ }
1955
+ ),
1956
+ /* @__PURE__ */ jsxRuntime.jsx(
1957
+ ui.Statistic,
1958
+ {
1959
+ label: t("positions.adjustMargin.leverageAfter"),
1960
+ valueProps: { dp: 2, unit: " x" },
1961
+ classNames: {
1962
+ root: "oui-flex-row oui-justify-between oui-items-center oui-w-full oui-text-2xs oui-h-5",
1963
+ label: "oui-text-2xs"
1964
+ },
1965
+ children: effectiveLeverage ?? "--"
1966
+ }
1967
+ )
1968
+ ]
1969
+ }
1970
+ );
1971
+ };
1972
+ var MarginActions = ({
1973
+ isAdd,
1974
+ onTabChange
1975
+ }) => {
1976
+ const { t } = i18n.useTranslation();
1977
+ const tabBase = "oui-h-7 oui-rounded-[4px] oui-text-xs oui-font-semibold oui-transition-colors";
1978
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { className: "oui-w-full oui-gap-[6px]", children: [
1979
+ /* @__PURE__ */ jsxRuntime.jsx(
1980
+ ui.Button,
1981
+ {
1982
+ size: "md",
1983
+ fullWidth: true,
1984
+ variant: "contained",
1985
+ color: "secondary",
1986
+ className: ui.cn(
1987
+ tabBase,
1988
+ isAdd && "oui-bg-base-5 oui-text-base-contrast-98",
1989
+ !isAdd && "oui-bg-base-7 oui-text-base-contrast-54 hover:oui-text-base-contrast-80"
1990
+ ),
1991
+ onClick: () => onTabChange("add"),
1992
+ children: t("positions.adjustMargin.add")
1993
+ }
1994
+ ),
1995
+ /* @__PURE__ */ jsxRuntime.jsx(
1996
+ ui.Button,
1997
+ {
1998
+ size: "sm",
1999
+ fullWidth: true,
2000
+ variant: "contained",
2001
+ color: "secondary",
2002
+ className: ui.cn(
2003
+ tabBase,
2004
+ !isAdd && "oui-bg-base-5 oui-text-base-contrast-98 hover:oui-text-base-contrast-80",
2005
+ isAdd && "oui-bg-base-7 oui-text-base-contrast-54 hover:oui-text-base-contrast-80"
2006
+ ),
2007
+ onClick: () => onTabChange("reduce"),
2008
+ children: t("positions.adjustMargin.reduce")
2009
+ }
2010
+ )
2011
+ ] });
2012
+ };
2013
+ var Quantity = ({
2014
+ inputValue,
2015
+ sliderValue,
2016
+ maxAmount,
2017
+ onInputChange,
2018
+ onSliderChange
2019
+ }) => {
2020
+ const { t } = i18n.useTranslation();
2021
+ const percentMarks = React2.useMemo(
2022
+ () => [0, 25, 50, 75, 100].map((m) => ({ value: m, label: `${m}%` })),
2023
+ []
2024
+ );
2025
+ const isMaxClickable = maxAmount > 0;
2026
+ const handleSetToMax = React2.useCallback(() => {
2027
+ if (!isMaxClickable) return;
2028
+ onSliderChange(100);
2029
+ }, [isMaxClickable, onSliderChange]);
2030
+ const handleKeyDown = React2.useCallback(
2031
+ (e) => {
2032
+ if (e.key === "Enter" || e.key === " ") {
2033
+ e.preventDefault();
2034
+ handleSetToMax();
2035
+ }
2036
+ },
2037
+ [handleSetToMax]
2038
+ );
2039
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "column", gap: 3, className: "oui-w-full", children: [
2040
+ /* @__PURE__ */ jsxRuntime.jsx(
2041
+ ui.Input,
2042
+ {
2043
+ value: inputValue,
2044
+ onValueChange: onInputChange,
2045
+ type: "text",
2046
+ fullWidth: true,
2047
+ size: "lg",
2048
+ align: "right",
2049
+ prefix: t("positions.adjustMargin.quantity"),
2050
+ suffix: "USDC",
2051
+ formatters: [
2052
+ ui.inputFormatter.numberFormatter,
2053
+ ui.inputFormatter.dpFormatter(2)
2054
+ ],
2055
+ disabled: maxAmount === null || maxAmount <= 0,
2056
+ autoComplete: "off",
2057
+ classNames: {
2058
+ // Keep border color stable and remove focus ring (Input has focus-within:outline-primary-light by default)
2059
+ 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",
2060
+ // keep value aligned to suffix side and match design emphasis
2061
+ input: "oui-text-sm oui-font-semibold oui-text-base-contrast-98",
2062
+ // override default additional padding so value can sit closer to suffix
2063
+ additional: "oui-px-0",
2064
+ prefix: "oui-pl-3 oui-pr-2 oui-text-sm oui-text-base-contrast-54",
2065
+ suffix: "oui-pl-2 oui-pr-3 oui-text-sm oui-text-base-contrast-54"
2066
+ }
2067
+ }
2068
+ ),
2069
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "column", gap: 2, className: "oui-w-full", children: [
2070
+ /* @__PURE__ */ jsxRuntime.jsx(
2071
+ ui.Slider,
2072
+ {
2073
+ value: [sliderValue],
2074
+ onValueChange: (val) => onSliderChange(val[0]),
2075
+ max: 100,
2076
+ min: 0,
2077
+ step: 1,
2078
+ color: "primary",
2079
+ showTip: true,
2080
+ tipFormatter: (v, _min, _max, percent) => `${percent.toFixed(0)}%`,
2081
+ marks: percentMarks,
2082
+ markLabelVisible: false,
2083
+ disabled: maxAmount === null || maxAmount <= 0
2084
+ }
2085
+ ),
2086
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "between", className: "oui-w-full", children: [
2087
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "2xs", className: "oui-text-primary", children: `${sliderValue.toFixed(0)}%` }),
2088
+ /* @__PURE__ */ jsxRuntime.jsxs(
2089
+ ui.Flex,
2090
+ {
2091
+ gap: 1,
2092
+ itemAlign: "baseline",
2093
+ role: isMaxClickable ? "button" : void 0,
2094
+ tabIndex: isMaxClickable ? 0 : void 0,
2095
+ onClick: isMaxClickable ? handleSetToMax : void 0,
2096
+ onKeyDown: isMaxClickable ? handleKeyDown : void 0,
2097
+ className: isMaxClickable ? "oui-cursor-pointer oui-opacity-90 hover:oui-opacity-100" : void 0,
2098
+ children: [
2099
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "2xs", className: "oui-text-primary", children: t("positions.adjustMargin.max") }),
2100
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { size: "2xs", intensity: 54, dp: 2, children: maxAmount })
2101
+ ]
2102
+ }
2103
+ )
2104
+ ] })
2105
+ ] })
2106
+ ] });
2107
+ };
2108
+ var SymbolInfo = ({ symbol }) => {
2109
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oui-flex oui-items-center oui-gap-2", children: [
2110
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TokenIcon, { symbol, className: "oui-size-5" }),
2111
+ /* @__PURE__ */ jsxRuntime.jsx(
2112
+ ui.Text.formatted,
2113
+ {
2114
+ rule: "symbol",
2115
+ formatString: "base-type",
2116
+ size: "base",
2117
+ weight: "semibold",
2118
+ intensity: 98,
2119
+ children: symbol
2120
+ }
2121
+ )
2122
+ ] });
2123
+ };
2124
+ var Title = ({ close }) => {
2125
+ const { t } = i18n.useTranslation();
2126
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oui-w-full", children: [
2127
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "between", itemAlign: "center", children: [
2128
+ /* @__PURE__ */ jsxRuntime.jsx(
2129
+ ui.Text,
2130
+ {
2131
+ className: "oui-text-base oui-leading-6 oui-font-semibold oui-tracking-[0.48px]",
2132
+ intensity: 98,
2133
+ children: t("positions.adjustMargin.title")
2134
+ }
2135
+ ),
2136
+ /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: close, color: "secondary", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CloseIcon, { size: 18, color: "white", opacity: 0.98 }) })
2137
+ ] }),
2138
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { className: "oui-mt-[9px] oui-w-full" })
2139
+ ] });
2140
+ };
2141
+ var title_default = Title;
2142
+ var AdjustMargin = (props) => {
2143
+ const {
2144
+ symbol,
2145
+ inputValue,
2146
+ sliderValue,
2147
+ maxAmount,
2148
+ currentMargin,
2149
+ liquidationPrice,
2150
+ effectiveLeverage,
2151
+ onTabChange,
2152
+ onInputChange,
2153
+ onSliderChange,
2154
+ close,
2155
+ isAdd
2156
+ } = props;
2157
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2158
+ ui.Flex,
2159
+ {
2160
+ direction: "column",
2161
+ className: "oui-w-full oui-rounded-[12px] oui-bg-base-8 oui-font-semibold",
2162
+ children: [
2163
+ /* @__PURE__ */ jsxRuntime.jsx(title_default, { close }),
2164
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oui-w-full oui-pt-5", children: [
2165
+ /* @__PURE__ */ jsxRuntime.jsx(SymbolInfo, { symbol }),
2166
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "column", gap: 4, className: "oui-mt-4 oui-w-full", children: [
2167
+ /* @__PURE__ */ jsxRuntime.jsx(MarginActions, { isAdd, onTabChange }),
2168
+ /* @__PURE__ */ jsxRuntime.jsx(
2169
+ Quantity,
2170
+ {
2171
+ inputValue,
2172
+ sliderValue,
2173
+ maxAmount,
2174
+ onInputChange,
2175
+ onSliderChange
2176
+ }
2177
+ ),
2178
+ /* @__PURE__ */ jsxRuntime.jsx(
2179
+ Infos,
2180
+ {
2181
+ currentMargin,
2182
+ liquidationPrice,
2183
+ effectiveLeverage
2184
+ }
2185
+ )
2186
+ ] })
2187
+ ] }),
2188
+ /* @__PURE__ */ jsxRuntime.jsx(fotter_default, { ...props })
2189
+ ]
2190
+ }
2191
+ );
2192
+ };
2193
+ var AdjustMarginDialogId = "AdjustMarginDialog";
2194
+ var AdjustMarginSheetId = "AdjustMarginSheet";
2195
+ var AdjustMarginWidget = (props) => {
2196
+ const { isMobile } = ui.useScreen();
2197
+ const state = useAdjustMarginScript({
2198
+ position: props.position,
2199
+ symbol: props.symbol,
2200
+ close: () => ui.modal.hide(isMobile ? AdjustMarginSheetId : AdjustMarginDialogId)
2201
+ });
2202
+ return /* @__PURE__ */ jsxRuntime.jsx(AdjustMargin, { ...state });
2203
+ };
2204
+ ui.registerSimpleDialog(AdjustMarginDialogId, AdjustMarginWidget, {
2205
+ title: void 0,
2206
+ closable: false,
2207
+ size: "sm"
2208
+ });
2209
+ ui.registerSimpleSheet(AdjustMarginSheetId, AdjustMarginWidget, {
2210
+ title: void 0,
2211
+ closable: false
2212
+ });
1607
2213
  var QuantitySlider = (props) => {
1608
2214
  const { t } = i18n.useTranslation();
1609
2215
  const [sliderValue, setSliderValue] = React2.useState(props.value);
@@ -2260,29 +2866,59 @@ var AddIcon = (props) => {
2260
2866
  );
2261
2867
  };
2262
2868
  var LeverageBadge = (props) => {
2263
- const { symbol, leverage } = props;
2869
+ const { symbol, leverage, marginMode } = props;
2870
+ const { t } = i18n.useTranslation();
2871
+ const resolvedMarginMode = marginMode;
2264
2872
  const showModal = () => {
2265
2873
  ui.modal.show(props.modalId, {
2266
2874
  symbol,
2267
- curLeverage: Number(leverage)
2875
+ curLeverage: leverage,
2876
+ marginMode: resolvedMarginMode
2268
2877
  });
2269
2878
  };
2270
- return /* @__PURE__ */ jsxRuntime.jsx(
2271
- "div",
2272
- {
2273
- className: ui.cn(
2274
- "oui-flex oui-h-[18px] oui-items-center oui-gap-1",
2275
- "oui-cursor-pointer oui-rounded oui-bg-line-6 oui-px-2",
2276
- "oui-text-2xs oui-font-semibold oui-text-base-contrast-36"
2277
- ),
2278
- onClick: showModal,
2279
- children: leverage ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { dp: 0, rm: utils.Decimal.ROUND_DOWN, size: "2xs", unit: "X", children: leverage }) : /* @__PURE__ */ jsxRuntime.jsx(LeverageDisplay, { symbol })
2280
- }
2281
- );
2879
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oui-flex oui-items-center oui-gap-1", children: [
2880
+ /* @__PURE__ */ jsxRuntime.jsx(
2881
+ "div",
2882
+ {
2883
+ className: ui.cn(
2884
+ "oui-flex oui-h-[18px] oui-items-center",
2885
+ "oui-rounded oui-bg-line-6 oui-px-2",
2886
+ "oui-text-2xs oui-font-semibold oui-text-base-contrast-36"
2887
+ ),
2888
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: resolvedMarginMode === void 0 ? "--" : resolvedMarginMode === types.MarginMode.ISOLATED ? t("marginMode.isolated") : t("marginMode.cross") })
2889
+ }
2890
+ ),
2891
+ /* @__PURE__ */ jsxRuntime.jsxs(
2892
+ "div",
2893
+ {
2894
+ className: ui.cn(
2895
+ "oui-flex oui-h-[18px] oui-items-center oui-gap-1",
2896
+ "oui-rounded oui-bg-line-6 oui-px-2",
2897
+ "oui-text-2xs oui-font-semibold oui-text-base-contrast-36",
2898
+ "oui-cursor-pointer"
2899
+ ),
2900
+ onClick: showModal,
2901
+ children: [
2902
+ leverage === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(LeverageDisplay, { symbol, marginMode }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { dp: 0, rm: utils.Decimal.ROUND_DOWN, size: "2xs", unit: "X", children: leverage }),
2903
+ /* @__PURE__ */ jsxRuntime.jsx(
2904
+ ui.ChevronRightIcon,
2905
+ {
2906
+ size: 12,
2907
+ className: "oui-text-base-contrast-36",
2908
+ opacity: 1
2909
+ }
2910
+ )
2911
+ ]
2912
+ }
2913
+ )
2914
+ ] });
2282
2915
  };
2283
- var LeverageDisplay = ({ symbol }) => {
2284
- const leverage = hooks.useLeverageBySymbol(symbol);
2285
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { dp: 0, rm: utils.Decimal.ROUND_DOWN, size: "2xs", unit: "X", children: leverage || 1 });
2916
+ var LeverageDisplay = ({
2917
+ symbol,
2918
+ marginMode
2919
+ }) => {
2920
+ const leverage = hooks.useLeverageBySymbol(symbol, marginMode);
2921
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: leverage === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "2xs", children: "--" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { dp: 0, rm: utils.Decimal.ROUND_DOWN, size: "2xs", unit: "X", children: leverage }) });
2286
2922
  };
2287
2923
  var renderQuantity = (value) => {
2288
2924
  const symbolInfo = useSymbolContext();
@@ -2436,11 +3072,13 @@ var useShareButtonScript = (props) => {
2436
3072
  const { position, sharePnLConfig, iconSize } = props;
2437
3073
  const { getFirstRefCode } = hooks.useReferralInfo();
2438
3074
  const symbolsInfo = hooks.useSymbolsInfo();
2439
- const { data: accountInfo } = hooks.useAccountInfo();
2440
3075
  const refCode = React2.useMemo(() => {
2441
3076
  return getFirstRefCode()?.code;
2442
3077
  }, [getFirstRefCode]);
2443
- const symbolLeverage = hooks.useLeverageBySymbol(position.symbol);
3078
+ const symbolLeverage = hooks.useLeverageBySymbol(
3079
+ position.symbol,
3080
+ position.margin_mode ?? types.MarginMode.CROSS
3081
+ );
2444
3082
  const getHistoryEntity = () => {
2445
3083
  const netPnL = position.netPnL || 0;
2446
3084
  const openPrice = Math.abs(position.avg_open_price);
@@ -2449,10 +3087,22 @@ var useShareButtonScript = (props) => {
2449
3087
  const symbolInfo = symbolsInfo[position.symbol];
2450
3088
  const baseIMR = symbolInfo("base_imr");
2451
3089
  const IMR_Factor = symbolInfo("imr_factor");
2452
- if (netPnL !== 0 && quantity !== 0 && openPrice !== 0 && accountInfo?.max_leverage && baseIMR && // IMR_Factor is possible to be 0
3090
+ if (netPnL !== 0 && quantity !== 0 && openPrice !== 0 && baseIMR && // IMR_Factor is possible to be 0
2453
3091
  typeof IMR_Factor !== "undefined") {
2454
3092
  const notional = perp.positions.notional(quantity, openPrice);
2455
- const maxLeverage = position.leverage ? position.leverage : accountInfo.max_leverage;
3093
+ const maxLeverage = position.leverage || symbolLeverage;
3094
+ if (!maxLeverage) {
3095
+ return {
3096
+ side: position.side,
3097
+ pnl: netPnL,
3098
+ roi,
3099
+ openPrice,
3100
+ closePrice: Math.abs(position.avg_close_price),
3101
+ openTime: position.open_timestamp,
3102
+ closeTime: position.close_timestamp,
3103
+ quantity: position.closed_position_qty
3104
+ };
3105
+ }
2456
3106
  const imr = perp.account.IMR({
2457
3107
  maxLeverage,
2458
3108
  baseIMR,
@@ -2496,7 +3146,8 @@ var useShareButtonScript = (props) => {
2496
3146
  symbol: position.symbol,
2497
3147
  // when position.leverage is empty, use leverage from useSymbolLeverage
2498
3148
  leverage: position.leverage || symbolLeverage,
2499
- ...entity
3149
+ ...entity,
3150
+ marginMode: position.margin_mode
2500
3151
  },
2501
3152
  refCode,
2502
3153
  ...sharePnLConfig
@@ -2811,7 +3462,7 @@ var useColumn = (config) => {
2811
3462
  positionReverse
2812
3463
  } = config;
2813
3464
  const { t } = i18n.useTranslation();
2814
- React2.useRef(Date.now().toString());
3465
+ const { isMobile } = ui.useScreen();
2815
3466
  const column = React2.useMemo(
2816
3467
  () => [
2817
3468
  {
@@ -2854,7 +3505,8 @@ var useColumn = (config) => {
2854
3505
  {
2855
3506
  symbol: value,
2856
3507
  leverage: record.leverage,
2857
- modalId: uiLeverage.SymbolLeverageDialogId
3508
+ modalId: uiLeverage.SymbolLeverageDialogId,
3509
+ marginMode: record.margin_mode
2858
3510
  }
2859
3511
  ),
2860
3512
  /* @__PURE__ */ jsxRuntime.jsx(RwaStatusTag, { symbol: value })
@@ -3043,17 +3695,13 @@ var useColumn = (config) => {
3043
3695
  ui.Tooltip,
3044
3696
  {
3045
3697
  className: "oui-max-w-[280px] oui-bg-base-8 oui-p-3 oui-text-2xs oui-text-base-contrast-54",
3046
- content: /* @__PURE__ */ jsxRuntime.jsxs(
3698
+ content: /* @__PURE__ */ jsxRuntime.jsx(
3047
3699
  ui.Flex,
3048
3700
  {
3049
3701
  direction: "column",
3050
3702
  gap: 3,
3051
3703
  className: "oui-rounded-sm oui-bg-base-8 oui-text-base-contrast-54",
3052
- children: [
3053
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("positions.column.margin.tooltip") }),
3054
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { className: "oui-w-full" }),
3055
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("positions.column.margin.formula") })
3056
- ]
3704
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("positions.column.margin.tooltip") })
3057
3705
  }
3058
3706
  ),
3059
3707
  children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "oui-underline oui-decoration-dotted", children: t("positions.column.margin") })
@@ -3063,7 +3711,26 @@ var useColumn = (config) => {
3063
3711
  onSort: true,
3064
3712
  width: 140,
3065
3713
  rule: "price",
3066
- render: (value) => /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { children: value })
3714
+ render: (value, record) => {
3715
+ const isIsolated = record.margin_mode === "ISOLATED";
3716
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gap: 2, itemAlign: "center", children: [
3717
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { children: isIsolated ? record.margin ?? "--" : "--" }),
3718
+ isIsolated && /* @__PURE__ */ jsxRuntime.jsx(
3719
+ ui.IconButton,
3720
+ {
3721
+ color: "secondary",
3722
+ onClick: (e) => {
3723
+ e.stopPropagation();
3724
+ ui.modal.show(AdjustMarginDialogId, {
3725
+ position: record,
3726
+ symbol: record.symbol
3727
+ });
3728
+ },
3729
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.AddCircleIcon, { size: 16, fill: "currentColor", opacity: 1 })
3730
+ }
3731
+ )
3732
+ ] });
3733
+ }
3067
3734
  },
3068
3735
  // {
3069
3736
  // title: t("funding.fundingFee"),
@@ -3128,7 +3795,8 @@ var SymbolToken = (props) => {
3128
3795
  {
3129
3796
  symbol: item.symbol,
3130
3797
  leverage: item.leverage,
3131
- modalId: uiLeverage.SymbolLeverageSheetId
3798
+ modalId: uiLeverage.SymbolLeverageSheetId,
3799
+ marginMode: item.margin_mode
3132
3800
  }
3133
3801
  )
3134
3802
  ] }),
@@ -3211,11 +3879,8 @@ var Qty = (props) => {
3211
3879
  var Margin = (props) => {
3212
3880
  const { item } = props;
3213
3881
  const { t } = i18n.useTranslation();
3214
- const marginTipsContent = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oui-text-2xs oui-text-base-contrast-80", children: [
3215
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: t("positions.column.margin.tooltip") }),
3216
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oui-my-2 oui-h-px oui-w-full oui-bg-base-8" }),
3217
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: t("positions.column.margin.formula") })
3218
- ] });
3882
+ const isIsolated = item.margin_mode === "ISOLATED";
3883
+ const marginTipsContent = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oui-text-2xs oui-text-base-contrast-80", children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: t("positions.column.margin.tooltip") }) });
3219
3884
  const marginLabel = /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "oui-underline oui-decoration-dotted", children: t("positions.column.margin") });
3220
3885
  return /* @__PURE__ */ jsxRuntime.jsx(
3221
3886
  ui.Statistic,
@@ -3232,7 +3897,23 @@ var Margin = (props) => {
3232
3897
  root: "oui-text-xs",
3233
3898
  label: "oui-text-2xs"
3234
3899
  },
3235
- children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { dp: 2, intensity: 80, children: item.mm })
3900
+ children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gap: 1, children: [
3901
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { dp: 2, intensity: 80, children: isIsolated ? item.margin ?? "--" : "--" }),
3902
+ isIsolated && /* @__PURE__ */ jsxRuntime.jsx(
3903
+ ui.IconButton,
3904
+ {
3905
+ color: "secondary",
3906
+ onClick: (e) => {
3907
+ e.stopPropagation();
3908
+ ui.modal.show(AdjustMarginSheetId, {
3909
+ position: item,
3910
+ symbol: item.symbol
3911
+ });
3912
+ },
3913
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.AddCircleIcon, { size: 16, fill: "currentColor", opacity: 1 })
3914
+ }
3915
+ )
3916
+ ] })
3236
3917
  }
3237
3918
  );
3238
3919
  };
@@ -3637,7 +4318,7 @@ var Positions = (props) => {
3637
4318
  columns,
3638
4319
  bordered: true,
3639
4320
  dataSource,
3640
- generatedRowKey: (record) => record.symbol,
4321
+ generatedRowKey: (record, index) => `${record.symbol}-${index}`,
3641
4322
  renderRowContainer: (record, index, children) => {
3642
4323
  return /* @__PURE__ */ jsxRuntime.jsx(SymbolProvider, { symbol: record.symbol, children: /* @__PURE__ */ jsxRuntime.jsx(PositionsRowProvider, { position: record, children }) });
3643
4324
  },
@@ -3709,7 +4390,7 @@ var CombinePositions = (props) => {
3709
4390
  dataSource,
3710
4391
  expanded: true,
3711
4392
  getSubRows: (row) => row.children,
3712
- generatedRowKey: (record) => `${record.account_id}${record.symbol || ""}`,
4393
+ generatedRowKey: (record, index) => `${record.account_id}${record.symbol || ""}-${index}`,
3713
4394
  onCell: (column, record) => {
3714
4395
  const isGroup = (record.children ?? []).length > 0;
3715
4396
  if (isGroup) {
@@ -3768,14 +4449,14 @@ var usePositionHistoryColumn = (props) => {
3768
4449
  onSort: (r1, r2) => {
3769
4450
  return r1.symbol?.localeCompare(r2.symbol || "");
3770
4451
  },
3771
- render: (value, record) => /* @__PURE__ */ jsxRuntime.jsx(SymbolInfo, { record, onSymbolChange })
4452
+ render: (value, record) => /* @__PURE__ */ jsxRuntime.jsx(SymbolInfo2, { record, onSymbolChange })
3772
4453
  },
3773
4454
  // quantity
3774
4455
  {
3775
4456
  title: t("positions.history.column.closed&maxClosed"),
3776
4457
  dataIndex: "close_maxClose",
3777
4458
  width: 200,
3778
- render: (value, record) => /* @__PURE__ */ jsxRuntime.jsx(Quantity, { record })
4459
+ render: (value, record) => /* @__PURE__ */ jsxRuntime.jsx(Quantity2, { record })
3779
4460
  },
3780
4461
  // net pnl
3781
4462
  {
@@ -3883,7 +4564,7 @@ var usePositionHistoryColumn = (props) => {
3883
4564
  );
3884
4565
  return column;
3885
4566
  };
3886
- var SymbolInfo = (props) => {
4567
+ var SymbolInfo2 = (props) => {
3887
4568
  const { record, onSymbolChange } = props;
3888
4569
  const { t } = i18n.useTranslation();
3889
4570
  const tags = React2.useMemo(() => {
@@ -3997,7 +4678,7 @@ var SymbolInfo = (props) => {
3997
4678
  ] })
3998
4679
  ] });
3999
4680
  };
4000
- var Quantity = (props) => {
4681
+ var Quantity2 = (props) => {
4001
4682
  const { record } = props;
4002
4683
  const { base_dp } = useSymbolContext();
4003
4684
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -4130,6 +4811,8 @@ var usePositionHistoryScript = (props) => {
4130
4811
  const netPnL = item.realized_pnl - item.accumulated_funding_fee - item.trading_fee;
4131
4812
  return {
4132
4813
  ...item,
4814
+ // convert margin_mode to MarginMode
4815
+ margin_mode: item.margin_mode === 1 || item.margin_mode === types.MarginMode.ISOLATED ? types.MarginMode.ISOLATED : types.MarginMode.CROSS,
4133
4816
  netPnL
4134
4817
  };
4135
4818
  }
@@ -4743,7 +5426,7 @@ var PositionHistory = (props) => {
4743
5426
  columns: column,
4744
5427
  bordered: true,
4745
5428
  dataSource: props.dataSource,
4746
- generatedRowKey: (record) => `${record.symbol}_${record.position_id}`,
5429
+ generatedRowKey: (record, index) => `${record.symbol}_${record.position_id}_${index}`,
4747
5430
  renderRowContainer: (record, index, children) => /* @__PURE__ */ jsxRuntime.jsx(SymbolProvider, { symbol: record.symbol, children }),
4748
5431
  manualPagination: false,
4749
5432
  pagination,
@@ -5536,7 +6219,8 @@ var useCloseAllPositionsScript = (options) => {
5536
6219
  order_type: types.OrderType.MARKET,
5537
6220
  side,
5538
6221
  order_quantity: quantity,
5539
- reduce_only: true
6222
+ reduce_only: true,
6223
+ margin_mode: position.margin_mode
5540
6224
  };
5541
6225
  }),
5542
6226
  []