@orderly.network/ui-positions 2.8.5 → 2.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var ui = require('@orderly.network/ui');
4
- var React = require('react');
4
+ var React2 = require('react');
5
5
  var i18n = require('@orderly.network/i18n');
6
6
  var types = require('@orderly.network/types');
7
7
  var utils = require('@orderly.network/utils');
@@ -18,7 +18,7 @@ var dateFns = require('date-fns');
18
18
 
19
19
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
20
20
 
21
- var React__default = /*#__PURE__*/_interopDefault(React);
21
+ var React2__default = /*#__PURE__*/_interopDefault(React2);
22
22
 
23
23
  // src/index.ts
24
24
  var ConfirmHeader = (props) => {
@@ -75,7 +75,7 @@ var ConfirmFooter = (props) => {
75
75
  var OrderDetail = (props) => {
76
76
  const { quantity, price, quoteDp, side } = props;
77
77
  const { t } = i18n.useTranslation();
78
- const total = React.useMemo(() => {
78
+ const total = React2.useMemo(() => {
79
79
  if (price && quantity) {
80
80
  return new utils.Decimal(price).mul(quantity).toFixed(quoteDp, utils.Decimal.ROUND_DOWN);
81
81
  }
@@ -216,17 +216,17 @@ var LimitConfirmDialog = (props) => {
216
216
  )
217
217
  ] });
218
218
  };
219
- var PositionsRowContext = React.createContext(
219
+ var PositionsRowContext = React2.createContext(
220
220
  {}
221
221
  );
222
222
  var usePositionsRowContext = () => {
223
- return React.useContext(PositionsRowContext);
223
+ return React2.useContext(PositionsRowContext);
224
224
  };
225
225
  function useEndReached(sentinelRef, onEndReached) {
226
- const observer = React.useRef();
227
- const cb = React.useRef(onEndReached);
226
+ const observer = React2.useRef();
227
+ const cb = React2.useRef(onEndReached);
228
228
  cb.current = onEndReached;
229
- React.useEffect(() => {
229
+ React2.useEffect(() => {
230
230
  const options = {
231
231
  root: null,
232
232
  rootMargin: "0px",
@@ -244,12 +244,12 @@ function useEndReached(sentinelRef, onEndReached) {
244
244
  observer.current?.disconnect();
245
245
  };
246
246
  }, []);
247
- React.useEffect(() => {
247
+ React2.useEffect(() => {
248
248
  observer.current?.observe(sentinelRef.current);
249
249
  }, []);
250
250
  }
251
251
  var EndReachedBox = (props) => {
252
- const sentinelRef = React.useRef(null);
252
+ const sentinelRef = React2.useRef(null);
253
253
  const { onEndReached } = props;
254
254
  useEndReached(sentinelRef, () => {
255
255
  onEndReached?.();
@@ -279,12 +279,12 @@ var FundingFeeHistoryUI = ({ total, symbol, start_t, end_t }) => {
279
279
  revalidateFirstPage: false
280
280
  }
281
281
  );
282
- const loadMore = React.useCallback(() => {
282
+ const loadMore = React2.useCallback(() => {
283
283
  setSize((prev) => {
284
284
  return prev + 1;
285
285
  });
286
286
  }, [setSize]);
287
- const flattenData = React.useMemo(() => {
287
+ const flattenData = React2.useMemo(() => {
288
288
  if (!Array.isArray(data))
289
289
  return [];
290
290
  return data.flat().map((item) => {
@@ -294,7 +294,7 @@ var FundingFeeHistoryUI = ({ total, symbol, start_t, end_t }) => {
294
294
  };
295
295
  });
296
296
  }, [data]);
297
- const listView = React.useMemo(() => {
297
+ const listView = React2.useMemo(() => {
298
298
  if (isMobile) {
299
299
  return /* @__PURE__ */ jsxRuntime.jsx(
300
300
  HistoryDataListViewSimple,
@@ -409,7 +409,7 @@ var FundingFeeLabel = ({
409
409
  };
410
410
  var HistoryDataListView = ({ isLoading, data, loadMore }) => {
411
411
  const { t } = i18n.useTranslation();
412
- const columns = React.useMemo(() => {
412
+ const columns = React2.useMemo(() => {
413
413
  return [
414
414
  {
415
415
  title: t("common.time"),
@@ -468,7 +468,7 @@ var HistoryDataListViewSimple = ({
468
468
  isLoading,
469
469
  loadMore
470
470
  }) => {
471
- const renderItem = React.useCallback((item) => {
471
+ const renderItem = React2.useCallback((item) => {
472
472
  return /* @__PURE__ */ jsxRuntime.jsx(FundingFeeItem, { item });
473
473
  }, []);
474
474
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oui-h-[calc(80vh_-_104px)] oui-overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -661,7 +661,7 @@ var useCombinePositionsScript = (props) => {
661
661
  selectedAccount
662
662
  } = props;
663
663
  const { pagination, setPage } = ui.usePagination({ pageSize: 50 });
664
- React.useEffect(() => {
664
+ React2.useEffect(() => {
665
665
  setPage(1);
666
666
  }, [symbol]);
667
667
  const symbolsInfo = hooks.useSymbolsInfo();
@@ -759,7 +759,7 @@ var useCombinePositionsScript = (props) => {
759
759
  (acc) => acc.position_qty !== 0
760
760
  )
761
761
  ) ?? [];
762
- const filtered = React.useMemo(() => {
762
+ const filtered = React2.useMemo(() => {
763
763
  if (!selectedAccount || selectedAccount === "All accounts" /* ALL */) {
764
764
  return dataSource;
765
765
  }
@@ -771,13 +771,13 @@ var useCombinePositionsScript = (props) => {
771
771
  }
772
772
  });
773
773
  }, [dataSource, selectedAccount, state.mainAccountId]);
774
- const groupDataSource = React.useMemo(() => {
774
+ const groupDataSource = React2.useMemo(() => {
775
775
  return groupDataByAccount(filtered, {
776
776
  mainAccountId: state.mainAccountId,
777
777
  subAccounts: state.subAccounts
778
778
  });
779
779
  }, [filtered, state.mainAccountId, state.subAccounts]);
780
- const mergedLoading = React.useMemo(() => {
780
+ const mergedLoading = React2.useMemo(() => {
781
781
  return isLoading || isPositionLoading || isAccountInfoLoading;
782
782
  }, [isLoading, isPositionLoading, isAccountInfoLoading]);
783
783
  return {
@@ -857,8 +857,8 @@ function sortList(list, sort) {
857
857
  return sortedList;
858
858
  }
859
859
  function useSort(initialSort, onSortChange) {
860
- const [sort, setSort] = React.useState(initialSort);
861
- const onSort = React.useCallback((options) => {
860
+ const [sort, setSort] = React2.useState(initialSort);
861
+ const onSort = React2.useCallback((options) => {
862
862
  const nextSort = options ? {
863
863
  sortKey: options.sortKey,
864
864
  sortOrder: options.sort
@@ -866,7 +866,7 @@ function useSort(initialSort, onSortChange) {
866
866
  setSort(nextSort);
867
867
  onSortChange?.(nextSort);
868
868
  }, []);
869
- const getSortedList = React.useCallback(
869
+ const getSortedList = React2.useCallback(
870
870
  (list) => sortList(list, sort),
871
871
  [sort]
872
872
  );
@@ -876,6 +876,404 @@ function useSort(initialSort, onSortChange) {
876
876
  getSortedList
877
877
  };
878
878
  }
879
+ var OrderInfoCard = ({
880
+ title,
881
+ side,
882
+ leverage,
883
+ qty,
884
+ baseDp,
885
+ estLiqPrice,
886
+ className
887
+ }) => {
888
+ const { t } = i18n.useTranslation();
889
+ return /* @__PURE__ */ jsxRuntime.jsxs(
890
+ ui.Flex,
891
+ {
892
+ direction: "column",
893
+ gap: 3,
894
+ itemAlign: "start",
895
+ className: `oui-bg-base-6 oui-rounded-lg oui-p-3 oui-w-full oui-font-weight-semibold ${className || ""}`,
896
+ children: [
897
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "between", itemAlign: "center", gap: 2, children: [
898
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "sm", weight: "semibold", intensity: 98, children: title }),
899
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { itemAlign: "center", gap: 1, children: [
900
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: side === types.OrderSide.SELL ? "sell" : "buy", size: "xs", children: side === types.OrderSide.SELL ? t("common.sell") : t("common.buy") }),
901
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { color: "neutral", size: "xs", children: [
902
+ leverage,
903
+ "X"
904
+ ] })
905
+ ] })
906
+ ] }),
907
+ /* @__PURE__ */ jsxRuntime.jsxs(
908
+ ui.Flex,
909
+ {
910
+ direction: "column",
911
+ justify: "between",
912
+ itemAlign: "center",
913
+ width: "100%",
914
+ children: [
915
+ /* @__PURE__ */ jsxRuntime.jsxs(
916
+ ui.Flex,
917
+ {
918
+ direction: "row",
919
+ justify: "between",
920
+ itemAlign: "center",
921
+ width: "100%",
922
+ gap: 1,
923
+ children: [
924
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "sm", intensity: 54, children: t("common.qty") }),
925
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { dp: baseDp, size: "sm", color: "danger", padding: false, children: qty })
926
+ ]
927
+ }
928
+ ),
929
+ /* @__PURE__ */ jsxRuntime.jsxs(
930
+ ui.Flex,
931
+ {
932
+ direction: "row",
933
+ justify: "between",
934
+ itemAlign: "center",
935
+ width: "100%",
936
+ gap: 1,
937
+ children: [
938
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "sm", intensity: 54, children: t("common.price") }),
939
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "sm", weight: "semibold", children: t("common.market") })
940
+ ]
941
+ }
942
+ ),
943
+ estLiqPrice && /* @__PURE__ */ jsxRuntime.jsxs(
944
+ ui.Flex,
945
+ {
946
+ direction: "row",
947
+ justify: "between",
948
+ itemAlign: "center",
949
+ width: "100%",
950
+ gap: 1,
951
+ children: [
952
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "sm", intensity: 54, children: t("orderEntry.estLiqPrice") }),
953
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "sm", weight: "semibold", children: estLiqPrice })
954
+ ]
955
+ }
956
+ )
957
+ ]
958
+ }
959
+ )
960
+ ]
961
+ }
962
+ );
963
+ };
964
+ var ReversePosition = (props) => {
965
+ const { displayInfo, className, style, onConfirm, onCancel } = props;
966
+ const { t } = i18n.useTranslation();
967
+ if (!displayInfo) {
968
+ return null;
969
+ }
970
+ const {
971
+ symbol,
972
+ base,
973
+ quote,
974
+ baseDp,
975
+ quoteDp,
976
+ positionQty,
977
+ reverseQty,
978
+ markPrice,
979
+ leverage,
980
+ isLong
981
+ } = displayInfo;
982
+ const closeSide = !isLong ? types.OrderSide.SELL : types.OrderSide.BUY;
983
+ const openSide = isLong ? types.OrderSide.SELL : types.OrderSide.BUY;
984
+ const closeAction = isLong ? t("positions.reverse.marketCloseLong") : t("positions.reverse.marketCloseShort");
985
+ const openAction = openSide === types.OrderSide.BUY ? t("positions.reverse.marketOpenLong") : t("positions.reverse.marketOpenShort");
986
+ const reverseTo = isLong ? t("positions.reverse.reverseToShort") : t("positions.reverse.reverseToLong");
987
+ const reverseToIcon = isLong ? /* @__PURE__ */ jsxRuntime.jsx(ui.ArrowDownShortIcon, { size: 16, color: "danger", opacity: 1 }) : /* @__PURE__ */ jsxRuntime.jsx(ui.ArrowUpShortIcon, { size: 16, color: "success", opacity: 1 });
988
+ const priceLabel = /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { itemAlign: "center", gap: 1, children: [
989
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { dp: quoteDp, size: "sm", intensity: 80, children: markPrice }),
990
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "sm", intensity: 36, children: quote })
991
+ ] });
992
+ return /* @__PURE__ */ jsxRuntime.jsxs(
993
+ ui.Flex,
994
+ {
995
+ direction: "column",
996
+ className,
997
+ style,
998
+ gap: 4,
999
+ width: "100%",
1000
+ children: [
1001
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "column", gap: 2, width: "100%", children: [
1002
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "between", itemAlign: "center", width: "100%", children: [
1003
+ /* @__PURE__ */ jsxRuntime.jsx(
1004
+ ui.Text.formatted,
1005
+ {
1006
+ size: "base",
1007
+ weight: "semibold",
1008
+ rule: "symbol",
1009
+ formatString: "base-type",
1010
+ intensity: 98,
1011
+ showIcon: true,
1012
+ children: symbol
1013
+ }
1014
+ ),
1015
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: isLong ? "sell" : "buy", size: "xs", children: reverseTo })
1016
+ ] }),
1017
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "between", itemAlign: "center", width: "100%", children: [
1018
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "sm", intensity: 54, children: t("common.markPrice") }),
1019
+ priceLabel
1020
+ ] })
1021
+ ] }),
1022
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { intensity: 4, className: "oui-w-full" }),
1023
+ /* @__PURE__ */ jsxRuntime.jsx(
1024
+ OrderInfoCard,
1025
+ {
1026
+ title: closeAction,
1027
+ side: closeSide,
1028
+ leverage,
1029
+ qty: positionQty,
1030
+ baseDp
1031
+ }
1032
+ ),
1033
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "row", itemAlign: "center", width: "100%", children: [
1034
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { intensity: 8, className: "oui-w-full" }),
1035
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { className: "oui-px-4 oui-py-[3px] oui-border oui-border-base-contrast-12 oui-rounded-full oui-shrink-0", children: [
1036
+ reverseToIcon,
1037
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "2xs", color: isLong ? "danger" : "success", children: reverseTo })
1038
+ ] }),
1039
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { intensity: 8, className: "oui-w-full" })
1040
+ ] }),
1041
+ /* @__PURE__ */ jsxRuntime.jsx(
1042
+ OrderInfoCard,
1043
+ {
1044
+ title: openAction,
1045
+ side: openSide,
1046
+ leverage,
1047
+ qty: reverseQty,
1048
+ baseDp
1049
+ }
1050
+ ),
1051
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "2xs", color: "warning", weight: "semibold", children: t("positions.reverse.description") })
1052
+ ]
1053
+ }
1054
+ );
1055
+ };
1056
+ var useReversePositionEnabled = () => {
1057
+ const { isMobile, isDesktop } = ui.useScreen();
1058
+ const [desktopEnabled, setDesktopEnabled] = hooks.useLocalStorage(
1059
+ "orderly_reverse_position_enabled_desktop",
1060
+ true
1061
+ );
1062
+ const [mobileEnabled, setMobileEnabled] = hooks.useLocalStorage(
1063
+ "orderly_reverse_position_enabled_mobile",
1064
+ false
1065
+ );
1066
+ const isEnabled = React2.useMemo(() => {
1067
+ if (isMobile) {
1068
+ return mobileEnabled;
1069
+ }
1070
+ if (isDesktop) {
1071
+ return desktopEnabled;
1072
+ }
1073
+ return false;
1074
+ }, [isMobile, isDesktop, desktopEnabled, mobileEnabled]);
1075
+ const setEnabled = React2.useCallback(
1076
+ (enabled) => {
1077
+ if (isMobile) {
1078
+ setMobileEnabled(enabled);
1079
+ } else if (isDesktop) {
1080
+ setDesktopEnabled(enabled);
1081
+ }
1082
+ },
1083
+ [isMobile, isDesktop, setMobileEnabled, setDesktopEnabled]
1084
+ );
1085
+ return {
1086
+ isEnabled,
1087
+ setEnabled
1088
+ };
1089
+ };
1090
+ var useReversePositionScript = (options) => {
1091
+ const { position, onSuccess, onError } = options || {};
1092
+ const { t } = i18n.useTranslation();
1093
+ const { isEnabled, setEnabled } = useReversePositionEnabled();
1094
+ const symbolsInfo = hooks.useSymbolsInfo();
1095
+ const symbol = position?.symbol || "";
1096
+ const { data: symbolMarketPrice } = hooks.useMarkPrice(symbol);
1097
+ const symbolInfo = symbolsInfo?.[symbol];
1098
+ const positionQty = React2.useMemo(() => {
1099
+ if (!position)
1100
+ return 0;
1101
+ return Math.abs(position.position_qty);
1102
+ }, [position]);
1103
+ const isLong = React2.useMemo(() => {
1104
+ if (!position)
1105
+ return false;
1106
+ return position.position_qty > 0;
1107
+ }, [position]);
1108
+ const oppositeSide = React2.useMemo(() => {
1109
+ return isLong ? types.OrderSide.SELL : types.OrderSide.BUY;
1110
+ }, [isLong]);
1111
+ const maxOpenQty = hooks.useMaxQty(symbol, oppositeSide, false);
1112
+ const reverseQty = React2.useMemo(() => {
1113
+ if (!position)
1114
+ return 0;
1115
+ const desiredQty = positionQty;
1116
+ if (desiredQty > maxOpenQty && maxOpenQty > 0) {
1117
+ return maxOpenQty;
1118
+ }
1119
+ return desiredQty;
1120
+ }, [positionQty, maxOpenQty]);
1121
+ const [doCreateOrder, { isMutating }] = hooks.useSubAccountMutation(
1122
+ "/v1/order",
1123
+ "POST",
1124
+ {
1125
+ accountId: position?.account_id
1126
+ }
1127
+ );
1128
+ const reversePosition = React2.useCallback(async () => {
1129
+ if (!position || positionQty === 0) {
1130
+ ui.toast.error("No position to reverse");
1131
+ return false;
1132
+ }
1133
+ try {
1134
+ const closeSide = isLong ? types.OrderSide.SELL : types.OrderSide.BUY;
1135
+ const closeOrder = await doCreateOrder({
1136
+ symbol: position.symbol,
1137
+ order_type: types.OrderType.MARKET,
1138
+ side: closeSide,
1139
+ order_quantity: new utils.Decimal(positionQty).toString(),
1140
+ reduce_only: true
1141
+ });
1142
+ const openSide = isLong ? types.OrderSide.SELL : types.OrderSide.BUY;
1143
+ const openOrder = await doCreateOrder({
1144
+ symbol: position.symbol,
1145
+ order_type: types.OrderType.MARKET,
1146
+ side: openSide,
1147
+ order_quantity: new utils.Decimal(reverseQty).toString(),
1148
+ reduce_only: false
1149
+ });
1150
+ if (!openOrder.success) {
1151
+ throw new Error(
1152
+ openOrder.message || "Failed to open opposite position"
1153
+ );
1154
+ }
1155
+ onSuccess?.();
1156
+ return true;
1157
+ } catch (error) {
1158
+ onError?.(error);
1159
+ return false;
1160
+ }
1161
+ }, [position, positionQty, reverseQty, isLong, doCreateOrder, t, onSuccess]);
1162
+ const displayInfo = React2.useMemo(() => {
1163
+ if (!position || !symbolInfo) {
1164
+ return null;
1165
+ }
1166
+ const base = symbolInfo("base");
1167
+ const quote = symbolInfo("quote");
1168
+ const baseDp = symbolInfo("base_dp");
1169
+ const quoteDp = symbolInfo("quote_dp");
1170
+ const leverage = position.leverage || 1;
1171
+ return {
1172
+ symbol: position.symbol,
1173
+ base,
1174
+ quote,
1175
+ baseDp,
1176
+ quoteDp,
1177
+ positionQty: new utils.Decimal(positionQty).todp(baseDp).toString(),
1178
+ reverseQty: new utils.Decimal(reverseQty).todp(baseDp).toString(),
1179
+ markPrice: symbolMarketPrice ? new utils.Decimal(symbolMarketPrice).todp(quoteDp).toString() : "--",
1180
+ leverage,
1181
+ isLong
1182
+ };
1183
+ }, [
1184
+ position,
1185
+ symbolMarketPrice,
1186
+ symbolInfo,
1187
+ positionQty,
1188
+ reverseQty,
1189
+ isLong
1190
+ ]);
1191
+ return {
1192
+ isEnabled,
1193
+ setEnabled,
1194
+ reversePosition,
1195
+ isReversing: isMutating,
1196
+ displayInfo,
1197
+ positionQty,
1198
+ reverseQty,
1199
+ isLong
1200
+ };
1201
+ };
1202
+ var ReversePositionWidget = (props) => {
1203
+ const { position, close, resolve, reject } = props;
1204
+ const { t } = i18n.useTranslation();
1205
+ const { visible, hide, onOpenChange } = ui.useModal();
1206
+ const state = useReversePositionScript({
1207
+ position,
1208
+ onSuccess: () => {
1209
+ resolve?.(true);
1210
+ hide();
1211
+ },
1212
+ onError: (error) => {
1213
+ reject?.(error);
1214
+ hide();
1215
+ }
1216
+ });
1217
+ const actions = React2.useMemo(() => {
1218
+ return {
1219
+ primary: {
1220
+ label: t("common.confirm"),
1221
+ onClick: async () => {
1222
+ try {
1223
+ const result = await state.reversePosition();
1224
+ if (result) {
1225
+ resolve?.(true);
1226
+ hide();
1227
+ return true;
1228
+ } else {
1229
+ reject?.(false);
1230
+ return false;
1231
+ }
1232
+ } catch (error) {
1233
+ reject?.(error);
1234
+ throw error;
1235
+ }
1236
+ },
1237
+ loading: state.isReversing,
1238
+ disabled: state.isReversing || !state.displayInfo
1239
+ },
1240
+ secondary: {
1241
+ label: t("common.cancel"),
1242
+ onClick: async () => {
1243
+ reject?.("cancel");
1244
+ hide();
1245
+ return false;
1246
+ }
1247
+ }
1248
+ };
1249
+ }, [state, t, resolve, reject, hide]);
1250
+ return /* @__PURE__ */ jsxRuntime.jsx(
1251
+ ui.SimpleDialog,
1252
+ {
1253
+ open: visible,
1254
+ onOpenChange,
1255
+ size: "sm",
1256
+ title: i18n.i18n.t("positions.reverse.title"),
1257
+ classNames: {
1258
+ content: "oui-border oui-border-line-6"
1259
+ },
1260
+ actions,
1261
+ children: /* @__PURE__ */ jsxRuntime.jsx(ReversePosition, { ...state })
1262
+ }
1263
+ );
1264
+ };
1265
+ var ReversePositionDialogId = "ReversePositionDialogId";
1266
+ ui.registerSimpleDialog(
1267
+ ReversePositionDialogId,
1268
+ ReversePositionWidget,
1269
+ {
1270
+ size: "sm",
1271
+ classNames: {
1272
+ content: "oui-border oui-border-line-6"
1273
+ },
1274
+ title: () => i18n.i18n.t("positions.reverse.title")
1275
+ }
1276
+ );
879
1277
  var PositionsTabName = /* @__PURE__ */ ((PositionsTabName2) => {
880
1278
  PositionsTabName2["Positions"] = "positions";
881
1279
  PositionsTabName2["PositionHistory"] = "positionHistory";
@@ -892,7 +1290,7 @@ function useTabSort(options) {
892
1290
  sortOrder: "desc"
893
1291
  }
894
1292
  });
895
- const onTabSort = React.useCallback(
1293
+ const onTabSort = React2.useCallback(
896
1294
  (type) => (sort) => {
897
1295
  setTabSort({ ...tabSort, [type]: sort });
898
1296
  },
@@ -917,6 +1315,7 @@ var usePositionsScript = (props) => {
917
1315
  // Default to true for backward compatibility
918
1316
  } = props;
919
1317
  const { pagination, setPage } = ui.usePagination({ pageSize: 50 });
1318
+ const { isEnabled: positionReverse } = useReversePositionEnabled();
920
1319
  const { tabSort, onTabSort } = useTabSort({
921
1320
  storageKey: TRADING_POSITIONS_SORT_STORAGE_KEY
922
1321
  });
@@ -924,7 +1323,7 @@ var usePositionsScript = (props) => {
924
1323
  enableSortingStorage ? tabSort?.["positions" /* Positions */] : void 0,
925
1324
  enableSortingStorage ? onTabSort("positions" /* Positions */) : void 0
926
1325
  );
927
- React__default.default.useEffect(() => {
1326
+ React2__default.default.useEffect(() => {
928
1327
  setPage(1);
929
1328
  }, [symbol]);
930
1329
  const [data, , { isLoading }] = hooks.usePositionStream(symbol, {
@@ -943,19 +1342,20 @@ var usePositionsScript = (props) => {
943
1342
  onSymbolChange,
944
1343
  pagination,
945
1344
  onSort,
1345
+ positionReverse,
946
1346
  initialSort: enableSortingStorage ? tabSort?.["positions" /* Positions */] : void 0
947
1347
  };
948
1348
  };
949
- var SymbolContext = React.createContext(
1349
+ var SymbolContext = React2.createContext(
950
1350
  {}
951
1351
  );
952
1352
  var useSymbolContext = () => {
953
- return React.useContext(SymbolContext);
1353
+ return React2.useContext(SymbolContext);
954
1354
  };
955
1355
  var SymbolProvider = (props) => {
956
1356
  const { symbol, children } = props;
957
1357
  const symbolInfo = hooks.useSymbolsInfo()[symbol];
958
- const memoizedValue = React.useMemo(() => {
1358
+ const memoizedValue = React2.useMemo(() => {
959
1359
  return {
960
1360
  symbol,
961
1361
  base_dp: symbolInfo("base_dp"),
@@ -993,8 +1393,8 @@ var RwaStatusTag = ({ symbol }) => {
993
1393
  };
994
1394
  var QuantitySlider = (props) => {
995
1395
  const { t } = i18n.useTranslation();
996
- const [sliderValue, setSliderValue] = React.useState(props.value);
997
- React.useEffect(() => {
1396
+ const [sliderValue, setSliderValue] = React2.useState(props.value);
1397
+ React2.useEffect(() => {
998
1398
  setSliderValue(props.value);
999
1399
  }, [props.value]);
1000
1400
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -1445,11 +1845,11 @@ var DesktopClosePosition = (props) => {
1445
1845
  ] });
1446
1846
  };
1447
1847
  var useClosePositionScript = (props) => {
1448
- const [sheetOpen, setSheetOpen] = React.useState(false);
1449
- const [dialogOpen, setDialogOpen] = React.useState(false);
1450
- const [popoverOpen, setPopoverOpen] = React.useState(false);
1451
- const [sliderValue, setSliderValue] = React.useState(100);
1452
- const quantityInputRef = React.useRef(null);
1848
+ const [sheetOpen, setSheetOpen] = React2.useState(false);
1849
+ const [dialogOpen, setDialogOpen] = React2.useState(false);
1850
+ const [popoverOpen, setPopoverOpen] = React2.useState(false);
1851
+ const [sliderValue, setSliderValue] = React2.useState(100);
1852
+ const quantityInputRef = React2.useRef(null);
1453
1853
  const [orderConfirm] = hooks.useLocalStorage("orderly_order_confirm", true);
1454
1854
  const {
1455
1855
  position,
@@ -1472,19 +1872,19 @@ var useClosePositionScript = (props) => {
1472
1872
  const closeType = props.type || type;
1473
1873
  const isMarketClose = closeType === types.OrderType.MARKET;
1474
1874
  const isEntirePosition = maxQty?.toString() === quantity.toString();
1475
- React.useEffect(() => {
1875
+ React2.useEffect(() => {
1476
1876
  if (sheetOpen) {
1477
1877
  updateOrderType(props.type);
1478
1878
  }
1479
1879
  }, [props.type, sheetOpen]);
1480
- const { priceErrorMsg, quantityErrorMsg } = React.useMemo(() => {
1880
+ const { priceErrorMsg, quantityErrorMsg } = React2.useMemo(() => {
1481
1881
  return {
1482
1882
  priceErrorMsg: getErrorMsg("order_price"),
1483
1883
  quantityErrorMsg: getErrorMsg("order_quantity")
1484
1884
  };
1485
1885
  }, [errors]);
1486
1886
  const disabled = !!(priceErrorMsg || quantityErrorMsg);
1487
- const formatQuantityToBaseTick = React.useCallback(
1887
+ const formatQuantityToBaseTick = React2.useCallback(
1488
1888
  (value) => {
1489
1889
  if (baseTick && baseTick > 0) {
1490
1890
  const formatQty = hooks.utils.formatNumber(value, baseTick) ?? value;
@@ -1493,7 +1893,7 @@ var useClosePositionScript = (props) => {
1493
1893
  },
1494
1894
  [baseTick, updateQuantity]
1495
1895
  );
1496
- const onSliderValueChange = React.useCallback(
1896
+ const onSliderValueChange = React2.useCallback(
1497
1897
  (value) => {
1498
1898
  setSliderValue(value);
1499
1899
  const qty = new utils.Decimal(value).div(100).mul(maxQty).toFixed(base_dp, utils.Decimal.ROUND_DOWN);
@@ -1501,38 +1901,38 @@ var useClosePositionScript = (props) => {
1501
1901
  },
1502
1902
  [maxQty, base_dp, formatQuantityToBaseTick]
1503
1903
  );
1504
- React.useEffect(() => {
1904
+ React2.useEffect(() => {
1505
1905
  const qty = Math.min(Number(quantity || 0), maxQty);
1506
1906
  const slider = new utils.Decimal(qty).div(maxQty).mul(100).toDecimalPlaces(2, utils.Decimal.ROUND_DOWN).toNumber();
1507
1907
  setSliderValue(slider);
1508
1908
  }, [quantity]);
1509
- const onMax = React.useCallback(() => {
1909
+ const onMax = React2.useCallback(() => {
1510
1910
  updateQuantity(maxQty?.toString());
1511
1911
  }, [maxQty, updateQuantity]);
1512
- const onConfirm = React.useCallback(() => {
1912
+ const onConfirm = React2.useCallback(() => {
1513
1913
  return onSubmit().then((res) => {
1514
1914
  setSheetOpen(false);
1515
1915
  setDialogOpen(false);
1516
1916
  setPopoverOpen(false);
1517
1917
  });
1518
1918
  }, [onSubmit]);
1519
- const onDoubleConfirm = React.useCallback(() => {
1919
+ const onDoubleConfirm = React2.useCallback(() => {
1520
1920
  if (!orderConfirm) {
1521
1921
  return onConfirm();
1522
1922
  }
1523
1923
  setDialogOpen(true);
1524
1924
  return Promise.resolve();
1525
1925
  }, [onConfirm, orderConfirm]);
1526
- const onCloseSheet = React.useCallback(() => {
1926
+ const onCloseSheet = React2.useCallback(() => {
1527
1927
  setSheetOpen(false);
1528
1928
  }, []);
1529
- const onCloseDialog = React.useCallback(() => {
1929
+ const onCloseDialog = React2.useCallback(() => {
1530
1930
  setDialogOpen(false);
1531
1931
  }, []);
1532
- const onClosePopover = React.useCallback(() => {
1932
+ const onClosePopover = React2.useCallback(() => {
1533
1933
  setPopoverOpen(false);
1534
1934
  }, []);
1535
- const onEntirePosition = React.useCallback(() => {
1935
+ const onEntirePosition = React2.useCallback(() => {
1536
1936
  updateQuantity("0");
1537
1937
  quantityInputRef.current?.focus();
1538
1938
  setTimeout(() => {
@@ -1699,10 +2099,21 @@ var PartialTPSL = (props) => {
1699
2099
  slTriggerPrice,
1700
2100
  direction = "column"
1701
2101
  } = props;
1702
- const { partialTPSLOrder: order, quoteDp, baseDp } = usePositionsRowContext();
2102
+ const {
2103
+ partialTPSLOrder: order,
2104
+ quoteDp,
2105
+ baseDp,
2106
+ position
2107
+ } = usePositionsRowContext();
1703
2108
  const symbolInfo = hooks.useSymbolsInfo();
1704
2109
  const { t } = i18n.useTranslation();
1705
- const child = React.useMemo(() => {
2110
+ const side = position.position_qty > 0 ? types.OrderSide.BUY : types.OrderSide.SELL;
2111
+ const slPriceError = hooks.useTpslPriceChecker({
2112
+ slPrice: slTriggerPrice?.toString() ?? void 0,
2113
+ liqPrice: position.est_liq_price ?? null,
2114
+ side
2115
+ });
2116
+ const child = React2.useMemo(() => {
1706
2117
  const children = [];
1707
2118
  if (!order?.symbol)
1708
2119
  return /* @__PURE__ */ jsxRuntime.jsx(AddIcon, { positionType: types.PositionType.PARTIAL });
@@ -1734,6 +2145,7 @@ var PartialTPSL = (props) => {
1734
2145
  rule: "price",
1735
2146
  dp: symbolInfo[order.symbol]("quote_dp", 2),
1736
2147
  prefix: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { intensity: 54, children: `${t("tpsl.sl")} - ` }),
2148
+ suffix: /* @__PURE__ */ jsxRuntime.jsx(uiTpsl.CloseToLiqPriceIcon, { slPriceError }),
1737
2149
  children: slTriggerPrice
1738
2150
  },
1739
2151
  "sl"
@@ -1746,7 +2158,7 @@ var PartialTPSL = (props) => {
1746
2158
  children.splice(1, 0, /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "/" }, "split"));
1747
2159
  }
1748
2160
  return children;
1749
- }, [tpTriggerPrice, slTriggerPrice, order?.symbol, t]);
2161
+ }, [tpTriggerPrice, slTriggerPrice, order?.symbol, t, slPriceError]);
1750
2162
  const hasTPSL = Array.isArray(child) ? !!child.length : !child;
1751
2163
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { className: "oui-gap-[6px]", children: [
1752
2164
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1769,6 +2181,29 @@ var PartialTPSL = (props) => {
1769
2181
  ] })
1770
2182
  ] });
1771
2183
  };
2184
+ var ReversePositionButton = (props) => {
2185
+ const { position } = props;
2186
+ return /* @__PURE__ */ jsxRuntime.jsx(
2187
+ "div",
2188
+ {
2189
+ className: "",
2190
+ style: { transform: "rotate(90deg)" },
2191
+ onClick: () => {
2192
+ ui.modal.show(ReversePositionDialogId, {
2193
+ position
2194
+ });
2195
+ },
2196
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2197
+ ui.ArrowLeftRightIcon,
2198
+ {
2199
+ size: 15,
2200
+ opacity: 1,
2201
+ className: "oui-cursor-pointer oui-text-base-contrast-54 hover:oui-text-base-contrast-80"
2202
+ }
2203
+ )
2204
+ }
2205
+ );
2206
+ };
1772
2207
  var ShareButton = (props) => {
1773
2208
  if (!props.sharePnLConfig) {
1774
2209
  return null;
@@ -1790,7 +2225,7 @@ var useShareButtonScript = (props) => {
1790
2225
  const { getFirstRefCode } = hooks.useReferralInfo();
1791
2226
  const symbolsInfo = hooks.useSymbolsInfo();
1792
2227
  const { data: accountInfo } = hooks.useAccountInfo();
1793
- const refCode = React.useMemo(() => {
2228
+ const refCode = React2.useMemo(() => {
1794
2229
  return getFirstRefCode()?.code;
1795
2230
  }, [getFirstRefCode]);
1796
2231
  const symbolLeverage = hooks.useLeverageBySymbol(position.symbol);
@@ -1869,6 +2304,12 @@ var ShareButtonWidget = (props) => {
1869
2304
  var TriggerPrice = (props) => {
1870
2305
  const { stopLossPrice, takeProfitPrice } = props;
1871
2306
  const { tpslOrder, position } = usePositionsRowContext();
2307
+ const side = position.position_qty > 0 ? types.OrderSide.BUY : types.OrderSide.SELL;
2308
+ const slPriceError = hooks.useTpslPriceChecker({
2309
+ slPrice: stopLossPrice?.toString() ?? void 0,
2310
+ liqPrice: position.est_liq_price ?? null,
2311
+ side
2312
+ });
1872
2313
  return /* @__PURE__ */ jsxRuntime.jsx(
1873
2314
  TPSLTriggerPrice,
1874
2315
  {
@@ -1877,6 +2318,7 @@ var TriggerPrice = (props) => {
1877
2318
  direction: "column",
1878
2319
  order: tpslOrder,
1879
2320
  position,
2321
+ slPriceError,
1880
2322
  tooltip: true
1881
2323
  }
1882
2324
  );
@@ -1916,7 +2358,7 @@ var TPSLTriggerPrice = (props) => {
1916
2358
  const { direction = "row", order, position } = props;
1917
2359
  const symbolInfo = hooks.useSymbolsInfo();
1918
2360
  const { t } = i18n.useTranslation();
1919
- const pnl = React.useMemo(() => {
2361
+ const pnl = React2.useMemo(() => {
1920
2362
  const msgs = [];
1921
2363
  if (!props.tooltip || !order || !position)
1922
2364
  return;
@@ -1967,7 +2409,7 @@ var TPSLTriggerPrice = (props) => {
1967
2409
  order?.quantity,
1968
2410
  order?.algo_type
1969
2411
  ]);
1970
- const child = React.useMemo(() => {
2412
+ const child = React2.useMemo(() => {
1971
2413
  const children = [];
1972
2414
  if (!order?.symbol)
1973
2415
  return /* @__PURE__ */ jsxRuntime.jsx(AddIcon, { positionType: types.PositionType.FULL });
@@ -1999,7 +2441,8 @@ var TPSLTriggerPrice = (props) => {
1999
2441
  rule: "price",
2000
2442
  dp: symbolInfo[order.symbol]("quote_dp", 2),
2001
2443
  children: props.stopLossPrice,
2002
- prefix: !props.takeProfitPrice || direction === "column" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { intensity: 54, children: `${t("tpsl.sl")} - ` }) : ""
2444
+ prefix: !props.takeProfitPrice || direction === "column" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { intensity: 54, children: `${t("tpsl.sl")} - ` }) : "",
2445
+ suffix: /* @__PURE__ */ jsxRuntime.jsx(uiTpsl.CloseToLiqPriceIcon, { slPriceError: props.slPriceError })
2003
2446
  },
2004
2447
  "sl"
2005
2448
  )
@@ -2011,7 +2454,13 @@ var TPSLTriggerPrice = (props) => {
2011
2454
  children.splice(1, 0, /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "/" }, "split"));
2012
2455
  }
2013
2456
  return children;
2014
- }, [props.takeProfitPrice, props.stopLossPrice, order?.symbol, t]);
2457
+ }, [
2458
+ props.takeProfitPrice,
2459
+ props.stopLossPrice,
2460
+ order?.symbol,
2461
+ t,
2462
+ props.slPriceError
2463
+ ]);
2015
2464
  const content = /* @__PURE__ */ jsxRuntime.jsx(
2016
2465
  "div",
2017
2466
  {
@@ -2146,10 +2595,15 @@ var UnselIcon = () => {
2146
2595
  );
2147
2596
  };
2148
2597
  var useColumn = (config) => {
2149
- const { pnlNotionalDecimalPrecision, sharePnLConfig, onSymbolChange } = config;
2598
+ const {
2599
+ pnlNotionalDecimalPrecision,
2600
+ sharePnLConfig,
2601
+ onSymbolChange,
2602
+ positionReverse
2603
+ } = config;
2150
2604
  const { t } = i18n.useTranslation();
2151
- React.useRef(Date.now().toString());
2152
- const column = React.useMemo(
2605
+ React2.useRef(Date.now().toString());
2606
+ const column = React2.useMemo(
2153
2607
  () => [
2154
2608
  {
2155
2609
  title: t("common.symbol"),
@@ -2417,14 +2871,17 @@ var useColumn = (config) => {
2417
2871
  title: null,
2418
2872
  dataIndex: "close_position",
2419
2873
  align: "right",
2420
- width: 70,
2874
+ width: positionReverse ? 100 : 70,
2421
2875
  fixed: "right",
2422
- render() {
2423
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { gapX: 2, justify: "end", children: /* @__PURE__ */ jsxRuntime.jsx(ClosePositionWidget, {}) });
2876
+ render(_, record) {
2877
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gapX: 2, justify: "end", children: [
2878
+ /* @__PURE__ */ jsxRuntime.jsx(ClosePositionWidget, {}),
2879
+ positionReverse && /* @__PURE__ */ jsxRuntime.jsx(ReversePositionButton, { position: record })
2880
+ ] });
2424
2881
  }
2425
2882
  }
2426
2883
  ],
2427
- [pnlNotionalDecimalPrecision, sharePnLConfig, t]
2884
+ [pnlNotionalDecimalPrecision, sharePnLConfig, t, positionReverse]
2428
2885
  );
2429
2886
  return column;
2430
2887
  };
@@ -2604,23 +3061,51 @@ var LiqPrice = (props) => {
2604
3061
  var TPSLPrice = (props) => {
2605
3062
  const { item } = props;
2606
3063
  const { t } = i18n.useTranslation();
2607
- const fullTPSL = React.useMemo(() => {
3064
+ const slPriceError = hooks.useTpslPriceChecker({
3065
+ slPrice: item.full_tp_sl?.sl_trigger_price?.toString() ?? void 0,
3066
+ liqPrice: item.est_liq_price ?? null,
3067
+ side: item.position_qty > 0 ? types.OrderSide.BUY : types.OrderSide.SELL
3068
+ });
3069
+ const partialSlPriceError = hooks.useTpslPriceChecker({
3070
+ slPrice: item.partial_tp_sl?.sl_trigger_price?.toString() ?? void 0,
3071
+ liqPrice: item.est_liq_price ?? null,
3072
+ side: item.position_qty > 0 ? types.OrderSide.BUY : types.OrderSide.SELL
3073
+ });
3074
+ const fullTPSL = React2.useMemo(() => {
2608
3075
  if (item.full_tp_sl?.tp_trigger_price == null && item.full_tp_sl?.sl_trigger_price == null)
2609
3076
  return /* @__PURE__ */ jsxRuntime.jsx(AddIcon, { positionType: types.PositionType.FULL });
2610
3077
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { className: "oui-gap-[2px]", children: [
2611
3078
  item.full_tp_sl?.tp_trigger_price && /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { color: "buy", children: item.full_tp_sl.tp_trigger_price }),
2612
3079
  item.full_tp_sl?.sl_trigger_price && "/",
2613
- item.full_tp_sl?.sl_trigger_price && /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { color: "sell", children: item.full_tp_sl.sl_trigger_price }),
3080
+ item.full_tp_sl?.sl_trigger_price && /* @__PURE__ */ jsxRuntime.jsx(
3081
+ ui.Text.numeral,
3082
+ {
3083
+ as: "div",
3084
+ color: "sell",
3085
+ suffix: /* @__PURE__ */ jsxRuntime.jsx(uiTpsl.CloseToLiqPriceIcon, { slPriceError }),
3086
+ className: "oui-flex oui-items-center",
3087
+ children: item.full_tp_sl.sl_trigger_price
3088
+ }
3089
+ ),
2614
3090
  /* @__PURE__ */ jsxRuntime.jsx(TPSLEditIcon, {})
2615
3091
  ] });
2616
3092
  }, [item.full_tp_sl]);
2617
- const partialTPSL = React.useMemo(() => {
3093
+ const partialTPSL = React2.useMemo(() => {
2618
3094
  if (item.partial_tp_sl?.tp_trigger_price == null && item.partial_tp_sl?.sl_trigger_price == null)
2619
3095
  return /* @__PURE__ */ jsxRuntime.jsx(AddIcon, { positionType: types.PositionType.PARTIAL });
2620
3096
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { className: "oui-gap-[2px]", itemAlign: "center", children: [
2621
3097
  item.partial_tp_sl?.tp_trigger_price && /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { color: "buy", children: item.partial_tp_sl.tp_trigger_price }),
2622
3098
  item.partial_tp_sl?.sl_trigger_price && "/",
2623
- item.partial_tp_sl?.sl_trigger_price && /* @__PURE__ */ jsxRuntime.jsx(ui.Text.numeral, { color: "sell", children: item.partial_tp_sl.sl_trigger_price }),
3099
+ item.partial_tp_sl?.sl_trigger_price && /* @__PURE__ */ jsxRuntime.jsx(
3100
+ ui.Text.numeral,
3101
+ {
3102
+ as: "div",
3103
+ color: "sell",
3104
+ suffix: /* @__PURE__ */ jsxRuntime.jsx(uiTpsl.CloseToLiqPriceIcon, { slPriceError: partialSlPriceError }),
3105
+ className: "oui-flex oui-items-center",
3106
+ children: item.partial_tp_sl.sl_trigger_price
3107
+ }
3108
+ ),
2624
3109
  /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: `(${item.partial_tp_sl?.order_num})` }),
2625
3110
  /* @__PURE__ */ jsxRuntime.jsx(TPSLEditIcon, {})
2626
3111
  ] });
@@ -2691,7 +3176,10 @@ var PositionCell = (props) => {
2691
3176
  /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { intensity: 6, className: "oui-w-full" }),
2692
3177
  body,
2693
3178
  /* @__PURE__ */ jsxRuntime.jsx(TPSLPrice, { ...rest }),
2694
- buttons
3179
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "between", width: "100%", gap: 2, children: [
3180
+ buttons,
3181
+ props.positionReverse && /* @__PURE__ */ jsxRuntime.jsx(ReversePositionButton, { position: props.item })
3182
+ ] })
2695
3183
  ]
2696
3184
  }
2697
3185
  );
@@ -2712,12 +3200,12 @@ var PositionCellWidget = (props) => {
2712
3200
  var PositionsRowProvider = (props) => {
2713
3201
  const { position, children, mutatePositions } = props;
2714
3202
  const { t } = i18n.useTranslation();
2715
- const [quantity, setQuantity] = React.useState(
3203
+ const [quantity, setQuantity] = React2.useState(
2716
3204
  Math.abs(position.position_qty).toString()
2717
3205
  );
2718
- const [price, setPrice] = React.useState("");
2719
- const [type, setType] = React.useState(types.OrderType.MARKET);
2720
- React.useEffect(() => {
3206
+ const [price, setPrice] = React2.useState("");
3207
+ const [type, setType] = React2.useState(types.OrderType.MARKET);
3208
+ React2.useEffect(() => {
2721
3209
  setQuantity(Math.abs(position.position_qty).toString());
2722
3210
  }, [position.position_qty]);
2723
3211
  const symbol = position.symbol;
@@ -2741,7 +3229,7 @@ var PositionsRowProvider = (props) => {
2741
3229
  price
2742
3230
  }
2743
3231
  });
2744
- const updateQuantity = React.useCallback(
3232
+ const updateQuantity = React2.useCallback(
2745
3233
  (value) => {
2746
3234
  const newValues = calculate(
2747
3235
  {},
@@ -2754,7 +3242,7 @@ var PositionsRowProvider = (props) => {
2754
3242
  },
2755
3243
  [calculate, symbolsInfo, position.mark_price]
2756
3244
  );
2757
- const updatePriceChange = React.useCallback(
3245
+ const updatePriceChange = React2.useCallback(
2758
3246
  (value) => {
2759
3247
  const newValues = calculate(
2760
3248
  {},
@@ -2767,14 +3255,14 @@ var PositionsRowProvider = (props) => {
2767
3255
  },
2768
3256
  [calculate, symbolsInfo, position.mark_price]
2769
3257
  );
2770
- const updateOrderType = React.useCallback(
3258
+ const updateOrderType = React2.useCallback(
2771
3259
  (type2) => {
2772
3260
  setType(type2);
2773
3261
  setPrice(type2 === types.OrderType.LIMIT ? position.mark_price?.toString() : "");
2774
3262
  },
2775
3263
  [position.mark_price]
2776
3264
  );
2777
- const onSubmit = React.useCallback(async () => {
3265
+ const onSubmit = React2.useCallback(async () => {
2778
3266
  if (Number(quantity) > symbolInfo("base_max")) {
2779
3267
  ui.toast.error(
2780
3268
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
@@ -2805,7 +3293,7 @@ var PositionsRowProvider = (props) => {
2805
3293
  return false;
2806
3294
  });
2807
3295
  }, [submit]);
2808
- const memoizedValue = React.useMemo(() => {
3296
+ const memoizedValue = React2.useMemo(() => {
2809
3297
  return {
2810
3298
  quantity,
2811
3299
  price,
@@ -2858,12 +3346,14 @@ var Positions = (props) => {
2858
3346
  pagination,
2859
3347
  isLoading,
2860
3348
  dataSource,
2861
- onSymbolChange
3349
+ onSymbolChange,
3350
+ positionReverse
2862
3351
  } = props;
2863
3352
  const columns = useColumn({
2864
3353
  pnlNotionalDecimalPrecision,
2865
3354
  sharePnLConfig,
2866
- onSymbolChange
3355
+ onSymbolChange,
3356
+ positionReverse
2867
3357
  });
2868
3358
  return /* @__PURE__ */ jsxRuntime.jsx(
2869
3359
  uiConnector.AuthGuardDataTable,
@@ -2896,7 +3386,8 @@ var MobilePositions = (props) => {
2896
3386
  pnlNotionalDecimalPrecision,
2897
3387
  sharePnLConfig,
2898
3388
  dataSource,
2899
- onSymbolChange
3389
+ onSymbolChange,
3390
+ positionReverse
2900
3391
  } = props;
2901
3392
  return /* @__PURE__ */ jsxRuntime.jsx(
2902
3393
  ui.ListView,
@@ -2911,7 +3402,8 @@ var MobilePositions = (props) => {
2911
3402
  index,
2912
3403
  pnlNotionalDecimalPrecision,
2913
3404
  sharePnLConfig,
2914
- onSymbolChange
3405
+ onSymbolChange,
3406
+ positionReverse
2915
3407
  }
2916
3408
  ) }) })
2917
3409
  }
@@ -2988,7 +3480,7 @@ var CombinePositionsWidget = (props) => {
2988
3480
  var usePositionHistoryColumn = (props) => {
2989
3481
  const { onSymbolChange, pnlNotionalDecimalPrecision } = props;
2990
3482
  const { t } = i18n.useTranslation();
2991
- const column = React.useMemo(
3483
+ const column = React2.useMemo(
2992
3484
  () => [
2993
3485
  // instrument
2994
3486
  {
@@ -3118,7 +3610,7 @@ var usePositionHistoryColumn = (props) => {
3118
3610
  var SymbolInfo = (props) => {
3119
3611
  const { record, onSymbolChange } = props;
3120
3612
  const { t } = i18n.useTranslation();
3121
- const tags = React.useMemo(() => {
3613
+ const tags = React2.useMemo(() => {
3122
3614
  const list = [];
3123
3615
  const status = record.position_status;
3124
3616
  const renderStatus = () => {
@@ -3387,10 +3879,10 @@ var usePositionHistoryScript = (props) => {
3387
3879
  filterItems,
3388
3880
  onFilter
3389
3881
  } = useFilter();
3390
- React.useEffect(() => {
3882
+ React2.useEffect(() => {
3391
3883
  setPage(1);
3392
3884
  }, [status, side, dateRange, filterDays, symbol]);
3393
- const filterData = React.useMemo(() => {
3885
+ const filterData = React2.useMemo(() => {
3394
3886
  if (data == null)
3395
3887
  return data;
3396
3888
  return data.filter((item) => {
@@ -3424,18 +3916,18 @@ var usePositionHistoryScript = (props) => {
3424
3916
  };
3425
3917
  var useFilter = () => {
3426
3918
  const { t } = i18n.useTranslation();
3427
- const [status, setStatus] = React.useState(
3919
+ const [status, setStatus] = React2.useState(
3428
3920
  "all" /* all */
3429
3921
  );
3430
- const [side, setSide] = React.useState(
3922
+ const [side, setSide] = React2.useState(
3431
3923
  "all" /* all */
3432
3924
  );
3433
3925
  const defaultRange = formatDatePickerRange({
3434
3926
  to: offsetEndOfDay(/* @__PURE__ */ new Date()),
3435
3927
  from: offsetStartOfDay(dateFns.subDays(/* @__PURE__ */ new Date(), 89))
3436
3928
  });
3437
- const [filterDays, setFilterDays] = React.useState(90);
3438
- const [dateRange, setDateRange] = React.useState(defaultRange);
3929
+ const [filterDays, setFilterDays] = React2.useState(90);
3930
+ const [dateRange, setDateRange] = React2.useState(defaultRange);
3439
3931
  const updateFilterDays = (days) => {
3440
3932
  setFilterDays(days);
3441
3933
  setDateRange({
@@ -3483,7 +3975,7 @@ var useFilter = () => {
3483
3975
  }
3484
3976
  };
3485
3977
  const { isMobile } = ui.useScreen();
3486
- const filterItems = React.useMemo(() => {
3978
+ const filterItems = React2.useMemo(() => {
3487
3979
  const sideFilter = {
3488
3980
  type: "select",
3489
3981
  name: "side",
@@ -3600,7 +4092,7 @@ var PositionHistoryType = (props) => {
3600
4092
  )
3601
4093
  });
3602
4094
  };
3603
- const tags = React.useMemo(() => {
4095
+ const tags = React2.useMemo(() => {
3604
4096
  const list = [];
3605
4097
  const status = record.position_status;
3606
4098
  const renderStatus = () => {
@@ -3920,7 +4412,7 @@ var PositionHistory = (props) => {
3920
4412
  sharePnLConfig: props.sharePnLConfig
3921
4413
  });
3922
4414
  const { t } = i18n.useTranslation();
3923
- const dayLabel = React.useMemo(() => {
4415
+ const dayLabel = React2.useMemo(() => {
3924
4416
  return {
3925
4417
  1: t("common.select.1d"),
3926
4418
  7: t("common.select.7d"),
@@ -4076,7 +4568,7 @@ var TooltipButton = (props) => {
4076
4568
  };
4077
4569
  var useLiquidationColumn = (props) => {
4078
4570
  const { t } = i18n.useTranslation();
4079
- const column = React.useMemo(
4571
+ const column = React2.useMemo(
4080
4572
  () => [
4081
4573
  // Time
4082
4574
  {
@@ -4292,7 +4784,7 @@ var Header2 = (props) => {
4292
4784
  var Body2 = (props) => {
4293
4785
  const position = props.item.positions_by_perp?.[0];
4294
4786
  const { t } = i18n.useTranslation();
4295
- const mr = React.useMemo(() => {
4787
+ const mr = React2.useMemo(() => {
4296
4788
  if (isNaN(props.item?.margin_ratio))
4297
4789
  return "--";
4298
4790
  return `${new utils.Decimal(props.item.margin_ratio).mul(100).todp(2, utils.Decimal.ROUND_DOWN).toNumber()}%`;
@@ -4395,7 +4887,7 @@ var LiquidationCellWidget = (props) => {
4395
4887
  return /* @__PURE__ */ jsxRuntime.jsx(LiquidationCell, { classNames, ...state });
4396
4888
  };
4397
4889
  var Liquidation = (props) => {
4398
- const [expanded, setExpanded] = React.useState({});
4890
+ const [expanded, setExpanded] = React2.useState({});
4399
4891
  const column = useLiquidationColumn();
4400
4892
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "column", width: "100%", height: "100%", itemAlign: "start", children: [
4401
4893
  /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gap: 3, children: [
@@ -4571,7 +5063,7 @@ var useLiquidationScript = (props) => {
4571
5063
  pageSize: 10
4572
5064
  });
4573
5065
  const { dateRange, filterDays, updateFilterDays, filterItems, onFilter } = useFilter2();
4574
- React.useEffect(() => {
5066
+ React2.useEffect(() => {
4575
5067
  setPage(1);
4576
5068
  }, [symbol, dateRange, filterDays]);
4577
5069
  const [data, { meta, isLoading, loadMore }] = useLiquidation({
@@ -4603,10 +5095,10 @@ var useLiquidation = (props) => {
4603
5095
  formatter: (data2) => data2,
4604
5096
  revalidateOnFocus: true
4605
5097
  });
4606
- const meta = React.useMemo(() => {
5098
+ const meta = React2.useMemo(() => {
4607
5099
  return ordersResponse.data?.[0]?.meta;
4608
5100
  }, [ordersResponse.data?.[0]]);
4609
- const data = React.useMemo(() => {
5101
+ const data = React2.useMemo(() => {
4610
5102
  return ordersResponse.data?.map(
4611
5103
  (item) => (
4612
5104
  // @ts-ignore
@@ -4636,8 +5128,8 @@ var useFilter2 = () => {
4636
5128
  to: offsetEndOfDay(/* @__PURE__ */ new Date()),
4637
5129
  from: offsetStartOfDay(dateFns.subDays(/* @__PURE__ */ new Date(), 89))
4638
5130
  });
4639
- const [filterDays, setFilterDays] = React.useState(90);
4640
- const [dateRange, setDateRange] = React.useState(defaultRange);
5131
+ const [filterDays, setFilterDays] = React2.useState(90);
5132
+ const [dateRange, setDateRange] = React2.useState(defaultRange);
4641
5133
  const updateFilterDays = (days) => {
4642
5134
  setFilterDays(days);
4643
5135
  setDateRange({
@@ -4679,7 +5171,7 @@ var useFilter2 = () => {
4679
5171
  }
4680
5172
  };
4681
5173
  const { isMobile } = ui.useScreen();
4682
- const filterItems = React.useMemo(() => {
5174
+ const filterItems = React2.useMemo(() => {
4683
5175
  const dateRangeFilter = {
4684
5176
  type: "range",
4685
5177
  name: "dateRange",
@@ -4757,21 +5249,21 @@ var useCloseAllPositionsScript = (options) => {
4757
5249
  const { t } = i18n.useTranslation();
4758
5250
  const { tracking } = hooks.useTrack();
4759
5251
  const [positionsData] = hooks.usePositionStream(symbol);
4760
- const openPositions = React.useMemo(() => {
5252
+ const openPositions = React2.useMemo(() => {
4761
5253
  if (!positionsData?.rows)
4762
5254
  return [];
4763
5255
  return positionsData.rows.filter(
4764
5256
  (position) => position.position_qty !== 0 && position.position_qty !== void 0
4765
5257
  );
4766
5258
  }, [positionsData]);
4767
- const hasOpenPositions = React.useMemo(() => {
5259
+ const hasOpenPositions = React2.useMemo(() => {
4768
5260
  return openPositions.length > 0;
4769
5261
  }, [openPositions]);
4770
5262
  const [doCreateOrder, { isMutating }] = hooks.useSubAccountMutation(
4771
5263
  "/v1/order",
4772
5264
  "POST"
4773
5265
  );
4774
- const closeAllPositions = React.useCallback(async () => {
5266
+ const closeAllPositions = React2.useCallback(async () => {
4775
5267
  if (!hasOpenPositions)
4776
5268
  return;
4777
5269
  try {
@@ -4799,7 +5291,7 @@ var useCloseAllPositionsScript = (options) => {
4799
5291
  return false;
4800
5292
  }
4801
5293
  }, [openPositions, hasOpenPositions, doCreateOrder, t, onSuccess]);
4802
- const onCloseAll = React.useCallback(() => {
5294
+ const onCloseAll = React2.useCallback(() => {
4803
5295
  ui.modal.confirm({
4804
5296
  title: t("positions.closeAll"),
4805
5297
  content: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "sm", children: t("positions.closeAll.description") }),
@@ -4852,15 +5344,21 @@ exports.MobileLiquidationWidget = MobileLiquidationWidget;
4852
5344
  exports.MobilePositionHistory = MobilePositionHistory;
4853
5345
  exports.MobilePositionHistoryWidget = MobilePositionHistoryWidget;
4854
5346
  exports.MobilePositionsWidget = MobilePositionsWidget;
5347
+ exports.OrderInfoCard = OrderInfoCard;
4855
5348
  exports.PositionHistory = PositionHistory;
4856
5349
  exports.PositionHistoryWidget = PositionHistoryWidget;
4857
5350
  exports.PositionsTabName = PositionsTabName;
4858
5351
  exports.PositionsWidget = PositionsWidget;
5352
+ exports.ReversePosition = ReversePosition;
5353
+ exports.ReversePositionDialogId = ReversePositionDialogId;
5354
+ exports.ReversePositionWidget = ReversePositionWidget;
4859
5355
  exports.sortList = sortList;
4860
5356
  exports.useCloseAllPositionsScript = useCloseAllPositionsScript;
4861
5357
  exports.useLiquidationScript = useLiquidationScript;
4862
5358
  exports.usePositionHistoryScript = usePositionHistoryScript;
4863
5359
  exports.usePositionsRowContext = usePositionsRowContext;
5360
+ exports.useReversePositionEnabled = useReversePositionEnabled;
5361
+ exports.useReversePositionScript = useReversePositionScript;
4864
5362
  exports.useSort = useSort;
4865
5363
  exports.useTabSort = useTabSort;
4866
5364
  //# sourceMappingURL=out.js.map