@orderly.network/ui-positions 2.10.2 → 3.0.0-beta.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 +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +750 -57
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +754 -61
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -13
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { registerSimpleDialog, useModal, SimpleDialog, Flex, Text, Badge, Divider, CloseIcon, Button, ThrottledButton,
|
|
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,
|
|
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 {
|
|
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
|
|
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:
|
|
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:
|
|
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 = (
|
|
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 =
|
|
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:
|
|
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(
|
|
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,619 @@ 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 = useMemo(() => {
|
|
1637
|
+
if (!currentPosition || !notional || !fundingRates) return null;
|
|
1638
|
+
const fundingRate = fundingRates[currentPosition.symbol];
|
|
1639
|
+
return notional.sub(new Decimal(currentPosition.cost_position)).sub(
|
|
1640
|
+
new Decimal(currentPosition.position_qty).mul(
|
|
1641
|
+
new Decimal(fundingRate.sum_unitary_funding ?? 0).sub(
|
|
1642
|
+
new Decimal(currentPosition.last_sum_unitary_funding)
|
|
1643
|
+
)
|
|
1644
|
+
)
|
|
1645
|
+
);
|
|
1646
|
+
}, [notional, currentPosition, fundingRates]);
|
|
1647
|
+
const imr = useMemo(() => {
|
|
1648
|
+
if (!currentPosition || !symbolsInfo?.[symbol] || !notional) {
|
|
1649
|
+
return null;
|
|
1650
|
+
}
|
|
1651
|
+
const currentSymbolInfo = symbolsInfo[symbol];
|
|
1652
|
+
const maxLeverage = Math.max(currentPosition.leverage ?? 1, 1);
|
|
1653
|
+
const IMR_Factor = accountInfo?.imr_factor?.[symbol] ?? currentSymbolInfo.imr_factor ?? 0;
|
|
1654
|
+
return new Decimal(
|
|
1655
|
+
account.IMR({
|
|
1656
|
+
maxLeverage,
|
|
1657
|
+
baseIMR: currentSymbolInfo.base_imr ?? 0,
|
|
1658
|
+
IMR_Factor,
|
|
1659
|
+
positionNotional: notional.toNumber(),
|
|
1660
|
+
ordersNotional: 0
|
|
1661
|
+
})
|
|
1662
|
+
);
|
|
1663
|
+
}, [currentPosition, symbolsInfo, symbol, notional, accountInfo]);
|
|
1664
|
+
const maxAmount = useMemo(() => {
|
|
1665
|
+
if (isAdd) {
|
|
1666
|
+
if (!freeCollateralUSDCOnly) return null;
|
|
1667
|
+
return Math.max(0, freeCollateralUSDCOnly);
|
|
1668
|
+
}
|
|
1669
|
+
if (!imr || !notional || isolatedMargin === void 0 || isolatedMargin === null || !currentPosition) {
|
|
1670
|
+
return null;
|
|
1671
|
+
}
|
|
1672
|
+
const positionNotional = notional;
|
|
1673
|
+
const imrValue = imr;
|
|
1674
|
+
const unsettledPnlValue = unSettledPnl ?? new Decimal(0);
|
|
1675
|
+
return account.maxReduce({
|
|
1676
|
+
isolatedPositionMargin: isolatedMargin,
|
|
1677
|
+
positionNotional: positionNotional.toNumber(),
|
|
1678
|
+
imr: imrValue.toNumber(),
|
|
1679
|
+
positionUnsettledPnL: unsettledPnlValue.toNumber()
|
|
1680
|
+
});
|
|
1681
|
+
}, [
|
|
1682
|
+
total_cross_unsettled_pnl,
|
|
1683
|
+
usdcHolding,
|
|
1684
|
+
isAdd,
|
|
1685
|
+
freeCollateral,
|
|
1686
|
+
unSettledPnl,
|
|
1687
|
+
isolatedMargin
|
|
1688
|
+
]);
|
|
1689
|
+
const liquidationPrice = useMemo(() => {
|
|
1690
|
+
if (!totalUnsettlementPnl || !currentPosition || !symbolsInfo?.[symbol] || !accountInfo?.imr_factor) {
|
|
1691
|
+
return null;
|
|
1692
|
+
}
|
|
1693
|
+
const currentSymbolInfo = symbolsInfo[symbol];
|
|
1694
|
+
const currentPositionNotional = notional?.toNumber() ?? 0;
|
|
1695
|
+
const currentPositionIMRFactor = accountInfo.imr_factor[symbol] ?? currentSymbolInfo.imr_factor ?? 0;
|
|
1696
|
+
const currentPositionMMR = positions.MMR({
|
|
1697
|
+
baseMMR: currentSymbolInfo.base_mmr ?? 0,
|
|
1698
|
+
baseIMR: currentSymbolInfo.base_imr ?? 0,
|
|
1699
|
+
IMRFactor: currentPositionIMRFactor,
|
|
1700
|
+
positionNotional: currentPositionNotional,
|
|
1701
|
+
IMR_factor_power: 4 / 5
|
|
1702
|
+
});
|
|
1703
|
+
const otherPositions = positions2?.filter((item) => item.symbol !== symbol).map((item) => {
|
|
1704
|
+
const itemSymbolInfo = symbolsInfo[item.symbol];
|
|
1705
|
+
const itemIMRFactor = accountInfo.imr_factor[item.symbol] ?? itemSymbolInfo?.imr_factor ?? 0;
|
|
1706
|
+
const itemNotional = item.notional ?? new Decimal(item.position_qty).mul(item.mark_price).abs().toNumber();
|
|
1707
|
+
const itemMMR = item.mmr ?? positions.MMR({
|
|
1708
|
+
baseMMR: itemSymbolInfo?.base_mmr ?? 0,
|
|
1709
|
+
baseIMR: itemSymbolInfo?.base_imr ?? 0,
|
|
1710
|
+
IMRFactor: itemIMRFactor,
|
|
1711
|
+
positionNotional: itemNotional,
|
|
1712
|
+
IMR_factor_power: 4 / 5
|
|
1713
|
+
});
|
|
1714
|
+
return {
|
|
1715
|
+
symbol: item.symbol,
|
|
1716
|
+
position_qty: item.position_qty,
|
|
1717
|
+
mark_price: item.mark_price,
|
|
1718
|
+
mmr: itemMMR
|
|
1719
|
+
};
|
|
1720
|
+
}) ?? [];
|
|
1721
|
+
const totalCollateral = new Decimal(finalMargin).add(currentPosition.unsettled_pnl ?? 0).toNumber();
|
|
1722
|
+
const liqPrice = positions.liqPrice({
|
|
1723
|
+
markPrice,
|
|
1724
|
+
symbol,
|
|
1725
|
+
totalCollateral,
|
|
1726
|
+
positionQty: currentPosition.position_qty,
|
|
1727
|
+
positions: otherPositions,
|
|
1728
|
+
MMR: currentPositionMMR,
|
|
1729
|
+
baseMMR: currentSymbolInfo.base_mmr ?? 0,
|
|
1730
|
+
baseIMR: currentSymbolInfo.base_imr ?? 0,
|
|
1731
|
+
IMRFactor: currentPositionIMRFactor,
|
|
1732
|
+
costPosition: currentPosition.cost_position ?? 0
|
|
1733
|
+
});
|
|
1734
|
+
return liqPrice;
|
|
1735
|
+
}, [
|
|
1736
|
+
totalUnsettlementPnl,
|
|
1737
|
+
currentPosition,
|
|
1738
|
+
symbolsInfo,
|
|
1739
|
+
symbol,
|
|
1740
|
+
accountInfo,
|
|
1741
|
+
notional,
|
|
1742
|
+
positions2,
|
|
1743
|
+
finalMargin,
|
|
1744
|
+
markPrice
|
|
1745
|
+
]);
|
|
1746
|
+
const total_collateral_value = useMemo(() => {
|
|
1747
|
+
if (!unSettledPnl) return null;
|
|
1748
|
+
return new Decimal(finalMargin).add(unSettledPnl).toNumber();
|
|
1749
|
+
}, [unSettledPnl, finalMargin]);
|
|
1750
|
+
const effectiveLeverage = useMemo(() => {
|
|
1751
|
+
if (!notional || !total_collateral_value) return null;
|
|
1752
|
+
return notional.div(total_collateral_value).toNumber();
|
|
1753
|
+
}, [notional, total_collateral_value]);
|
|
1754
|
+
return {
|
|
1755
|
+
maxAmount,
|
|
1756
|
+
liquidationPrice,
|
|
1757
|
+
effectiveLeverage
|
|
1758
|
+
};
|
|
1759
|
+
};
|
|
1760
|
+
var usePositionMargin_default = usePositionMargin;
|
|
1761
|
+
|
|
1762
|
+
// src/components/positions/adjustMargin/adjustMargin.script.tsx
|
|
1763
|
+
var useAdjustMarginScript = (props) => {
|
|
1764
|
+
const { position, symbol, close } = props;
|
|
1765
|
+
const { t } = useTranslation();
|
|
1766
|
+
const [tab, setTab] = useState("add");
|
|
1767
|
+
const [inputValue, setInputValue] = useState("");
|
|
1768
|
+
const [sliderValue, setSliderValue] = useState(0);
|
|
1769
|
+
const [updateMargin, { isMutating: isLoading }] = useMutation(
|
|
1770
|
+
"/v1/position_margin",
|
|
1771
|
+
"POST"
|
|
1772
|
+
);
|
|
1773
|
+
const isAdd = useMemo(() => {
|
|
1774
|
+
return tab === "add";
|
|
1775
|
+
}, [tab]);
|
|
1776
|
+
const currentMargin = position.margin ?? 0;
|
|
1777
|
+
const finalMargin = useMemo(() => {
|
|
1778
|
+
const delta = new Decimal(inputValue || 0);
|
|
1779
|
+
if (tab === "add") return currentMargin + delta.toNumber();
|
|
1780
|
+
return currentMargin - delta.toNumber();
|
|
1781
|
+
}, [currentMargin, inputValue, tab]);
|
|
1782
|
+
const { maxAmount, liquidationPrice, effectiveLeverage } = usePositionMargin_default(
|
|
1783
|
+
symbol,
|
|
1784
|
+
isAdd,
|
|
1785
|
+
currentMargin,
|
|
1786
|
+
finalMargin
|
|
1787
|
+
);
|
|
1788
|
+
const syncSliderFromInput = useCallback(
|
|
1789
|
+
(value) => {
|
|
1790
|
+
if (!value) {
|
|
1791
|
+
setSliderValue(0);
|
|
1792
|
+
return;
|
|
1793
|
+
}
|
|
1794
|
+
if (!maxAmount) return;
|
|
1795
|
+
const val = new Decimal(value);
|
|
1796
|
+
if (maxAmount === 0) {
|
|
1797
|
+
setSliderValue(0);
|
|
1798
|
+
return;
|
|
1799
|
+
}
|
|
1800
|
+
const percent = val.div(maxAmount).mul(100).toNumber();
|
|
1801
|
+
setSliderValue(Math.min(100, Math.max(0, percent)));
|
|
1802
|
+
},
|
|
1803
|
+
[maxAmount]
|
|
1804
|
+
);
|
|
1805
|
+
const syncInputFromSlider = useCallback(
|
|
1806
|
+
(value) => {
|
|
1807
|
+
if (!maxAmount) return;
|
|
1808
|
+
const val = new Decimal(maxAmount).mul(value).div(100);
|
|
1809
|
+
setInputValue(val.toFixed(2, Decimal.ROUND_DOWN));
|
|
1810
|
+
},
|
|
1811
|
+
[maxAmount]
|
|
1812
|
+
);
|
|
1813
|
+
const onInputChange = useCallback(
|
|
1814
|
+
(value) => {
|
|
1815
|
+
let finalValue = value;
|
|
1816
|
+
if (maxAmount && value) {
|
|
1817
|
+
const inputDecimal = new Decimal(value);
|
|
1818
|
+
if (inputDecimal.gt(maxAmount)) {
|
|
1819
|
+
finalValue = new Decimal(maxAmount).toFixed(2, Decimal.ROUND_DOWN);
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
setInputValue(finalValue);
|
|
1823
|
+
syncSliderFromInput(finalValue);
|
|
1824
|
+
},
|
|
1825
|
+
[syncSliderFromInput, maxAmount]
|
|
1826
|
+
);
|
|
1827
|
+
const onSliderChange = useCallback(
|
|
1828
|
+
(value) => {
|
|
1829
|
+
setSliderValue(value);
|
|
1830
|
+
syncInputFromSlider(value);
|
|
1831
|
+
},
|
|
1832
|
+
[syncInputFromSlider]
|
|
1833
|
+
);
|
|
1834
|
+
const onTabChange = useCallback((nextTab) => {
|
|
1835
|
+
setTab(nextTab);
|
|
1836
|
+
setInputValue("");
|
|
1837
|
+
setSliderValue(0);
|
|
1838
|
+
}, []);
|
|
1839
|
+
const canConfirm = useMemo(() => {
|
|
1840
|
+
if (!inputValue) return false;
|
|
1841
|
+
const value = new Decimal(inputValue);
|
|
1842
|
+
return !value.isZero() && value.isPositive();
|
|
1843
|
+
}, [inputValue]);
|
|
1844
|
+
const onConfirm = useCallback(async () => {
|
|
1845
|
+
if (!inputValue || new Decimal(inputValue).isZero()) return;
|
|
1846
|
+
if (maxAmount) {
|
|
1847
|
+
const inputDecimal = new Decimal(inputValue);
|
|
1848
|
+
if (inputDecimal.gt(maxAmount)) {
|
|
1849
|
+
toast.error(t("positions.adjustMargin.marginCannotMoreThanMax"));
|
|
1850
|
+
return;
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
try {
|
|
1854
|
+
const payload = {
|
|
1855
|
+
symbol,
|
|
1856
|
+
amount: new Decimal(inputValue).toString(),
|
|
1857
|
+
type: tab === "add" ? "ADD" : "REDUCE"
|
|
1858
|
+
};
|
|
1859
|
+
const response = await updateMargin(payload);
|
|
1860
|
+
if (!response?.success) {
|
|
1861
|
+
toast.error(response?.message || t("positions.adjustMargin.failed"));
|
|
1862
|
+
return;
|
|
1863
|
+
}
|
|
1864
|
+
toast.success(t("positions.adjustMargin.success"));
|
|
1865
|
+
close();
|
|
1866
|
+
} catch (error) {
|
|
1867
|
+
const message = error instanceof Error ? error.message : void 0;
|
|
1868
|
+
toast.error(message || t("positions.adjustMargin.failed"));
|
|
1869
|
+
}
|
|
1870
|
+
}, [close, inputValue, symbol, t, tab, updateMargin, maxAmount]);
|
|
1871
|
+
return {
|
|
1872
|
+
symbol,
|
|
1873
|
+
tab,
|
|
1874
|
+
inputValue,
|
|
1875
|
+
sliderValue,
|
|
1876
|
+
maxAmount: maxAmount ?? 0,
|
|
1877
|
+
currentMargin,
|
|
1878
|
+
liquidationPrice: liquidationPrice ?? 0,
|
|
1879
|
+
effectiveLeverage: effectiveLeverage ?? 0,
|
|
1880
|
+
isLoading,
|
|
1881
|
+
isAdd,
|
|
1882
|
+
canConfirm,
|
|
1883
|
+
onTabChange,
|
|
1884
|
+
onInputChange,
|
|
1885
|
+
onSliderChange,
|
|
1886
|
+
onConfirm,
|
|
1887
|
+
close
|
|
1888
|
+
};
|
|
1889
|
+
};
|
|
1890
|
+
var Footer = (props) => {
|
|
1891
|
+
const { t } = useTranslation();
|
|
1892
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 3, className: "oui-w-full oui-pt-5", children: [
|
|
1893
|
+
/* @__PURE__ */ jsx(
|
|
1894
|
+
Button,
|
|
1895
|
+
{
|
|
1896
|
+
variant: "contained",
|
|
1897
|
+
fullWidth: true,
|
|
1898
|
+
size: "lg",
|
|
1899
|
+
color: "secondary",
|
|
1900
|
+
className: "oui-h-10",
|
|
1901
|
+
onClick: props.close,
|
|
1902
|
+
children: t("common.cancel")
|
|
1903
|
+
}
|
|
1904
|
+
),
|
|
1905
|
+
/* @__PURE__ */ jsx(
|
|
1906
|
+
Button,
|
|
1907
|
+
{
|
|
1908
|
+
variant: "contained",
|
|
1909
|
+
color: "primary",
|
|
1910
|
+
fullWidth: true,
|
|
1911
|
+
size: "lg",
|
|
1912
|
+
className: "oui-h-10",
|
|
1913
|
+
loading: props.isLoading,
|
|
1914
|
+
disabled: !props.canConfirm,
|
|
1915
|
+
onClick: props.onConfirm,
|
|
1916
|
+
children: t("common.confirm")
|
|
1917
|
+
}
|
|
1918
|
+
)
|
|
1919
|
+
] });
|
|
1920
|
+
};
|
|
1921
|
+
var fotter_default = Footer;
|
|
1922
|
+
var Infos = ({
|
|
1923
|
+
currentMargin,
|
|
1924
|
+
liquidationPrice,
|
|
1925
|
+
effectiveLeverage
|
|
1926
|
+
}) => {
|
|
1927
|
+
const { t } = useTranslation();
|
|
1928
|
+
return /* @__PURE__ */ jsxs(
|
|
1929
|
+
Flex,
|
|
1930
|
+
{
|
|
1931
|
+
direction: "column",
|
|
1932
|
+
gap: 1,
|
|
1933
|
+
className: "oui-w-full oui-rounded-[6px] oui-bg-base-6 oui-p-3 oui-text-2xs oui-font-semibold",
|
|
1934
|
+
children: [
|
|
1935
|
+
/* @__PURE__ */ jsx(
|
|
1936
|
+
Statistic,
|
|
1937
|
+
{
|
|
1938
|
+
label: t("positions.adjustMargin.currentMargin"),
|
|
1939
|
+
valueProps: { dp: 2, unit: " USDC", padding: false },
|
|
1940
|
+
classNames: {
|
|
1941
|
+
root: "oui-flex-row oui-justify-between oui-items-center oui-w-full oui-text-2xs oui-h-5",
|
|
1942
|
+
label: "oui-text-2xs"
|
|
1943
|
+
},
|
|
1944
|
+
children: currentMargin
|
|
1945
|
+
}
|
|
1946
|
+
),
|
|
1947
|
+
/* @__PURE__ */ jsx(
|
|
1948
|
+
Statistic,
|
|
1949
|
+
{
|
|
1950
|
+
label: t("positions.adjustMargin.liqPriceAfter"),
|
|
1951
|
+
valueProps: { dp: 2, unit: " USDC", padding: false },
|
|
1952
|
+
classNames: {
|
|
1953
|
+
root: "oui-flex-row oui-justify-between oui-items-center oui-w-full oui-text-2xs oui-h-5",
|
|
1954
|
+
label: "oui-text-2xs"
|
|
1955
|
+
},
|
|
1956
|
+
children: liquidationPrice ?? "--"
|
|
1957
|
+
}
|
|
1958
|
+
),
|
|
1959
|
+
/* @__PURE__ */ jsx(
|
|
1960
|
+
Statistic,
|
|
1961
|
+
{
|
|
1962
|
+
label: t("positions.adjustMargin.leverageAfter"),
|
|
1963
|
+
valueProps: { dp: 2, unit: " x" },
|
|
1964
|
+
classNames: {
|
|
1965
|
+
root: "oui-flex-row oui-justify-between oui-items-center oui-w-full oui-text-2xs oui-h-5",
|
|
1966
|
+
label: "oui-text-2xs"
|
|
1967
|
+
},
|
|
1968
|
+
children: effectiveLeverage ?? "--"
|
|
1969
|
+
}
|
|
1970
|
+
)
|
|
1971
|
+
]
|
|
1972
|
+
}
|
|
1973
|
+
);
|
|
1974
|
+
};
|
|
1975
|
+
var MarginActions = ({
|
|
1976
|
+
isAdd,
|
|
1977
|
+
onTabChange
|
|
1978
|
+
}) => {
|
|
1979
|
+
const { t } = useTranslation();
|
|
1980
|
+
const tabBase = "oui-h-7 oui-rounded-[4px] oui-text-xs oui-font-semibold oui-transition-colors";
|
|
1981
|
+
return /* @__PURE__ */ jsxs(Flex, { className: "oui-w-full oui-gap-[6px]", children: [
|
|
1982
|
+
/* @__PURE__ */ jsx(
|
|
1983
|
+
Button,
|
|
1984
|
+
{
|
|
1985
|
+
size: "md",
|
|
1986
|
+
fullWidth: true,
|
|
1987
|
+
variant: "contained",
|
|
1988
|
+
color: "secondary",
|
|
1989
|
+
className: cn(
|
|
1990
|
+
tabBase,
|
|
1991
|
+
isAdd && "oui-bg-base-5 oui-text-base-contrast-98",
|
|
1992
|
+
!isAdd && "oui-bg-base-7 oui-text-base-contrast-54 hover:oui-text-base-contrast-80"
|
|
1993
|
+
),
|
|
1994
|
+
onClick: () => onTabChange("add"),
|
|
1995
|
+
children: t("positions.adjustMargin.add")
|
|
1996
|
+
}
|
|
1997
|
+
),
|
|
1998
|
+
/* @__PURE__ */ jsx(
|
|
1999
|
+
Button,
|
|
2000
|
+
{
|
|
2001
|
+
size: "sm",
|
|
2002
|
+
fullWidth: true,
|
|
2003
|
+
variant: "contained",
|
|
2004
|
+
color: "secondary",
|
|
2005
|
+
className: cn(
|
|
2006
|
+
tabBase,
|
|
2007
|
+
!isAdd && "oui-bg-base-5 oui-text-base-contrast-98 hover:oui-text-base-contrast-80",
|
|
2008
|
+
isAdd && "oui-bg-base-7 oui-text-base-contrast-54 hover:oui-text-base-contrast-80"
|
|
2009
|
+
),
|
|
2010
|
+
onClick: () => onTabChange("reduce"),
|
|
2011
|
+
children: t("positions.adjustMargin.reduce")
|
|
2012
|
+
}
|
|
2013
|
+
)
|
|
2014
|
+
] });
|
|
2015
|
+
};
|
|
2016
|
+
var Quantity = ({
|
|
2017
|
+
inputValue,
|
|
2018
|
+
sliderValue,
|
|
2019
|
+
maxAmount,
|
|
2020
|
+
onInputChange,
|
|
2021
|
+
onSliderChange
|
|
2022
|
+
}) => {
|
|
2023
|
+
const { t } = useTranslation();
|
|
2024
|
+
const percentMarks = useMemo(
|
|
2025
|
+
() => [0, 25, 50, 75, 100].map((m) => ({ value: m, label: `${m}%` })),
|
|
2026
|
+
[]
|
|
2027
|
+
);
|
|
2028
|
+
const isMaxClickable = maxAmount > 0;
|
|
2029
|
+
const handleSetToMax = useCallback(() => {
|
|
2030
|
+
if (!isMaxClickable) return;
|
|
2031
|
+
onSliderChange(100);
|
|
2032
|
+
}, [isMaxClickable, onSliderChange]);
|
|
2033
|
+
const handleKeyDown = useCallback(
|
|
2034
|
+
(e) => {
|
|
2035
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2036
|
+
e.preventDefault();
|
|
2037
|
+
handleSetToMax();
|
|
2038
|
+
}
|
|
2039
|
+
},
|
|
2040
|
+
[handleSetToMax]
|
|
2041
|
+
);
|
|
2042
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, className: "oui-w-full", children: [
|
|
2043
|
+
/* @__PURE__ */ jsx(
|
|
2044
|
+
Input,
|
|
2045
|
+
{
|
|
2046
|
+
value: inputValue,
|
|
2047
|
+
onValueChange: onInputChange,
|
|
2048
|
+
type: "text",
|
|
2049
|
+
fullWidth: true,
|
|
2050
|
+
size: "lg",
|
|
2051
|
+
align: "right",
|
|
2052
|
+
prefix: t("positions.adjustMargin.quantity"),
|
|
2053
|
+
suffix: "USDC",
|
|
2054
|
+
formatters: [
|
|
2055
|
+
inputFormatter.numberFormatter,
|
|
2056
|
+
inputFormatter.dpFormatter(2)
|
|
2057
|
+
],
|
|
2058
|
+
disabled: maxAmount === null || maxAmount <= 0,
|
|
2059
|
+
autoComplete: "off",
|
|
2060
|
+
classNames: {
|
|
2061
|
+
// Keep border color stable and remove focus ring (Input has focus-within:outline-primary-light by default)
|
|
2062
|
+
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",
|
|
2063
|
+
// keep value aligned to suffix side and match design emphasis
|
|
2064
|
+
input: "oui-text-sm oui-font-semibold oui-text-base-contrast-98",
|
|
2065
|
+
// override default additional padding so value can sit closer to suffix
|
|
2066
|
+
additional: "oui-px-0",
|
|
2067
|
+
prefix: "oui-pl-3 oui-pr-2 oui-text-sm oui-text-base-contrast-54",
|
|
2068
|
+
suffix: "oui-pl-2 oui-pr-3 oui-text-sm oui-text-base-contrast-54"
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
),
|
|
2072
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, className: "oui-w-full", children: [
|
|
2073
|
+
/* @__PURE__ */ jsx(
|
|
2074
|
+
Slider,
|
|
2075
|
+
{
|
|
2076
|
+
value: [sliderValue],
|
|
2077
|
+
onValueChange: (val) => onSliderChange(val[0]),
|
|
2078
|
+
max: 100,
|
|
2079
|
+
min: 0,
|
|
2080
|
+
step: 1,
|
|
2081
|
+
color: "primary",
|
|
2082
|
+
showTip: true,
|
|
2083
|
+
tipFormatter: (v, _min, _max, percent) => `${percent.toFixed(0)}%`,
|
|
2084
|
+
marks: percentMarks,
|
|
2085
|
+
markLabelVisible: false,
|
|
2086
|
+
disabled: maxAmount === null || maxAmount <= 0
|
|
2087
|
+
}
|
|
2088
|
+
),
|
|
2089
|
+
/* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-w-full", children: [
|
|
2090
|
+
/* @__PURE__ */ jsx(Text, { size: "2xs", className: "oui-text-primary", children: `${sliderValue.toFixed(0)}%` }),
|
|
2091
|
+
/* @__PURE__ */ jsxs(
|
|
2092
|
+
Flex,
|
|
2093
|
+
{
|
|
2094
|
+
gap: 1,
|
|
2095
|
+
itemAlign: "baseline",
|
|
2096
|
+
role: isMaxClickable ? "button" : void 0,
|
|
2097
|
+
tabIndex: isMaxClickable ? 0 : void 0,
|
|
2098
|
+
onClick: isMaxClickable ? handleSetToMax : void 0,
|
|
2099
|
+
onKeyDown: isMaxClickable ? handleKeyDown : void 0,
|
|
2100
|
+
className: isMaxClickable ? "oui-cursor-pointer oui-opacity-90 hover:oui-opacity-100" : void 0,
|
|
2101
|
+
children: [
|
|
2102
|
+
/* @__PURE__ */ jsx(Text, { size: "2xs", className: "oui-text-primary", children: t("positions.adjustMargin.max") }),
|
|
2103
|
+
/* @__PURE__ */ jsx(Text.numeral, { size: "2xs", intensity: 54, dp: 2, children: maxAmount })
|
|
2104
|
+
]
|
|
2105
|
+
}
|
|
2106
|
+
)
|
|
2107
|
+
] })
|
|
2108
|
+
] })
|
|
2109
|
+
] });
|
|
2110
|
+
};
|
|
2111
|
+
var SymbolInfo = ({ symbol }) => {
|
|
2112
|
+
return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-items-center oui-gap-2", children: [
|
|
2113
|
+
/* @__PURE__ */ jsx(TokenIcon, { symbol, className: "oui-size-5" }),
|
|
2114
|
+
/* @__PURE__ */ jsx(
|
|
2115
|
+
Text.formatted,
|
|
2116
|
+
{
|
|
2117
|
+
rule: "symbol",
|
|
2118
|
+
formatString: "base-type",
|
|
2119
|
+
size: "base",
|
|
2120
|
+
weight: "semibold",
|
|
2121
|
+
intensity: 98,
|
|
2122
|
+
children: symbol
|
|
2123
|
+
}
|
|
2124
|
+
)
|
|
2125
|
+
] });
|
|
2126
|
+
};
|
|
2127
|
+
var Title = ({ close }) => {
|
|
2128
|
+
const { t } = useTranslation();
|
|
2129
|
+
return /* @__PURE__ */ jsxs("div", { className: "oui-w-full", children: [
|
|
2130
|
+
/* @__PURE__ */ jsxs(Flex, { justify: "between", itemAlign: "center", children: [
|
|
2131
|
+
/* @__PURE__ */ jsx(
|
|
2132
|
+
Text,
|
|
2133
|
+
{
|
|
2134
|
+
className: "oui-text-base oui-leading-6 oui-font-semibold oui-tracking-[0.48px]",
|
|
2135
|
+
intensity: 98,
|
|
2136
|
+
children: t("positions.adjustMargin.title")
|
|
2137
|
+
}
|
|
2138
|
+
),
|
|
2139
|
+
/* @__PURE__ */ jsx(IconButton, { onClick: close, color: "secondary", children: /* @__PURE__ */ jsx(CloseIcon, { size: 18, color: "white", opacity: 0.98 }) })
|
|
2140
|
+
] }),
|
|
2141
|
+
/* @__PURE__ */ jsx(Divider, { className: "oui-mt-[9px] oui-w-full" })
|
|
2142
|
+
] });
|
|
2143
|
+
};
|
|
2144
|
+
var title_default = Title;
|
|
2145
|
+
var AdjustMargin = (props) => {
|
|
2146
|
+
const {
|
|
2147
|
+
symbol,
|
|
2148
|
+
inputValue,
|
|
2149
|
+
sliderValue,
|
|
2150
|
+
maxAmount,
|
|
2151
|
+
currentMargin,
|
|
2152
|
+
liquidationPrice,
|
|
2153
|
+
effectiveLeverage,
|
|
2154
|
+
onTabChange,
|
|
2155
|
+
onInputChange,
|
|
2156
|
+
onSliderChange,
|
|
2157
|
+
close,
|
|
2158
|
+
isAdd
|
|
2159
|
+
} = props;
|
|
2160
|
+
return /* @__PURE__ */ jsxs(
|
|
2161
|
+
Flex,
|
|
2162
|
+
{
|
|
2163
|
+
direction: "column",
|
|
2164
|
+
className: "oui-w-full oui-rounded-[12px] oui-bg-base-8 oui-font-semibold",
|
|
2165
|
+
children: [
|
|
2166
|
+
/* @__PURE__ */ jsx(title_default, { close }),
|
|
2167
|
+
/* @__PURE__ */ jsxs("div", { className: "oui-w-full oui-pt-5", children: [
|
|
2168
|
+
/* @__PURE__ */ jsx(SymbolInfo, { symbol }),
|
|
2169
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, className: "oui-mt-4 oui-w-full", children: [
|
|
2170
|
+
/* @__PURE__ */ jsx(MarginActions, { isAdd, onTabChange }),
|
|
2171
|
+
/* @__PURE__ */ jsx(
|
|
2172
|
+
Quantity,
|
|
2173
|
+
{
|
|
2174
|
+
inputValue,
|
|
2175
|
+
sliderValue,
|
|
2176
|
+
maxAmount,
|
|
2177
|
+
onInputChange,
|
|
2178
|
+
onSliderChange
|
|
2179
|
+
}
|
|
2180
|
+
),
|
|
2181
|
+
/* @__PURE__ */ jsx(
|
|
2182
|
+
Infos,
|
|
2183
|
+
{
|
|
2184
|
+
currentMargin,
|
|
2185
|
+
liquidationPrice,
|
|
2186
|
+
effectiveLeverage
|
|
2187
|
+
}
|
|
2188
|
+
)
|
|
2189
|
+
] })
|
|
2190
|
+
] }),
|
|
2191
|
+
/* @__PURE__ */ jsx(fotter_default, { ...props })
|
|
2192
|
+
]
|
|
2193
|
+
}
|
|
2194
|
+
);
|
|
2195
|
+
};
|
|
2196
|
+
var AdjustMarginDialogId = "AdjustMarginDialog";
|
|
2197
|
+
var AdjustMarginSheetId = "AdjustMarginSheet";
|
|
2198
|
+
var AdjustMarginWidget = (props) => {
|
|
2199
|
+
const { isMobile } = useScreen();
|
|
2200
|
+
const state = useAdjustMarginScript({
|
|
2201
|
+
position: props.position,
|
|
2202
|
+
symbol: props.symbol,
|
|
2203
|
+
close: () => modal.hide(isMobile ? AdjustMarginSheetId : AdjustMarginDialogId)
|
|
2204
|
+
});
|
|
2205
|
+
return /* @__PURE__ */ jsx(AdjustMargin, { ...state });
|
|
2206
|
+
};
|
|
2207
|
+
registerSimpleDialog(AdjustMarginDialogId, AdjustMarginWidget, {
|
|
2208
|
+
title: void 0,
|
|
2209
|
+
closable: false,
|
|
2210
|
+
size: "sm"
|
|
2211
|
+
});
|
|
2212
|
+
registerSimpleSheet(AdjustMarginSheetId, AdjustMarginWidget, {
|
|
2213
|
+
title: void 0,
|
|
2214
|
+
closable: false
|
|
2215
|
+
});
|
|
1601
2216
|
var QuantitySlider = (props) => {
|
|
1602
2217
|
const { t } = useTranslation();
|
|
1603
2218
|
const [sliderValue, setSliderValue] = useState(props.value);
|
|
@@ -2254,29 +2869,59 @@ var AddIcon = (props) => {
|
|
|
2254
2869
|
);
|
|
2255
2870
|
};
|
|
2256
2871
|
var LeverageBadge = (props) => {
|
|
2257
|
-
const { symbol, leverage } = props;
|
|
2872
|
+
const { symbol, leverage, marginMode } = props;
|
|
2873
|
+
const { t } = useTranslation();
|
|
2874
|
+
const resolvedMarginMode = marginMode;
|
|
2258
2875
|
const showModal = () => {
|
|
2259
2876
|
modal.show(props.modalId, {
|
|
2260
2877
|
symbol,
|
|
2261
|
-
curLeverage:
|
|
2878
|
+
curLeverage: leverage,
|
|
2879
|
+
marginMode: resolvedMarginMode
|
|
2262
2880
|
});
|
|
2263
2881
|
};
|
|
2264
|
-
return /* @__PURE__ */
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2882
|
+
return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-items-center oui-gap-1", children: [
|
|
2883
|
+
/* @__PURE__ */ jsx(
|
|
2884
|
+
"div",
|
|
2885
|
+
{
|
|
2886
|
+
className: cn(
|
|
2887
|
+
"oui-flex oui-h-[18px] oui-items-center",
|
|
2888
|
+
"oui-rounded oui-bg-line-6 oui-px-2",
|
|
2889
|
+
"oui-text-2xs oui-font-semibold oui-text-base-contrast-36"
|
|
2890
|
+
),
|
|
2891
|
+
children: /* @__PURE__ */ jsx(Text, { children: resolvedMarginMode === void 0 ? "--" : resolvedMarginMode === MarginMode.ISOLATED ? t("marginMode.isolated") : t("marginMode.cross") })
|
|
2892
|
+
}
|
|
2893
|
+
),
|
|
2894
|
+
/* @__PURE__ */ jsxs(
|
|
2895
|
+
"div",
|
|
2896
|
+
{
|
|
2897
|
+
className: cn(
|
|
2898
|
+
"oui-flex oui-h-[18px] oui-items-center oui-gap-1",
|
|
2899
|
+
"oui-rounded oui-bg-line-6 oui-px-2",
|
|
2900
|
+
"oui-text-2xs oui-font-semibold oui-text-base-contrast-36",
|
|
2901
|
+
"oui-cursor-pointer"
|
|
2902
|
+
),
|
|
2903
|
+
onClick: showModal,
|
|
2904
|
+
children: [
|
|
2905
|
+
leverage === void 0 ? /* @__PURE__ */ jsx(LeverageDisplay, { symbol, marginMode }) : /* @__PURE__ */ jsx(Text.numeral, { dp: 0, rm: Decimal.ROUND_DOWN, size: "2xs", unit: "X", children: leverage }),
|
|
2906
|
+
/* @__PURE__ */ jsx(
|
|
2907
|
+
ChevronRightIcon,
|
|
2908
|
+
{
|
|
2909
|
+
size: 12,
|
|
2910
|
+
className: "oui-text-base-contrast-36",
|
|
2911
|
+
opacity: 1
|
|
2912
|
+
}
|
|
2913
|
+
)
|
|
2914
|
+
]
|
|
2915
|
+
}
|
|
2916
|
+
)
|
|
2917
|
+
] });
|
|
2276
2918
|
};
|
|
2277
|
-
var LeverageDisplay = ({
|
|
2278
|
-
|
|
2279
|
-
|
|
2919
|
+
var LeverageDisplay = ({
|
|
2920
|
+
symbol,
|
|
2921
|
+
marginMode
|
|
2922
|
+
}) => {
|
|
2923
|
+
const leverage = useLeverageBySymbol(symbol, marginMode);
|
|
2924
|
+
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
2925
|
};
|
|
2281
2926
|
var renderQuantity = (value) => {
|
|
2282
2927
|
const symbolInfo = useSymbolContext();
|
|
@@ -2430,11 +3075,13 @@ var useShareButtonScript = (props) => {
|
|
|
2430
3075
|
const { position, sharePnLConfig, iconSize } = props;
|
|
2431
3076
|
const { getFirstRefCode } = useReferralInfo();
|
|
2432
3077
|
const symbolsInfo = useSymbolsInfo();
|
|
2433
|
-
const { data: accountInfo } = useAccountInfo();
|
|
2434
3078
|
const refCode = useMemo(() => {
|
|
2435
3079
|
return getFirstRefCode()?.code;
|
|
2436
3080
|
}, [getFirstRefCode]);
|
|
2437
|
-
const symbolLeverage = useLeverageBySymbol(
|
|
3081
|
+
const symbolLeverage = useLeverageBySymbol(
|
|
3082
|
+
position.symbol,
|
|
3083
|
+
position.margin_mode ?? MarginMode.CROSS
|
|
3084
|
+
);
|
|
2438
3085
|
const getHistoryEntity = () => {
|
|
2439
3086
|
const netPnL = position.netPnL || 0;
|
|
2440
3087
|
const openPrice = Math.abs(position.avg_open_price);
|
|
@@ -2443,10 +3090,22 @@ var useShareButtonScript = (props) => {
|
|
|
2443
3090
|
const symbolInfo = symbolsInfo[position.symbol];
|
|
2444
3091
|
const baseIMR = symbolInfo("base_imr");
|
|
2445
3092
|
const IMR_Factor = symbolInfo("imr_factor");
|
|
2446
|
-
if (netPnL !== 0 && quantity !== 0 && openPrice !== 0 &&
|
|
3093
|
+
if (netPnL !== 0 && quantity !== 0 && openPrice !== 0 && baseIMR && // IMR_Factor is possible to be 0
|
|
2447
3094
|
typeof IMR_Factor !== "undefined") {
|
|
2448
3095
|
const notional = positions.notional(quantity, openPrice);
|
|
2449
|
-
const maxLeverage = position.leverage
|
|
3096
|
+
const maxLeverage = position.leverage || symbolLeverage;
|
|
3097
|
+
if (!maxLeverage) {
|
|
3098
|
+
return {
|
|
3099
|
+
side: position.side,
|
|
3100
|
+
pnl: netPnL,
|
|
3101
|
+
roi,
|
|
3102
|
+
openPrice,
|
|
3103
|
+
closePrice: Math.abs(position.avg_close_price),
|
|
3104
|
+
openTime: position.open_timestamp,
|
|
3105
|
+
closeTime: position.close_timestamp,
|
|
3106
|
+
quantity: position.closed_position_qty
|
|
3107
|
+
};
|
|
3108
|
+
}
|
|
2450
3109
|
const imr = account.IMR({
|
|
2451
3110
|
maxLeverage,
|
|
2452
3111
|
baseIMR,
|
|
@@ -2490,7 +3149,8 @@ var useShareButtonScript = (props) => {
|
|
|
2490
3149
|
symbol: position.symbol,
|
|
2491
3150
|
// when position.leverage is empty, use leverage from useSymbolLeverage
|
|
2492
3151
|
leverage: position.leverage || symbolLeverage,
|
|
2493
|
-
...entity
|
|
3152
|
+
...entity,
|
|
3153
|
+
marginMode: position.margin_mode
|
|
2494
3154
|
},
|
|
2495
3155
|
refCode,
|
|
2496
3156
|
...sharePnLConfig
|
|
@@ -2805,7 +3465,7 @@ var useColumn = (config) => {
|
|
|
2805
3465
|
positionReverse
|
|
2806
3466
|
} = config;
|
|
2807
3467
|
const { t } = useTranslation();
|
|
2808
|
-
|
|
3468
|
+
const { isMobile } = useScreen();
|
|
2809
3469
|
const column = useMemo(
|
|
2810
3470
|
() => [
|
|
2811
3471
|
{
|
|
@@ -2848,7 +3508,8 @@ var useColumn = (config) => {
|
|
|
2848
3508
|
{
|
|
2849
3509
|
symbol: value,
|
|
2850
3510
|
leverage: record.leverage,
|
|
2851
|
-
modalId: SymbolLeverageDialogId
|
|
3511
|
+
modalId: SymbolLeverageDialogId,
|
|
3512
|
+
marginMode: record.margin_mode
|
|
2852
3513
|
}
|
|
2853
3514
|
),
|
|
2854
3515
|
/* @__PURE__ */ jsx(RwaStatusTag, { symbol: value })
|
|
@@ -3037,17 +3698,13 @@ var useColumn = (config) => {
|
|
|
3037
3698
|
Tooltip,
|
|
3038
3699
|
{
|
|
3039
3700
|
className: "oui-max-w-[280px] oui-bg-base-8 oui-p-3 oui-text-2xs oui-text-base-contrast-54",
|
|
3040
|
-
content: /* @__PURE__ */
|
|
3701
|
+
content: /* @__PURE__ */ jsx(
|
|
3041
3702
|
Flex,
|
|
3042
3703
|
{
|
|
3043
3704
|
direction: "column",
|
|
3044
3705
|
gap: 3,
|
|
3045
3706
|
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
|
-
]
|
|
3707
|
+
children: /* @__PURE__ */ jsx("span", { children: t("positions.column.margin.tooltip") })
|
|
3051
3708
|
}
|
|
3052
3709
|
),
|
|
3053
3710
|
children: /* @__PURE__ */ jsx(Text, { className: "oui-underline oui-decoration-dotted", children: t("positions.column.margin") })
|
|
@@ -3057,7 +3714,26 @@ var useColumn = (config) => {
|
|
|
3057
3714
|
onSort: true,
|
|
3058
3715
|
width: 140,
|
|
3059
3716
|
rule: "price",
|
|
3060
|
-
render: (value) =>
|
|
3717
|
+
render: (value, record) => {
|
|
3718
|
+
const isIsolated = record.margin_mode === "ISOLATED";
|
|
3719
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, itemAlign: "center", children: [
|
|
3720
|
+
/* @__PURE__ */ jsx(Text.numeral, { children: isIsolated ? record.margin ?? "--" : "--" }),
|
|
3721
|
+
isIsolated && /* @__PURE__ */ jsx(
|
|
3722
|
+
IconButton,
|
|
3723
|
+
{
|
|
3724
|
+
color: "secondary",
|
|
3725
|
+
onClick: (e) => {
|
|
3726
|
+
e.stopPropagation();
|
|
3727
|
+
modal.show(AdjustMarginDialogId, {
|
|
3728
|
+
position: record,
|
|
3729
|
+
symbol: record.symbol
|
|
3730
|
+
});
|
|
3731
|
+
},
|
|
3732
|
+
children: /* @__PURE__ */ jsx(AddCircleIcon, { size: 16, fill: "currentColor", opacity: 1 })
|
|
3733
|
+
}
|
|
3734
|
+
)
|
|
3735
|
+
] });
|
|
3736
|
+
}
|
|
3061
3737
|
},
|
|
3062
3738
|
// {
|
|
3063
3739
|
// title: t("funding.fundingFee"),
|
|
@@ -3122,7 +3798,8 @@ var SymbolToken = (props) => {
|
|
|
3122
3798
|
{
|
|
3123
3799
|
symbol: item.symbol,
|
|
3124
3800
|
leverage: item.leverage,
|
|
3125
|
-
modalId: SymbolLeverageSheetId
|
|
3801
|
+
modalId: SymbolLeverageSheetId,
|
|
3802
|
+
marginMode: item.margin_mode
|
|
3126
3803
|
}
|
|
3127
3804
|
)
|
|
3128
3805
|
] }),
|
|
@@ -3205,11 +3882,8 @@ var Qty = (props) => {
|
|
|
3205
3882
|
var Margin = (props) => {
|
|
3206
3883
|
const { item } = props;
|
|
3207
3884
|
const { t } = useTranslation();
|
|
3208
|
-
const
|
|
3209
|
-
|
|
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
|
-
] });
|
|
3885
|
+
const isIsolated = item.margin_mode === "ISOLATED";
|
|
3886
|
+
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
3887
|
const marginLabel = /* @__PURE__ */ jsx(Text, { className: "oui-underline oui-decoration-dotted", children: t("positions.column.margin") });
|
|
3214
3888
|
return /* @__PURE__ */ jsx(
|
|
3215
3889
|
Statistic,
|
|
@@ -3226,7 +3900,23 @@ var Margin = (props) => {
|
|
|
3226
3900
|
root: "oui-text-xs",
|
|
3227
3901
|
label: "oui-text-2xs"
|
|
3228
3902
|
},
|
|
3229
|
-
children: /* @__PURE__ */
|
|
3903
|
+
children: /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
|
|
3904
|
+
/* @__PURE__ */ jsx(Text.numeral, { dp: 2, intensity: 80, children: isIsolated ? item.margin ?? "--" : "--" }),
|
|
3905
|
+
isIsolated && /* @__PURE__ */ jsx(
|
|
3906
|
+
IconButton,
|
|
3907
|
+
{
|
|
3908
|
+
color: "secondary",
|
|
3909
|
+
onClick: (e) => {
|
|
3910
|
+
e.stopPropagation();
|
|
3911
|
+
modal.show(AdjustMarginSheetId, {
|
|
3912
|
+
position: item,
|
|
3913
|
+
symbol: item.symbol
|
|
3914
|
+
});
|
|
3915
|
+
},
|
|
3916
|
+
children: /* @__PURE__ */ jsx(AddCircleIcon, { size: 16, fill: "currentColor", opacity: 1 })
|
|
3917
|
+
}
|
|
3918
|
+
)
|
|
3919
|
+
] })
|
|
3230
3920
|
}
|
|
3231
3921
|
);
|
|
3232
3922
|
};
|
|
@@ -3631,7 +4321,7 @@ var Positions = (props) => {
|
|
|
3631
4321
|
columns,
|
|
3632
4322
|
bordered: true,
|
|
3633
4323
|
dataSource,
|
|
3634
|
-
generatedRowKey: (record) => record.symbol
|
|
4324
|
+
generatedRowKey: (record, index) => `${record.symbol}-${index}`,
|
|
3635
4325
|
renderRowContainer: (record, index, children) => {
|
|
3636
4326
|
return /* @__PURE__ */ jsx(SymbolProvider, { symbol: record.symbol, children: /* @__PURE__ */ jsx(PositionsRowProvider, { position: record, children }) });
|
|
3637
4327
|
},
|
|
@@ -3703,7 +4393,7 @@ var CombinePositions = (props) => {
|
|
|
3703
4393
|
dataSource,
|
|
3704
4394
|
expanded: true,
|
|
3705
4395
|
getSubRows: (row) => row.children,
|
|
3706
|
-
generatedRowKey: (record) => `${record.account_id}${record.symbol || ""}`,
|
|
4396
|
+
generatedRowKey: (record, index) => `${record.account_id}${record.symbol || ""}-${index}`,
|
|
3707
4397
|
onCell: (column, record) => {
|
|
3708
4398
|
const isGroup = (record.children ?? []).length > 0;
|
|
3709
4399
|
if (isGroup) {
|
|
@@ -3762,14 +4452,14 @@ var usePositionHistoryColumn = (props) => {
|
|
|
3762
4452
|
onSort: (r1, r2) => {
|
|
3763
4453
|
return r1.symbol?.localeCompare(r2.symbol || "");
|
|
3764
4454
|
},
|
|
3765
|
-
render: (value, record) => /* @__PURE__ */ jsx(
|
|
4455
|
+
render: (value, record) => /* @__PURE__ */ jsx(SymbolInfo2, { record, onSymbolChange })
|
|
3766
4456
|
},
|
|
3767
4457
|
// quantity
|
|
3768
4458
|
{
|
|
3769
4459
|
title: t("positions.history.column.closed&maxClosed"),
|
|
3770
4460
|
dataIndex: "close_maxClose",
|
|
3771
4461
|
width: 200,
|
|
3772
|
-
render: (value, record) => /* @__PURE__ */ jsx(
|
|
4462
|
+
render: (value, record) => /* @__PURE__ */ jsx(Quantity2, { record })
|
|
3773
4463
|
},
|
|
3774
4464
|
// net pnl
|
|
3775
4465
|
{
|
|
@@ -3877,7 +4567,7 @@ var usePositionHistoryColumn = (props) => {
|
|
|
3877
4567
|
);
|
|
3878
4568
|
return column;
|
|
3879
4569
|
};
|
|
3880
|
-
var
|
|
4570
|
+
var SymbolInfo2 = (props) => {
|
|
3881
4571
|
const { record, onSymbolChange } = props;
|
|
3882
4572
|
const { t } = useTranslation();
|
|
3883
4573
|
const tags = useMemo(() => {
|
|
@@ -3991,7 +4681,7 @@ var SymbolInfo = (props) => {
|
|
|
3991
4681
|
] })
|
|
3992
4682
|
] });
|
|
3993
4683
|
};
|
|
3994
|
-
var
|
|
4684
|
+
var Quantity2 = (props) => {
|
|
3995
4685
|
const { record } = props;
|
|
3996
4686
|
const { base_dp } = useSymbolContext();
|
|
3997
4687
|
return /* @__PURE__ */ jsxs(
|
|
@@ -4124,6 +4814,8 @@ var usePositionHistoryScript = (props) => {
|
|
|
4124
4814
|
const netPnL = item.realized_pnl - item.accumulated_funding_fee - item.trading_fee;
|
|
4125
4815
|
return {
|
|
4126
4816
|
...item,
|
|
4817
|
+
// convert margin_mode to MarginMode
|
|
4818
|
+
margin_mode: item.margin_mode === 1 || item.margin_mode === MarginMode.ISOLATED ? MarginMode.ISOLATED : MarginMode.CROSS,
|
|
4127
4819
|
netPnL
|
|
4128
4820
|
};
|
|
4129
4821
|
}
|
|
@@ -4737,7 +5429,7 @@ var PositionHistory = (props) => {
|
|
|
4737
5429
|
columns: column,
|
|
4738
5430
|
bordered: true,
|
|
4739
5431
|
dataSource: props.dataSource,
|
|
4740
|
-
generatedRowKey: (record) => `${record.symbol}_${record.position_id}`,
|
|
5432
|
+
generatedRowKey: (record, index) => `${record.symbol}_${record.position_id}_${index}`,
|
|
4741
5433
|
renderRowContainer: (record, index, children) => /* @__PURE__ */ jsx(SymbolProvider, { symbol: record.symbol, children }),
|
|
4742
5434
|
manualPagination: false,
|
|
4743
5435
|
pagination,
|
|
@@ -5530,7 +6222,8 @@ var useCloseAllPositionsScript = (options) => {
|
|
|
5530
6222
|
order_type: OrderType.MARKET,
|
|
5531
6223
|
side,
|
|
5532
6224
|
order_quantity: quantity,
|
|
5533
|
-
reduce_only: true
|
|
6225
|
+
reduce_only: true,
|
|
6226
|
+
margin_mode: position.margin_mode
|
|
5534
6227
|
};
|
|
5535
6228
|
}),
|
|
5536
6229
|
[]
|