@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.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +741 -57
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +745 -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,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:
|
|
2869
|
+
curLeverage: leverage,
|
|
2870
|
+
marginMode: resolvedMarginMode
|
|
2262
2871
|
});
|
|
2263
2872
|
};
|
|
2264
|
-
return /* @__PURE__ */
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
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 = ({
|
|
2278
|
-
|
|
2279
|
-
|
|
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(
|
|
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 &&
|
|
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
|
|
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
|
-
|
|
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__ */
|
|
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) =>
|
|
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
|
|
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
|
-
] });
|
|
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__ */
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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
|
[]
|