@orderly.network/ui-order-entry 3.0.0-beta.0 → 3.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
- import React3, { forwardRef, useState, useImperativeHandle, useEffect, memo, createContext, useMemo, useRef, useCallback, useContext, useId } from 'react';
2
- import { useLocalStorage, utils, useOrderlyContext, useMemoizedFn, ERROR_MSG_CODES, usePositionStream, useMarkets, MarketsType, useMarginModes, useMarginModeBySymbol, useGetEstLiqPrice, useEventEmitter, useDebouncedCallback, useFeatureFlag, FlagKeys, useFeeState, useRwaSymbolsInfoStore, useHoldingStream, useAppStore, useIndexPricesStream, useComputedLTV, useBoolean, useQuery, useOrderEntry, useMarginRatio, useTpslPriceChecker, useTrack } from '@orderly.network/hooks';
3
- import { useTranslation, i18n } from '@orderly.network/i18n';
1
+ import React3, { memo, forwardRef, useState, useImperativeHandle, useEffect, createContext, useMemo, useRef, useCallback, useContext, useId } from 'react';
2
+ import { useLocalStorage, utils, useGetEstLiqPrice, useOrderlyContext, useMemoizedFn, ERROR_MSG_CODES, usePositionStream, useFeeState, useRwaSymbolsInfoStore, useMarkets, MarketsType, useMarginModes, useMarginModeBySymbol, useBadgeBySymbol, useEventEmitter, useDebouncedCallback, useHoldingStream, useAppStore, useIndexPricesStream, useComputedLTV, useBoolean, useFeatureFlag, FlagKeys, useQuery, useAccount, useOrderEntry, useMarginRatio, useTpslPriceChecker, useTrack } from '@orderly.network/hooks';
3
+ import { i18n, useTranslation } from '@orderly.network/i18n';
4
4
  import { useOrderEntryFormErrorMsg, useCanTrade } from '@orderly.network/react-app';
5
- import { EMPTY_LIST, DistributionType, TrailingCallbackType, OrderSide, OrderType, PositionType, MarginMode, BBOOrderType, ORDER_ENTRY_EST_LIQ_PRICE_CHANGE, OrderLevel, TrackerEventName } from '@orderly.network/types';
6
- import { ExclamationFillIcon, modal, Text, Tooltip, TooltipTrigger, Flex, Input, cn, inputFormatter, Box, registerSimpleDialog, SimpleDialog, registerSimpleSheet, Select, Grid, Checkbox, Slider, textVariants, SettingFillIcon, injectable, useModal, useScreen, toast, ThrottledButton, Divider, Switch, SimpleSheet, Badge, Button, TokenIcon, DataTable, IconButton, CloseIcon, CloseCircleFillIcon, ChevronRightIcon, InfoCircleIcon, AddCircleIcon, SimpleDropdownMenu, CaretDownIcon, DotStatus, PopoverRoot, PopoverTrigger, PopoverContent, EditIcon as EditIcon$1 } from '@orderly.network/ui';
5
+ import { OrderSide, EMPTY_LIST, DistributionType, TrailingCallbackType, OrderType, MarginMode, PositionType, BBOOrderType, ORDER_ENTRY_EST_LIQ_PRICE_CHANGE, OrderLevel, TrackerEventName } from '@orderly.network/types';
6
+ import { registerSimpleDialog, SimpleDialog, ExclamationFillIcon, modal, Text, Tooltip, TooltipTrigger, Flex, Input, cn, inputFormatter, Box, Slider, textVariants, injectable, Button, ThrottledButton, registerSimpleSheet, Select, Grid, Checkbox, SettingFillIcon, useScreen, InfoCircleIcon, AddCircleIcon, useModal, toast, Divider, Switch, SimpleSheet, Badge, TokenIcon, DataTable, IconButton, CloseIcon, CloseCircleFillIcon, ChevronRightIcon, SymbolBadge as SymbolBadge$1, EditIcon as EditIcon$1, SimpleDropdownMenu, CaretDownIcon, DotStatus, PopoverRoot, PopoverTrigger, PopoverContent } from '@orderly.network/ui';
7
7
  import { TPSLPositionTypeWidget, TPSLAdvancedWidget } from '@orderly.network/ui-tpsl';
8
- import { Decimal, zero, formatSymbol, todpIfNeed, getBBOType, removeTrailingZeros } from '@orderly.network/utils';
8
+ import { Decimal, zero, formatSymbol, removeTrailingZeros, todpIfNeed, getBBOType } from '@orderly.network/utils';
9
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
10
  import { AuthGuard } from '@orderly.network/ui-connector';
11
11
  import { account } from '@orderly.network/perp';
@@ -541,1225 +541,799 @@ var EditIcon = (props) => {
541
541
  }
542
542
  );
543
543
  };
544
- var RegularFeesUI = (props) => {
545
- const { t } = useTranslation();
546
- const { taker, maker } = props;
547
- const originalTrailingFees = /* @__PURE__ */ jsx(
548
- Flex,
549
- {
550
- itemAlign: "center",
551
- justify: "between",
552
- width: "100%",
553
- gap: 1,
554
- className: "oui-orderEntry-fees",
555
- children: /* @__PURE__ */ jsxs(Flex, { width: "100%", itemAlign: "center", justify: "between", children: [
556
- /* @__PURE__ */ jsx(Text, { className: "oui-fees-label oui-truncate", size: "2xs", children: t("common.fees") }),
557
- /* @__PURE__ */ jsx(
558
- AuthGuard,
559
- {
560
- fallback: () => /* @__PURE__ */ jsxs(Text, { className: "oui-truncate", size: "2xs", children: [
561
- t("dmm.taker"),
562
- ": --% / ",
563
- t("dmm.maker"),
564
- ": --%"
565
- ] }),
566
- children: /* @__PURE__ */ jsxs(Flex, { gap: 1, className: "oui-fees-value-container", children: [
567
- /* @__PURE__ */ jsxs(Text, { className: "oui-truncate", size: "2xs", children: [
568
- t("dmm.taker"),
569
- ":"
570
- ] }),
571
- /* @__PURE__ */ jsx(Text, { size: "2xs", className: "oui-text-base-contrast-80", children: taker }),
572
- /* @__PURE__ */ jsx(Text, { size: "2xs", children: "/" }),
573
- /* @__PURE__ */ jsxs(Text, { className: "oui-truncate", size: "2xs", children: [
574
- t("dmm.maker"),
575
- ":"
576
- ] }),
577
- /* @__PURE__ */ jsx(Text, { size: "2xs", className: "oui-text-base-contrast-80", children: maker })
578
- ] })
579
- }
580
- )
581
- ] })
544
+ function isBBOOrder(options2) {
545
+ const { order_type, order_type_ext } = options2;
546
+ const isBBO = [OrderType.ASK, OrderType.BID].includes(order_type_ext);
547
+ if (order_type) {
548
+ return order_type === OrderType.LIMIT && isBBO;
549
+ }
550
+ return isBBO;
551
+ }
552
+ function getOrderTypeByBBO(value, size) {
553
+ if ([BBOOrderType.COUNTERPARTY1, BBOOrderType.COUNTERPARTY5].includes(value)) {
554
+ return size === OrderSide.BUY ? OrderType.ASK : OrderType.BID;
555
+ }
556
+ if ([BBOOrderType.QUEUE1, BBOOrderType.QUEUE5].includes(value)) {
557
+ return size === OrderSide.BUY ? OrderType.BID : OrderType.ASK;
558
+ }
559
+ }
560
+ function getOrderLevelByBBO(value) {
561
+ if ([BBOOrderType.COUNTERPARTY1, BBOOrderType.QUEUE1].includes(value)) {
562
+ return OrderLevel.ONE;
563
+ }
564
+ if ([BBOOrderType.COUNTERPARTY5, BBOOrderType.QUEUE5].includes(value)) {
565
+ return OrderLevel.FIVE;
566
+ }
567
+ }
568
+ function getScaledPlaceOrderMessage(result) {
569
+ const rows = result?.data?.rows || [];
570
+ if (rows.length > 0) {
571
+ const totalCount = rows.length;
572
+ const successCount = rows.filter((row) => row.success).length;
573
+ if (successCount === totalCount) {
574
+ return i18n.t("orderEntry.scaledOrder.fullySuccessful", {
575
+ total: totalCount
576
+ });
582
577
  }
583
- );
584
- return originalTrailingFees;
585
- };
586
- var RegularFeesWidget = (props) => {
587
- return /* @__PURE__ */ jsx(RegularFeesUI, { ...props });
588
- };
589
- var FeesWidget = ({ symbol }) => {
590
- const { takerFee, makerFee, rwaTakerFee, rwaMakerFee } = useFeeState();
591
- const info = useRwaSymbolsInfoStore();
592
- const isRwa = info?.[symbol] !== void 0;
593
- return /* @__PURE__ */ jsx(
594
- RegularFeesWidget,
595
- {
596
- taker: isRwa ? rwaTakerFee : takerFee,
597
- maker: isRwa ? rwaMakerFee : makerFee
578
+ if (successCount === 0) {
579
+ return i18n.t("orderEntry.scaledOrder.allFailed");
598
580
  }
581
+ return i18n.t("orderEntry.scaledOrder.partiallySuccessful", {
582
+ successCount,
583
+ total: totalCount
584
+ });
585
+ }
586
+ }
587
+ var safeNumber = (val) => {
588
+ return Number.isNaN(Number(val)) ? 0 : Number(val);
589
+ };
590
+ var SymbolBadge = (props) => {
591
+ const { brokerId, brokerName, brokerNameRaw } = useBadgeBySymbol(
592
+ props.symbol
599
593
  );
594
+ const badge = brokerName ?? brokerId ?? void 0;
595
+ return /* @__PURE__ */ jsx(SymbolBadge$1, { badge, fullName: brokerNameRaw });
600
596
  };
601
- var options = [0.01, 0.05, 0.1];
602
- var SlippageEditor = forwardRef((props, ref) => {
597
+ var OrderConfirmDialog = (props) => {
598
+ const { symbolInfo, order, onConfirm, onCancel } = props;
599
+ const { quote, quote_dp, base_dp } = symbolInfo;
600
+ const { side, order_type, order_type_ext, level, symbol } = order;
601
+ const orderMarginMode = order.margin_mode;
603
602
  const { t } = useTranslation();
604
- const [value, setValue] = useState();
605
- const [customValue, setCustomValue] = useState("");
606
- const [error, setError] = useState(void 0);
607
- useImperativeHandle(ref, () => ({
608
- getValue: () => customValue ? new Decimal(customValue)?.toNumber() : value
609
- }));
610
- useEffect(() => {
611
- if (props.initialValue && !options.includes(props.initialValue)) {
612
- setCustomValue(props.initialValue.toString());
613
- } else {
614
- setValue(props.initialValue);
603
+ const [{ rows: positions }] = usePositionStream(symbol);
604
+ const position = useMemo(
605
+ () => orderMarginMode != null ? positions?.find(
606
+ (row) => row.symbol === symbol && row.margin_mode === orderMarginMode
607
+ ) : positions?.[0],
608
+ [positions, symbol, orderMarginMode]
609
+ );
610
+ const positionQty = position?.position_qty;
611
+ const [_, setNeedConfirm] = useLocalStorage("orderly_order_confirm", true);
612
+ const renderPositionType = () => {
613
+ if (order.position_type === PositionType.FULL) {
614
+ return /* @__PURE__ */ jsx(Text, { children: t("tpsl.positionType.full") });
615
615
  }
616
- }, [props.initialValue, open]);
617
- const onClick = (val) => {
618
- setValue(val);
619
- setCustomValue("");
620
- setError(void 0);
616
+ return /* @__PURE__ */ jsx(Text, { children: t("tpsl.positionType.partial") });
621
617
  };
622
- const onValueChange = (val) => {
623
- if (!val) {
624
- setCustomValue(val);
625
- return;
618
+ const renderPrice = () => {
619
+ if (order_type === OrderType.MARKET || order_type === OrderType.STOP_MARKET) {
620
+ return /* @__PURE__ */ jsx(Text, { intensity: 80, children: t("common.marketPrice") });
626
621
  }
627
- const d = new Decimal(val);
628
- setValue(void 0);
629
- if (d.gt(3)) {
630
- setCustomValue("3");
631
- setError(t("orderEntry.slippage.error.exceed"));
632
- } else {
633
- setCustomValue(val);
634
- setError(void 0);
622
+ if (isBBOOrder({ order_type, order_type_ext })) {
623
+ const bboType = getBBOType({
624
+ type: order_type_ext,
625
+ side,
626
+ level
627
+ });
628
+ const label = {
629
+ [BBOOrderType.COUNTERPARTY1]: t("orderEntry.bbo.counterparty1"),
630
+ [BBOOrderType.COUNTERPARTY5]: t("orderEntry.bbo.counterparty5"),
631
+ [BBOOrderType.QUEUE1]: t("orderEntry.bbo.queue1"),
632
+ [BBOOrderType.QUEUE5]: t("orderEntry.bbo.queue5")
633
+ }[bboType];
634
+ return /* @__PURE__ */ jsx(Text, { intensity: 80, children: label });
635
635
  }
636
+ return /* @__PURE__ */ jsx(
637
+ Text.numeral,
638
+ {
639
+ unit: quote,
640
+ rule: "price",
641
+ className: "oui-text-base-contrast",
642
+ unitClassName: "oui-text-base-contrast-36 oui-ml-1",
643
+ dp: quote_dp,
644
+ padding: false,
645
+ children: order.order_price
646
+ }
647
+ );
636
648
  };
637
- const toolTipButton = props.isMobile ? /* @__PURE__ */ jsx(
638
- "button",
639
- {
640
- onClick: () => {
641
- modal.alert({
642
- title: t("common.tips"),
643
- message: /* @__PURE__ */ jsx(Text, { size: "2xs", children: t("orderEntry.slippage.tips") })
644
- });
645
- },
646
- children: /* @__PURE__ */ jsx(ExclamationFillIcon, { className: "oui-text-base-contrast-54", size: 16 })
649
+ const renderTPSLPrice = ({
650
+ price,
651
+ isOrderPrice,
652
+ isEnable,
653
+ colorType
654
+ }) => {
655
+ if (!isEnable) {
656
+ return /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-36", children: "-- USDC" });
647
657
  }
648
- ) : /* @__PURE__ */ jsx(
649
- Tooltip,
650
- {
651
- content: /* @__PURE__ */ jsx(Text, { intensity: 80, size: "2xs", children: t("orderEntry.slippage.tips") }),
652
- className: "oui-w-[260px] oui-bg-base-6",
653
- arrow: { className: "oui-fill-base-6" },
654
- children: /* @__PURE__ */ jsx(TooltipTrigger, { children: /* @__PURE__ */ jsx(ExclamationFillIcon, { className: "oui-text-base-contrast-54", size: 16 }) })
658
+ if (!price) {
659
+ if (isOrderPrice) {
660
+ return /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-36", children: t("common.marketPrice") });
661
+ }
655
662
  }
656
- );
657
- return /* @__PURE__ */ jsxs("div", { className: "oui-orderEntry-slippageEditor oui-text-2xs", children: [
658
- /* @__PURE__ */ jsxs(Flex, { mb: 2, gapX: 1, children: [
659
- /* @__PURE__ */ jsx(Text, { size: "xs", children: t("orderEntry.slippage") }),
660
- toolTipButton
661
- ] }),
662
- /* @__PURE__ */ jsxs(Flex, { gapX: 2, children: [
663
- options.map((item) => {
664
- const isActive = value === item;
665
- return /* @__PURE__ */ jsx(
666
- SlippageItem,
667
- {
668
- value: item,
669
- isActive,
670
- onClick: () => {
671
- onClick(item);
672
- }
673
- },
674
- item
675
- );
676
- }),
663
+ return /* @__PURE__ */ jsx(
664
+ Text.numeral,
665
+ {
666
+ unit: "USDC",
667
+ rule: "price",
668
+ className: cn(
669
+ "oui-text-base-contrast",
670
+ colorType === "TP" ? "oui-text-trade-profit" : "oui-text-trade-loss"
671
+ ),
672
+ unitClassName: "oui-text-base-contrast-36 oui-ml-1",
673
+ dp: quote_dp,
674
+ padding: false,
675
+ children: price
676
+ }
677
+ );
678
+ };
679
+ const renderTPSLQty = () => {
680
+ if (!positionQty || !order.order_quantity) {
681
+ return null;
682
+ }
683
+ let qty = new Decimal(order.order_quantity);
684
+ if (order.position_type === PositionType.FULL) {
685
+ qty = qty.plus(new Decimal(positionQty ?? 0));
686
+ }
687
+ return /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
688
+ /* @__PURE__ */ jsx(Text, { children: order.position_type === PositionType.FULL ? t("common.positionQty") : t("common.orderQty") }),
677
689
  /* @__PURE__ */ jsx(
678
- Input,
690
+ Text.numeral,
679
691
  {
680
- suffix: "%",
681
- formatters: [
682
- inputFormatter.numberFormatter,
683
- inputFormatter.dpFormatter(2)
684
- ],
685
- value: customValue,
686
- onValueChange,
687
- classNames: {
688
- root: cn(
689
- "oui-slippageEditor-customInput",
690
- "oui-rounded-md oui-bg-base-6",
691
- "oui-h-[40px] oui-w-[74px]"
692
- ),
693
- input: "oui-text-base-contrast",
694
- additional: "oui-pl-1"
695
- }
692
+ rule: "price",
693
+ dp: base_dp,
694
+ padding: false,
695
+ className: "oui-text-base-contrast",
696
+ children: qty.toNumber()
696
697
  }
697
698
  )
698
- ] }),
699
- !!error && /* @__PURE__ */ jsx(Box, { mt: 5, className: "-oui-mb-5", children: /* @__PURE__ */ jsx(Text, { size: "2xs", color: "danger", children: error }) })
700
- ] });
701
- });
702
- var SlippageItem = ({ value, isActive, onClick }) => {
703
- return /* @__PURE__ */ jsx(
704
- Flex,
705
- {
706
- intensity: 600,
707
- justify: "center",
708
- itemAlign: "center",
709
- r: "md",
710
- width: 74,
711
- height: 40,
712
- className: cn(
713
- "oui-slippageEditor-option",
714
- "oui-cursor-pointer oui-select-none",
715
- isActive ? "oui-bg-primary-light oui-text-primary-contrast/80" : "oui-text-base-contrast-80"
716
- ),
717
- onClick,
718
- children: /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
719
- value,
720
- "%"
721
- ] })
722
- }
723
- );
724
- };
725
- var SlippageCell = (props) => {
726
- const { t } = useTranslation();
727
- const [open2, { setTrue: setOpen, setFalse: setClose, toggle }] = useBoolean(false);
728
- const { isMobile } = useScreen();
729
- const slippageRef = useRef(null);
730
- const onConfirm = () => {
731
- const val = slippageRef.current?.getValue();
732
- props.setSlippage(!val ? "1" : val.toString());
733
- setClose();
734
- return Promise.resolve(true);
699
+ ] });
735
700
  };
736
- return /* @__PURE__ */ jsxs(Fragment, { children: [
737
- /* @__PURE__ */ jsx(
738
- SimpleDialog,
739
- {
740
- open: open2,
741
- onOpenChange: toggle,
742
- title: t("common.settings"),
743
- contentProps: { size: isMobile ? "xs" : "sm" },
744
- classNames: {
745
- footer: "oui-orderEntry-slippage-footer",
746
- body: "oui-orderEntry-slippage-body"
747
- },
748
- actions: {
749
- primary: {
750
- disabled: false,
751
- label: t("common.save"),
752
- onClick: onConfirm,
753
- className: "oui-slippage-save-btn"
754
- },
755
- secondary: {
756
- label: t("common.cancel"),
757
- onClick: () => setClose(),
758
- className: "oui-slippage-cancel-btn"
759
- }
760
- },
761
- children: /* @__PURE__ */ jsx(
762
- SlippageEditor,
701
+ const renderPriceAndTotal = () => {
702
+ if (order_type === OrderType.TRAILING_STOP) {
703
+ const { activated_price, callback_value, callback_rate } = order;
704
+ const callbackView = callback_rate ? /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
705
+ /* @__PURE__ */ jsx(Text, { children: t("orderEntry.trailingRate") }),
706
+ /* @__PURE__ */ jsxs(Text, { className: "oui-text-base-contrast", children: [
707
+ callback_rate,
708
+ "%"
709
+ ] })
710
+ ] }) : /* @__PURE__ */ jsx(
711
+ OrderItem,
712
+ {
713
+ title: t("orderEntry.trailingValue"),
714
+ value: callback_value,
715
+ unit: quote,
716
+ dp: quote_dp
717
+ }
718
+ );
719
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
720
+ activated_price && /* @__PURE__ */ jsx(
721
+ OrderItem,
763
722
  {
764
- ref: slippageRef,
765
- isMobile,
766
- initialValue: props.slippage ? Number(props.slippage) : void 0
723
+ title: t("common.triggerPrice"),
724
+ value: activated_price,
725
+ unit: quote,
726
+ dp: quote_dp
767
727
  }
768
- )
769
- }
770
- ),
771
- /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-orderEntry-slippage", children: [
772
- /* @__PURE__ */ jsx(Text, { className: "oui-slippage-label", size: "2xs", children: t("orderEntry.slippage") }),
728
+ ),
729
+ callbackView
730
+ ] });
731
+ }
732
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
733
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
734
+ /* @__PURE__ */ jsx(Text, { children: t("common.price") }),
735
+ renderPrice()
736
+ ] }),
773
737
  /* @__PURE__ */ jsx(
774
- AuthGuard,
738
+ OrderItem,
775
739
  {
776
- fallback: () => /* @__PURE__ */ jsxs(Text, { size: "2xs", children: [
777
- t("orderEntry.slippage.est"),
778
- ": -% / ",
779
- t("common.max"),
780
- ": --%"
781
- ] }),
782
- children: /* @__PURE__ */ jsxs(Flex, { gap: 1, className: "oui-slippage-value-container", children: [
783
- /* @__PURE__ */ jsx(
784
- Text.numeral,
785
- {
786
- size: "2xs",
787
- rule: "percentages",
788
- prefix: `${t("orderEntry.slippage.est")}: `,
789
- suffix: ` / ${t("common.max")}: `,
790
- children: props.estSlippage ?? 0
791
- }
792
- ),
793
- /* @__PURE__ */ jsx(
794
- "button",
795
- {
796
- className: "oui-slippage-edit-btn oui-text-2xs",
797
- onClick: () => setOpen(),
798
- children: /* @__PURE__ */ jsxs(Flex, { className: "oui-gap-0.5", as: "span", children: [
799
- /* @__PURE__ */ jsx(Text, { size: "2xs", className: "oui-text-primary", children: `${props.slippage || "-"}%` }),
800
- /* @__PURE__ */ jsx(
801
- EditIcon$1,
802
- {
803
- className: "oui-slippage-edit-icon oui-text-primary oui-hidden md:oui-block",
804
- size: 12,
805
- opacity: 1
806
- }
807
- )
808
- ] })
809
- }
810
- )
811
- ] })
740
+ title: t("common.estTotal"),
741
+ value: order.total,
742
+ unit: quote,
743
+ dp: quote_dp
812
744
  }
813
745
  )
814
- ] })
815
- ] });
816
- };
817
- var SlippageUI = (props) => {
818
- return /* @__PURE__ */ jsx(SlippageCell, { ...props });
819
- };
820
- function AssetInfo(props) {
821
- const { canTrade, disableFeatures, orderType, symbol } = props;
822
- const { t } = useTranslation();
823
- const { isMobile } = useScreen();
824
- const displayEstLiqPrice = useGetEstLiqPrice({
825
- estLiqPrice: props.estLiqPrice,
826
- symbol,
827
- side: props.side
828
- });
829
- return /* @__PURE__ */ jsxs(
830
- "div",
746
+ ] });
747
+ };
748
+ const header = /* @__PURE__ */ jsxs(
749
+ Flex,
831
750
  {
832
- className: "oui-orderEntry-assetInfo oui-space-y-[2px] xl:oui-space-y-1",
751
+ justify: "between",
752
+ className: "oui-orderEntry-orderConfirmDialog-header",
833
753
  children: [
834
- /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-orderEntry-estLiqPrice", children: [
835
- isMobile ? /* @__PURE__ */ jsx(Text, { size: "2xs", children: t("orderEntry.estLiqPrice") }) : /* @__PURE__ */ jsx(
836
- Tooltip,
837
- {
838
- content: /* @__PURE__ */ jsxs("div", { className: "oui-min-w-[204px] oui-max-w-[280px] oui-text-2xs oui-leading-normal oui-text-base-contrast-80", children: [
839
- /* @__PURE__ */ jsx("div", { className: "oui-text-pretty", children: t("common.liquidationPrice.tooltip") }),
840
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
841
- "a",
842
- {
843
- href: "https://orderly.network/docs/introduction/trade-on-orderly/perpetual-futures/liquidations",
844
- target: "_blank",
845
- rel: "noopener noreferrer",
846
- className: "oui-text-primary oui-underline",
847
- children: t("common.liquidationPrice.tooltip.learnMore")
848
- }
849
- ) })
850
- ] }),
851
- children: /* @__PURE__ */ jsx(
852
- Text,
853
- {
854
- size: "2xs",
855
- className: "oui-estLiqPrice-label oui-cursor-pointer oui-border-b oui-border-dashed oui-border-line-12",
856
- children: t("orderEntry.estLiqPrice")
857
- }
858
- )
859
- }
860
- ),
754
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, direction: "column", itemAlign: "start", children: [
861
755
  /* @__PURE__ */ jsx(
862
- Text.numeral,
756
+ Text.formatted,
863
757
  {
864
- unit: props.quote,
865
- size: "2xs",
866
- dp: props.dp,
867
- className: "oui-estLiqPrice-value oui-text-base-contrast-80",
868
- unitClassName: "oui-ml-1 oui-text-base-contrast-36",
869
- children: canTrade ? displayEstLiqPrice ?? "--" : "--"
758
+ rule: "symbol",
759
+ formatString: "base",
760
+ showIcon: true,
761
+ className: "oui-orderConfirmDialog-symbol",
762
+ children: order.symbol
870
763
  }
871
- )
764
+ ),
765
+ /* @__PURE__ */ jsx(SymbolBadge, { symbol: order.symbol })
872
766
  ] }),
873
- orderType === OrderType.MARKET && !disableFeatures?.includes("slippageSetting") && /* @__PURE__ */ jsx(
874
- SlippageUI,
767
+ /* @__PURE__ */ jsxs(
768
+ Flex,
875
769
  {
876
- slippage: props.slippage,
877
- setSlippage: props.setSlippage,
878
- estSlippage: props.estSlippage
770
+ justify: "end",
771
+ gapX: 1,
772
+ className: "oui-orderConfirmDialog-header-tags",
773
+ children: [
774
+ /* @__PURE__ */ jsx(OrderTypeTag, { type: order_type }),
775
+ side === OrderSide.BUY ? /* @__PURE__ */ jsx(Badge, { color: "buy", size: "sm", children: t("common.buy") }) : /* @__PURE__ */ jsx(Badge, { color: "sell", size: "sm", children: t("common.sell") })
776
+ ]
879
777
  }
880
- ),
881
- !disableFeatures?.includes("feesInfo") && /* @__PURE__ */ jsx(FeesWidget, { symbol: props.symbol })
778
+ )
882
779
  ]
883
780
  }
884
781
  );
885
- }
886
- var calculateLTVColor = (val) => {
887
- if (val >= 0 && val < 50) {
888
- return "oui-text-success";
889
- } else if (val >= 50 && val < 80) {
890
- return "oui-text-warning";
891
- } else if (val >= 80) {
892
- return "oui-text-danger";
893
- } else {
894
- return "";
895
- }
896
- };
897
- var LTVRiskTooltipUI = (props) => {
898
- const { t } = useTranslation();
899
- const {
900
- ltv_threshold,
901
- negative_usdc_threshold,
902
- isThresholdLoading,
903
- holdingData = [],
904
- currentLtv,
905
- onConvert,
906
- marginMode
907
- } = props;
908
- return /* @__PURE__ */ jsxs(
909
- Flex,
782
+ const quantityItem = /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
783
+ /* @__PURE__ */ jsx(Text, { children: t("common.orderQty") }),
784
+ /* @__PURE__ */ jsx(
785
+ Text.numeral,
786
+ {
787
+ rule: "price",
788
+ dp: base_dp,
789
+ padding: false,
790
+ className: "oui-text-base-contrast",
791
+ children: order.order_quantity
792
+ }
793
+ )
794
+ ] });
795
+ const triggerPriceItem = (order_type === OrderType.STOP_LIMIT || order_type === OrderType.STOP_MARKET && order.trigger_price) && /* @__PURE__ */ jsx(
796
+ OrderItem,
910
797
  {
911
- gap: 1,
912
- className: "oui-orderEntry-ltvRiskTooltip oui-w-72 oui-max-w-72",
913
- direction: "column",
914
- itemAlign: "start",
915
- children: [
916
- /* @__PURE__ */ jsxs(Flex, { width: "100%", justify: "between", itemAlign: "center", children: [
917
- /* @__PURE__ */ jsx(Text, { intensity: 36, size: "xs", children: t("common.assets") }),
918
- /* @__PURE__ */ jsx(Text, { intensity: 36, size: "xs", children: t("transfer.deposit.collateralContribution") })
919
- ] }),
920
- holdingData.map((asset, index) => {
921
- return /* @__PURE__ */ jsxs(
798
+ title: t("common.trigger"),
799
+ value: order.trigger_price,
800
+ unit: quote,
801
+ dp: quote_dp
802
+ }
803
+ );
804
+ const tpslTriggerPrice = (order.tp_trigger_price || order.sl_trigger_price) && /* @__PURE__ */ jsxs(Fragment, { children: [
805
+ /* @__PURE__ */ jsx(Divider, { className: "oui-my-4" }),
806
+ /* @__PURE__ */ jsxs(
807
+ "div",
808
+ {
809
+ className: textVariants({
810
+ size: "sm",
811
+ intensity: 54,
812
+ className: "oui-space-y-1 oui-w-full oui-flex oui-flex-col oui-gap-3"
813
+ }),
814
+ children: [
815
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast", children: renderPositionType() }),
816
+ renderTPSLQty(),
817
+ /* @__PURE__ */ jsxs(
922
818
  Flex,
923
819
  {
924
- width: "100%",
820
+ direction: "column",
925
821
  justify: "between",
926
- itemAlign: "center",
822
+ itemAlign: "start",
823
+ gap: 1,
824
+ className: "oui-w-full",
927
825
  children: [
928
- /* @__PURE__ */ jsx(Text, { intensity: 80, size: "xs", children: asset.token }),
929
- /* @__PURE__ */ jsx(
930
- Text,
931
- {
932
- size: "xs",
933
- intensity: 80,
934
- className: cn(
935
- Number(asset.collateralContribution) < 0 && "oui-text-warning"
936
- ),
937
- children: removeTrailingZeros(asset.collateralContribution)
938
- }
939
- )
826
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-w-full", children: [
827
+ /* @__PURE__ */ jsx(Text, { children: t("tpsl.tpTriggerPrice") }),
828
+ renderTPSLPrice({
829
+ price: order.tp_trigger_price ?? "",
830
+ isOrderPrice: false,
831
+ isEnable: !!order.tp_trigger_price,
832
+ colorType: "TP"
833
+ })
834
+ ] }),
835
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-w-full", children: [
836
+ /* @__PURE__ */ jsx(Text, { children: t("tpsl.tpOrderPrice") }),
837
+ renderTPSLPrice({
838
+ price: order.tp_order_price ?? "",
839
+ isOrderPrice: true,
840
+ isEnable: !!order.tp_trigger_price,
841
+ colorType: "TP"
842
+ })
843
+ ] })
940
844
  ]
941
- },
942
- `item-${index}`
943
- );
944
- }),
945
- /* @__PURE__ */ jsx(Divider, { className: "oui-w-full" }),
946
- /* @__PURE__ */ jsxs(Flex, { width: "100%", justify: "between", itemAlign: "center", children: [
947
- /* @__PURE__ */ jsx(Text, { intensity: 36, size: "xs", children: t("transfer.LTV.currentLTV") }),
845
+ }
846
+ ),
948
847
  /* @__PURE__ */ jsxs(
949
- Text,
848
+ Flex,
950
849
  {
951
- size: "xs",
952
- intensity: 36,
953
- className: cn("oui-select-none", calculateLTVColor(currentLtv)),
850
+ direction: "column",
851
+ justify: "between",
852
+ itemAlign: "start",
853
+ gap: 1,
854
+ className: "oui-w-full",
954
855
  children: [
955
- currentLtv,
956
- "%"
856
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-w-full", children: [
857
+ /* @__PURE__ */ jsx(Text, { children: t("tpsl.slTriggerPrice") }),
858
+ renderTPSLPrice({
859
+ price: order.sl_trigger_price ?? "",
860
+ isOrderPrice: false,
861
+ isEnable: !!order.sl_trigger_price,
862
+ colorType: "SL"
863
+ })
864
+ ] }),
865
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-w-full", children: [
866
+ /* @__PURE__ */ jsx(Text, { children: t("tpsl.slOrderPrice") }),
867
+ renderTPSLPrice({
868
+ price: order.sl_order_price ?? "",
869
+ isOrderPrice: true,
870
+ isEnable: !!order.sl_trigger_price,
871
+ colorType: "SL"
872
+ })
873
+ ] })
957
874
  ]
958
875
  }
959
876
  )
960
- ] }),
961
- /* @__PURE__ */ jsx(Text, { className: "oui-py-2", intensity: 54, size: "2xs", children: t("transfer.LTV.tooltip", {
962
- threshold: isThresholdLoading ? "-" : ltv_threshold,
963
- usdcThreshold: isThresholdLoading ? "-" : negative_usdc_threshold
964
- }) }),
877
+ ]
878
+ }
879
+ )
880
+ ] });
881
+ const orderConfirmCheckbox = /* @__PURE__ */ jsxs(
882
+ Flex,
883
+ {
884
+ gapX: 1,
885
+ pt: 4,
886
+ pb: 5,
887
+ className: "oui-orderEntry-orderConfirmDialog-disableConfirm",
888
+ children: [
889
+ /* @__PURE__ */ jsx(
890
+ Checkbox,
891
+ {
892
+ id: "orderConfirm",
893
+ color: "white",
894
+ className: "oui-orderConfirmDialog-disableConfirm-checkbox",
895
+ onCheckedChange: (checked) => {
896
+ setNeedConfirm(!!!checked);
897
+ }
898
+ }
899
+ ),
900
+ /* @__PURE__ */ jsx(
901
+ "label",
902
+ {
903
+ htmlFor: "orderConfirm",
904
+ className: textVariants({
905
+ size: "xs",
906
+ intensity: 54
907
+ }),
908
+ children: t("orderEntry.disableOrderConfirm")
909
+ }
910
+ )
911
+ ]
912
+ }
913
+ );
914
+ const buttons = /* @__PURE__ */ jsxs(
915
+ Grid,
916
+ {
917
+ cols: 2,
918
+ gapX: 3,
919
+ className: "oui-orderEntry-orderConfirmDialog-actions",
920
+ children: [
965
921
  /* @__PURE__ */ jsx(
966
922
  Button,
967
923
  {
968
- fullWidth: true,
969
- size: "md",
970
- variant: "outlined",
971
924
  color: "secondary",
972
- className: "oui-ltvRiskTooltip-convert-btn",
973
- onClick: onConvert,
974
- children: t("transfer.convert.convertAssets")
925
+ size: "md",
926
+ className: "oui-cancel-btn",
927
+ onClick: () => onCancel(),
928
+ children: t("common.cancel")
929
+ }
930
+ ),
931
+ /* @__PURE__ */ jsx(
932
+ Button,
933
+ {
934
+ size: "md",
935
+ className: "oui-confirm-btn",
936
+ onClick: () => onConfirm(),
937
+ children: t("common.confirm")
975
938
  }
976
939
  )
977
940
  ]
978
941
  }
979
942
  );
943
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
944
+ header,
945
+ /* @__PURE__ */ jsx(Divider, { className: "oui-my-4" }),
946
+ /* @__PURE__ */ jsxs(
947
+ "div",
948
+ {
949
+ className: textVariants({
950
+ size: "sm",
951
+ intensity: 54,
952
+ className: "oui-orderEntry-orderConfirmDialog-content oui-space-y-1"
953
+ }),
954
+ children: [
955
+ quantityItem,
956
+ triggerPriceItem,
957
+ renderPriceAndTotal()
958
+ ]
959
+ }
960
+ ),
961
+ tpslTriggerPrice,
962
+ orderConfirmCheckbox,
963
+ buttons
964
+ ] });
980
965
  };
981
- var useConvertThreshold = () => {
982
- const { data, error, isLoading } = useQuery(
983
- "/v1/public/auto_convert_threshold",
984
- { errorRetryCount: 3 }
985
- );
986
- return {
987
- ltv_threshold: new Decimal(data?.ltv_threshold ?? 0).mul(100).toNumber(),
988
- negative_usdc_threshold: data?.negative_usdc_threshold,
989
- isLoading,
990
- error
991
- };
966
+ var OrderItem = (props) => {
967
+ const { title, value, unit, dp } = props;
968
+ return /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
969
+ /* @__PURE__ */ jsx(Text, { children: title }),
970
+ /* @__PURE__ */ jsx(
971
+ Text.numeral,
972
+ {
973
+ unit,
974
+ rule: "price",
975
+ dp,
976
+ padding: false,
977
+ className: "oui-text-base-contrast",
978
+ unitClassName: "oui-text-base-contrast-36 oui-ml-1",
979
+ children: value
980
+ }
981
+ )
982
+ ] });
992
983
  };
993
- var useLTVTooltipScript = (marginMode) => {
994
- const { data: holdingList = [], isLoading: isHoldingLoading } = useHoldingStream();
995
- const {
996
- ltv_threshold,
997
- negative_usdc_threshold,
998
- isLoading: isThresholdLoading
999
- } = useConvertThreshold();
1000
- const tokensInfo = useAppStore((state) => state.tokensInfo);
1001
- const { getIndexPrice } = useIndexPricesStream();
1002
- const holdingData = holdingList.map((item) => {
1003
- const tokenInfo = tokensInfo?.find(({ token }) => token === item.token);
1004
- const indexPrice = getIndexPrice(item.token);
1005
- const collateralRatio = tokenInfo ? account.collateralRatio({
1006
- baseWeight: tokenInfo.base_weight ?? 0,
1007
- discountFactor: tokenInfo.discount_factor ?? 0,
1008
- collateralQty: item.holding,
1009
- collateralCap: tokenInfo?.user_max_qty ?? item.holding,
1010
- indexPrice
1011
- }) : zero;
1012
- const collateralContribution = account.collateralContribution({
1013
- collateralQty: item.holding,
1014
- collateralCap: tokenInfo?.user_max_qty ?? item.holding,
1015
- collateralRatio: collateralRatio.toNumber(),
1016
- indexPrice
1017
- });
1018
- return {
1019
- ...item,
1020
- collateralContribution
1021
- };
1022
- });
1023
- const currentLtv = useComputedLTV();
1024
- const onConvert = useCallback(async () => {
1025
- return modal.show("ConvertDialogId");
1026
- }, []);
1027
- return {
1028
- holdingData,
1029
- isHoldingLoading,
1030
- ltv_threshold,
1031
- negative_usdc_threshold,
1032
- isThresholdLoading,
1033
- currentLtv,
1034
- onConvert,
1035
- marginMode
1036
- };
984
+ OrderConfirmDialog.displayName = "OrderConfirmDialog";
985
+ var OrderTypeTag = (props) => {
986
+ const { t } = useTranslation();
987
+ const typeStr = useMemo(() => {
988
+ switch (props.type) {
989
+ case OrderType.LIMIT:
990
+ return t("orderEntry.orderType.limit");
991
+ case OrderType.MARKET:
992
+ return t("common.marketPrice");
993
+ case OrderType.STOP_LIMIT:
994
+ return t("orderEntry.orderType.stopLimit");
995
+ case OrderType.STOP_MARKET:
996
+ return t("orderEntry.orderType.stopMarket");
997
+ case OrderType.TRAILING_STOP:
998
+ return t("orderEntry.orderType.trailingStop");
999
+ default:
1000
+ return "";
1001
+ }
1002
+ }, [props.type]);
1003
+ return /* @__PURE__ */ jsx(Badge, { color: "neutral", size: "sm", children: typeStr });
1037
1004
  };
1038
- var LTVRiskTooltipWidget = ({
1039
- marginMode
1040
- }) => {
1041
- const state = useLTVTooltipScript(marginMode);
1042
- return /* @__PURE__ */ jsx(LTVRiskTooltipUI, { ...state });
1005
+ var Dialog = (props) => {
1006
+ const { close, resolve, reject, ...rest } = props;
1007
+ return /* @__PURE__ */ jsx(
1008
+ OrderConfirmDialog,
1009
+ {
1010
+ ...rest,
1011
+ onCancel: () => {
1012
+ reject();
1013
+ close();
1014
+ },
1015
+ onConfirm: () => {
1016
+ resolve();
1017
+ close();
1018
+ }
1019
+ }
1020
+ );
1043
1021
  };
1044
- var Available = (props) => {
1045
- const { canTrade, currentLtv, quote, freeCollateral, marginMode } = props;
1022
+ var orderConfirmDialogId = "orderConfirm";
1023
+ registerSimpleDialog(orderConfirmDialogId, Dialog, {
1024
+ size: "sm",
1025
+ title: () => i18n.t("orderEntry.orderConfirm")
1026
+ });
1027
+ var MaxQtyConfirm = memo((props) => {
1046
1028
  const { t } = useTranslation();
1047
- const { isMobile } = useScreen();
1048
- const showLTV = useMemo(() => {
1049
- return typeof currentLtv === "number" && !Number.isNaN(currentLtv) && currentLtv > 0;
1050
- }, [currentLtv]);
1051
- return /* @__PURE__ */ jsxs(
1029
+ return /* @__PURE__ */ jsx(
1030
+ SimpleDialog,
1031
+ {
1032
+ open: props.open,
1033
+ title: t("orderEntry.orderConfirm"),
1034
+ closable: true,
1035
+ onOpenChange: props.onOpenChange,
1036
+ size: "sm",
1037
+ classNames: {
1038
+ footer: "oui-maxQtyConfirm-footer",
1039
+ body: "oui-maxQtyConfirm-body"
1040
+ },
1041
+ actions: {
1042
+ primary: {
1043
+ label: t("orderEntry.placeOrderNow"),
1044
+ className: "oui-primary-btn oui-text-sm oui-font-semibold oui-w-[100%] oui-h-8",
1045
+ onClick: () => {
1046
+ props.onConfirm();
1047
+ return Promise.resolve();
1048
+ }
1049
+ },
1050
+ secondary: {
1051
+ label: t("common.cancel"),
1052
+ className: "oui-secondary-btn oui-text-sm oui-font-semibold oui-w-[100%] oui-h-8",
1053
+ onClick: () => {
1054
+ props.onOpenChange(false);
1055
+ return Promise.resolve();
1056
+ }
1057
+ }
1058
+ },
1059
+ children: /* @__PURE__ */ jsx("div", { className: "oui-maxQtyConfirm-content oui-text-2xs lg:oui-text-sm", children: t("orderEntry.maxQty.reminder.content", {
1060
+ maxQty: `${props.maxQty} ${props.base}`
1061
+ }) })
1062
+ }
1063
+ );
1064
+ });
1065
+ var PermissionlessMarketNoticeDialog = (props) => {
1066
+ const { onConfirm, onCancel } = props;
1067
+ const { t } = useTranslation();
1068
+ const [checked, setChecked] = useState(false);
1069
+ const content = /* @__PURE__ */ jsxs(
1052
1070
  Flex,
1053
1071
  {
1054
- itemAlign: "center",
1055
- justify: "between",
1056
- className: "oui-orderEntry-available",
1072
+ direction: "column",
1073
+ gap: 3,
1074
+ itemAlign: "start",
1075
+ className: "oui-permissionlessNotice-content",
1057
1076
  children: [
1058
- marginMode === MarginMode.ISOLATED ? /* @__PURE__ */ jsx(Tooltip, { content: t("transfer.LTV.isolatedModeUsdcOnly"), children: /* @__PURE__ */ jsx(Text, { className: "oui-available-label oui-cursor-pointer", size: "2xs", children: t("common.available") }) }) : /* @__PURE__ */ jsx(Text, { className: "oui-available-label", size: "2xs", children: t("common.available") }),
1059
- /* @__PURE__ */ jsxs(Flex, { itemAlign: "center", justify: "center", gap: 1, children: [
1060
- showLTV && /* @__PURE__ */ jsx(
1061
- Tooltip,
1062
- {
1063
- className: "oui-available-ltvRisk-tooltip oui-bg-base-6 oui-p-2",
1064
- content: /* @__PURE__ */ jsx(LTVRiskTooltipWidget, { marginMode }),
1065
- children: /* @__PURE__ */ jsx(
1066
- InfoCircleIcon,
1067
- {
1068
- className: "oui-cursor-pointer oui-text-warning oui-opacity-80"
1069
- }
1070
- )
1071
- }
1072
- ),
1073
- /* @__PURE__ */ jsx(
1074
- Text.numeral,
1075
- {
1076
- unit: quote,
1077
- size: "2xs",
1078
- className: "oui-available-value oui-text-base-contrast-80",
1079
- unitClassName: "oui-ml-1 oui-text-base-contrast-54",
1080
- dp: 2,
1081
- padding: false,
1082
- children: canTrade ? freeCollateral : 0
1083
- }
1084
- ),
1085
- /* @__PURE__ */ jsx(
1086
- Button,
1087
- {
1088
- variant: "text",
1077
+ /* @__PURE__ */ jsx(
1078
+ Text,
1079
+ {
1080
+ className: textVariants({
1081
+ size: "sm",
1082
+ intensity: 54
1083
+ }),
1084
+ children: t("orderEntry.permissionlessNotice.content1")
1085
+ }
1086
+ ),
1087
+ /* @__PURE__ */ jsx(
1088
+ Text,
1089
+ {
1090
+ className: textVariants({
1091
+ size: "sm",
1092
+ intensity: 54
1093
+ }),
1094
+ children: t("orderEntry.permissionlessNotice.content2")
1095
+ }
1096
+ ),
1097
+ /* @__PURE__ */ jsx(
1098
+ Text,
1099
+ {
1100
+ className: textVariants({
1101
+ size: "sm",
1102
+ intensity: 54
1103
+ }),
1104
+ children: t("orderEntry.permissionlessNotice.content3")
1105
+ }
1106
+ )
1107
+ ]
1108
+ }
1109
+ );
1110
+ const checkboxSection = /* @__PURE__ */ jsxs(
1111
+ Flex,
1112
+ {
1113
+ gapX: 1,
1114
+ pt: 4,
1115
+ pb: 5,
1116
+ itemAlign: "start",
1117
+ className: "oui-permissionlessNotice-checkbox oui-orderEntry-orderConfirmDialog-disableConfirm oui-cursor-pointer",
1118
+ children: [
1119
+ /* @__PURE__ */ jsx(
1120
+ Checkbox,
1121
+ {
1122
+ id: "permissionlessNotice",
1123
+ color: "white",
1124
+ className: "oui-permissionlessNotice-checkbox-input oui-mt-1",
1125
+ checked,
1126
+ onCheckedChange: (value) => setChecked(!!value)
1127
+ }
1128
+ ),
1129
+ /* @__PURE__ */ jsx(
1130
+ "label",
1131
+ {
1132
+ htmlFor: "permissionlessNotice",
1133
+ className: textVariants({
1089
1134
  size: "xs",
1090
- color: "secondary",
1091
- className: "oui-available-deposit-icon oui-p-0 hover:oui-text-base-contrast-80",
1092
- onClick: () => {
1093
- const handleDomId = isMobile ? "DepositAndWithdrawWithSheetId" : "DepositAndWithdrawWithDialogId";
1094
- modal.show(handleDomId, {
1095
- activeTab: "deposit"
1096
- });
1097
- },
1098
- children: /* @__PURE__ */ jsx(AddCircleIcon, { opacity: 1 })
1099
- }
1100
- )
1101
- ] })
1135
+ intensity: 54,
1136
+ className: "oui-cursor-pointer"
1137
+ }),
1138
+ children: t("orderEntry.permissionlessNotice.checkbox")
1139
+ }
1140
+ )
1102
1141
  ]
1103
1142
  }
1104
1143
  );
1144
+ const confirmButton = /* @__PURE__ */ jsx(
1145
+ Flex,
1146
+ {
1147
+ className: "oui-permissionlessNotice-confirm-button oui-w-full",
1148
+ justify: "center",
1149
+ children: /* @__PURE__ */ jsx(
1150
+ Button,
1151
+ {
1152
+ fullWidth: true,
1153
+ size: "md",
1154
+ className: "oui-permissionlessNotice-confirm oui-confirm-btn oui-max-w-[244px]",
1155
+ disabled: !checked,
1156
+ onClick: () => onConfirm(),
1157
+ children: t("common.confirm")
1158
+ }
1159
+ )
1160
+ }
1161
+ );
1162
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1163
+ content,
1164
+ checkboxSection,
1165
+ confirmButton
1166
+ ] });
1105
1167
  };
1106
- function isBBOOrder(options2) {
1107
- const { order_type, order_type_ext } = options2;
1108
- const isBBO = [OrderType.ASK, OrderType.BID].includes(order_type_ext);
1109
- if (order_type) {
1110
- return order_type === OrderType.LIMIT && isBBO;
1111
- }
1112
- return isBBO;
1113
- }
1114
- function getOrderTypeByBBO(value, size) {
1115
- if ([BBOOrderType.COUNTERPARTY1, BBOOrderType.COUNTERPARTY5].includes(value)) {
1116
- return size === OrderSide.BUY ? OrderType.ASK : OrderType.BID;
1117
- }
1118
- if ([BBOOrderType.QUEUE1, BBOOrderType.QUEUE5].includes(value)) {
1119
- return size === OrderSide.BUY ? OrderType.BID : OrderType.ASK;
1120
- }
1121
- }
1122
- function getOrderLevelByBBO(value) {
1123
- if ([BBOOrderType.COUNTERPARTY1, BBOOrderType.QUEUE1].includes(value)) {
1124
- return OrderLevel.ONE;
1125
- }
1126
- if ([BBOOrderType.COUNTERPARTY5, BBOOrderType.QUEUE5].includes(value)) {
1127
- return OrderLevel.FIVE;
1128
- }
1129
- }
1130
- function getScaledPlaceOrderMessage(result) {
1131
- const rows = result?.data?.rows || [];
1132
- if (rows.length > 0) {
1133
- const totalCount = rows.length;
1134
- const successCount = rows.filter((row) => row.success).length;
1135
- if (successCount === totalCount) {
1136
- return i18n.t("orderEntry.scaledOrder.fullySuccessful", {
1137
- total: totalCount
1138
- });
1139
- }
1140
- if (successCount === 0) {
1141
- return i18n.t("orderEntry.scaledOrder.allFailed");
1168
+ PermissionlessMarketNoticeDialog.displayName = "PermissionlessMarketNoticeDialog";
1169
+ var Dialog2 = (props) => {
1170
+ const { close, resolve, reject } = props;
1171
+ return /* @__PURE__ */ jsx(
1172
+ PermissionlessMarketNoticeDialog,
1173
+ {
1174
+ onCancel: () => {
1175
+ reject();
1176
+ close();
1177
+ },
1178
+ onConfirm: () => {
1179
+ resolve();
1180
+ close();
1181
+ }
1142
1182
  }
1143
- return i18n.t("orderEntry.scaledOrder.partiallySuccessful", {
1144
- successCount,
1145
- total: totalCount
1146
- });
1147
- }
1148
- }
1149
- var safeNumber = (val) => {
1150
- return Number.isNaN(Number(val)) ? 0 : Number(val);
1183
+ );
1151
1184
  };
1152
- var OrderConfirmDialog = (props) => {
1153
- const { symbolInfo, order, onConfirm, onCancel } = props;
1154
- const { quote, quote_dp, base_dp } = symbolInfo;
1155
- const { side, order_type, order_type_ext, level, symbol } = order;
1156
- const orderMarginMode = order.margin_mode;
1185
+ var permissionlessMarketNoticeDialogId = "permissionlessMarketNotice";
1186
+ var permissionlessMarketNoticeDesktopDialogId = "permissionlessMarketNoticeDesktop";
1187
+ registerSimpleDialog(permissionlessMarketNoticeDialogId, Dialog2, {
1188
+ size: "sm",
1189
+ title: () => i18n.t("orderEntry.permissionlessNotice.title")
1190
+ });
1191
+ registerSimpleDialog(permissionlessMarketNoticeDesktopDialogId, Dialog2, {
1192
+ size: "xl",
1193
+ title: () => i18n.t("orderEntry.permissionlessNotice.title")
1194
+ });
1195
+ var ScaledOrderConfirm = (props) => {
1196
+ const { order, symbolInfo, dataSource, national, askAndBid, totalQuantity } = props;
1197
+ const { base, quote, base_dp, quote_dp } = symbolInfo;
1157
1198
  const { t } = useTranslation();
1158
- const [{ rows: positions }] = usePositionStream(symbol);
1159
- const position = useMemo(
1160
- () => orderMarginMode != null ? positions?.find(
1161
- (row) => row.symbol === symbol && row.margin_mode === orderMarginMode
1162
- ) : positions?.[0],
1163
- [positions, symbol, orderMarginMode]
1164
- );
1165
- const positionQty = position?.position_qty;
1166
- const [_, setNeedConfirm] = useLocalStorage("orderly_order_confirm", true);
1167
- const renderPositionType = () => {
1168
- if (order.position_type === PositionType.FULL) {
1169
- return /* @__PURE__ */ jsx(Text, { children: t("tpsl.positionType.full") });
1170
- }
1171
- return /* @__PURE__ */ jsx(Text, { children: t("tpsl.positionType.partial") });
1199
+ const onCancel = () => {
1200
+ props.reject();
1201
+ props.close?.();
1172
1202
  };
1173
- const renderPrice = () => {
1174
- if (order_type === OrderType.MARKET || order_type === OrderType.STOP_MARKET) {
1175
- return /* @__PURE__ */ jsx(Text, { intensity: 80, children: t("common.marketPrice") });
1176
- }
1177
- if (isBBOOrder({ order_type, order_type_ext })) {
1178
- const bboType = getBBOType({
1179
- type: order_type_ext,
1180
- side,
1181
- level
1182
- });
1183
- const label = {
1184
- [BBOOrderType.COUNTERPARTY1]: t("orderEntry.bbo.counterparty1"),
1185
- [BBOOrderType.COUNTERPARTY5]: t("orderEntry.bbo.counterparty5"),
1186
- [BBOOrderType.QUEUE1]: t("orderEntry.bbo.queue1"),
1187
- [BBOOrderType.QUEUE5]: t("orderEntry.bbo.queue5")
1188
- }[bboType];
1189
- return /* @__PURE__ */ jsx(Text, { intensity: 80, children: label });
1190
- }
1191
- return /* @__PURE__ */ jsx(
1192
- Text.numeral,
1193
- {
1194
- unit: quote,
1195
- rule: "price",
1196
- className: "oui-text-base-contrast",
1197
- unitClassName: "oui-text-base-contrast-36 oui-ml-1",
1198
- dp: quote_dp,
1199
- padding: false,
1200
- children: order.order_price
1201
- }
1202
- );
1203
+ const onConfirm = () => {
1204
+ props.resolve();
1205
+ props.close?.();
1203
1206
  };
1204
- const renderTPSLPrice = ({
1205
- price,
1206
- isOrderPrice,
1207
- isEnable,
1208
- colorType
1209
- }) => {
1210
- if (!isEnable) {
1211
- return /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-36", children: "-- USDC" });
1212
- }
1213
- if (!price) {
1214
- if (isOrderPrice) {
1215
- return /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-36", children: t("common.marketPrice") });
1216
- }
1217
- }
1218
- return /* @__PURE__ */ jsx(
1219
- Text.numeral,
1207
+ const columns = useMemo(() => {
1208
+ return [
1220
1209
  {
1221
- unit: "USDC",
1222
- rule: "price",
1223
- className: cn(
1224
- "oui-text-base-contrast",
1225
- colorType === "TP" ? "oui-text-trade-profit" : "oui-text-trade-loss"
1226
- ),
1227
- unitClassName: "oui-text-base-contrast-36 oui-ml-1",
1228
- dp: quote_dp,
1229
- padding: false,
1230
- children: price
1231
- }
1232
- );
1233
- };
1234
- const renderTPSLQty = () => {
1235
- if (!positionQty || !order.order_quantity) {
1236
- return null;
1237
- }
1238
- let qty = new Decimal(order.order_quantity);
1239
- if (order.position_type === PositionType.FULL) {
1240
- qty = qty.plus(new Decimal(positionQty ?? 0));
1241
- }
1242
- return /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
1243
- /* @__PURE__ */ jsx(Text, { children: order.position_type === PositionType.FULL ? t("common.positionQty") : t("common.orderQty") }),
1244
- /* @__PURE__ */ jsx(
1245
- Text.numeral,
1246
- {
1247
- rule: "price",
1248
- dp: base_dp,
1249
- padding: false,
1250
- className: "oui-text-base-contrast",
1251
- children: qty.toNumber()
1210
+ title: t("common.symbol"),
1211
+ dataIndex: "symbol",
1212
+ width: 125,
1213
+ render: (value, record) => {
1214
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1215
+ /* @__PURE__ */ jsx(
1216
+ "div",
1217
+ {
1218
+ className: cn(
1219
+ "oui-h-[42px] oui-w-1 oui-shrink-0 oui-rounded-[1px]",
1220
+ record.side === OrderSide.BUY ? "oui-bg-trade-profit" : "oui-bg-trade-loss"
1221
+ )
1222
+ }
1223
+ ),
1224
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", itemAlign: "start", children: [
1225
+ /* @__PURE__ */ jsxs(Flex, { gapX: 1, children: [
1226
+ /* @__PURE__ */ jsx(TokenIcon, { symbol: value, className: "oui-size-3" }),
1227
+ /* @__PURE__ */ jsx(Text.formatted, { rule: "symbol", size: "xs", formatString: "base", children: value })
1228
+ ] }),
1229
+ /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
1230
+ /* @__PURE__ */ jsx(SymbolBadge, { symbol: value }),
1231
+ /* @__PURE__ */ jsx(Badge, { color: "neutral", size: "xs", children: t("orderEntry.orderType.limit") })
1232
+ ] })
1233
+ ] })
1234
+ ] });
1252
1235
  }
1253
- )
1254
- ] });
1255
- };
1256
- const renderPriceAndTotal = () => {
1257
- if (order_type === OrderType.TRAILING_STOP) {
1258
- const { activated_price, callback_value, callback_rate } = order;
1259
- const callbackView = callback_rate ? /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
1260
- /* @__PURE__ */ jsx(Text, { children: t("orderEntry.trailingRate") }),
1261
- /* @__PURE__ */ jsxs(Text, { className: "oui-text-base-contrast", children: [
1262
- callback_rate,
1263
- "%"
1264
- ] })
1265
- ] }) : /* @__PURE__ */ jsx(
1266
- OrderItem,
1267
- {
1268
- title: t("orderEntry.trailingValue"),
1269
- value: callback_value,
1270
- unit: quote,
1271
- dp: quote_dp
1236
+ },
1237
+ {
1238
+ title: t("common.quantity"),
1239
+ dataIndex: "order_quantity",
1240
+ width: 100,
1241
+ render: (value, record) => {
1242
+ return /* @__PURE__ */ jsx(
1243
+ Text.numeral,
1244
+ {
1245
+ rule: "price",
1246
+ dp: base_dp,
1247
+ padding: false,
1248
+ color: record.side === OrderSide.BUY ? "buy" : "sell",
1249
+ children: value
1250
+ }
1251
+ );
1272
1252
  }
1273
- );
1274
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1275
- activated_price && /* @__PURE__ */ jsx(
1276
- OrderItem,
1277
- {
1278
- title: t("common.triggerPrice"),
1279
- value: activated_price,
1280
- unit: quote,
1281
- dp: quote_dp
1282
- }
1283
- ),
1284
- callbackView
1285
- ] });
1286
- }
1287
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1288
- /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
1289
- /* @__PURE__ */ jsx(Text, { children: t("common.price") }),
1290
- renderPrice()
1291
- ] }),
1292
- /* @__PURE__ */ jsx(
1293
- OrderItem,
1294
- {
1295
- title: t("common.estTotal"),
1296
- value: order.total,
1297
- unit: quote,
1298
- dp: quote_dp
1253
+ },
1254
+ {
1255
+ title: t("common.orderPrice"),
1256
+ dataIndex: "order_price",
1257
+ width: 100,
1258
+ render: (value, record) => {
1259
+ const showWarning = !!(record.side === OrderSide.BUY ? askAndBid?.[0] && Number(value) >= askAndBid?.[0] : askAndBid?.[1] && Number(value) <= askAndBid?.[1]);
1260
+ return /* @__PURE__ */ jsxs(Flex, { gapX: 1, children: [
1261
+ /* @__PURE__ */ jsx(Text.numeral, { rule: "price", dp: quote_dp, children: value }),
1262
+ showWarning && /* @__PURE__ */ jsx(
1263
+ Tooltip,
1264
+ {
1265
+ content: t(
1266
+ "orderEntry.confirmScaledOrder.orderPrice.warning"
1267
+ ),
1268
+ className: "oui-w-[240px] oui-text-2xs oui-font-semibold oui-text-base-contrast-80",
1269
+ children: /* @__PURE__ */ jsx(TooltipIcon, { className: "oui-text-warning-darken" })
1270
+ }
1271
+ )
1272
+ ] });
1299
1273
  }
1300
- )
1301
- ] });
1302
- };
1303
- const header = /* @__PURE__ */ jsxs(
1304
- Flex,
1305
- {
1306
- justify: "between",
1307
- className: "oui-orderEntry-orderConfirmDialog-header",
1308
- children: [
1309
- /* @__PURE__ */ jsx(
1310
- Text.formatted,
1311
- {
1312
- rule: "symbol",
1313
- showIcon: true,
1314
- className: "oui-orderConfirmDialog-symbol",
1315
- children: order.symbol
1316
- }
1317
- ),
1318
- /* @__PURE__ */ jsxs(
1319
- Flex,
1320
- {
1321
- justify: "end",
1322
- gapX: 1,
1323
- className: "oui-orderConfirmDialog-header-tags",
1324
- children: [
1325
- /* @__PURE__ */ jsx(OrderTypeTag, { type: order_type }),
1326
- side === OrderSide.BUY ? /* @__PURE__ */ jsx(Badge, { color: "buy", size: "sm", children: t("common.buy") }) : /* @__PURE__ */ jsx(Badge, { color: "sell", size: "sm", children: t("common.sell") })
1327
- ]
1328
- }
1329
- )
1330
- ]
1331
- }
1332
- );
1333
- const quantityItem = /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
1334
- /* @__PURE__ */ jsx(Text, { children: t("common.orderQty") }),
1335
- /* @__PURE__ */ jsx(
1336
- Text.numeral,
1337
- {
1338
- rule: "price",
1339
- dp: base_dp,
1340
- padding: false,
1341
- className: "oui-text-base-contrast",
1342
- children: order.order_quantity
1343
1274
  }
1344
- )
1345
- ] });
1346
- const triggerPriceItem = (order_type === OrderType.STOP_LIMIT || order_type === OrderType.STOP_MARKET && order.trigger_price) && /* @__PURE__ */ jsx(
1347
- OrderItem,
1348
- {
1349
- title: t("common.trigger"),
1350
- value: order.trigger_price,
1351
- unit: quote,
1352
- dp: quote_dp
1353
- }
1354
- );
1355
- const tpslTriggerPrice = (order.tp_trigger_price || order.sl_trigger_price) && /* @__PURE__ */ jsxs(Fragment, { children: [
1356
- /* @__PURE__ */ jsx(Divider, { className: "oui-my-4" }),
1357
- /* @__PURE__ */ jsxs(
1358
- "div",
1275
+ ];
1276
+ }, [t, symbolInfo, askAndBid, base_dp, quote_dp]);
1277
+ return /* @__PURE__ */ jsxs("div", { className: "oui-orderEntry-scaledOrderConfirm oui-font-semibold", children: [
1278
+ /* @__PURE__ */ jsx(
1279
+ DataTable,
1359
1280
  {
1360
- className: textVariants({
1361
- size: "sm",
1362
- intensity: 54,
1363
- className: "oui-space-y-1 oui-w-full oui-flex oui-flex-col oui-gap-3"
1364
- }),
1365
- children: [
1366
- /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast", children: renderPositionType() }),
1367
- renderTPSLQty(),
1368
- /* @__PURE__ */ jsxs(
1369
- Flex,
1370
- {
1371
- direction: "column",
1372
- justify: "between",
1373
- itemAlign: "start",
1374
- gap: 1,
1375
- className: "oui-w-full",
1376
- children: [
1377
- /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-w-full", children: [
1378
- /* @__PURE__ */ jsx(Text, { children: t("tpsl.tpTriggerPrice") }),
1379
- renderTPSLPrice({
1380
- price: order.tp_trigger_price ?? "",
1381
- isOrderPrice: false,
1382
- isEnable: !!order.tp_trigger_price,
1383
- colorType: "TP"
1384
- })
1385
- ] }),
1386
- /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-w-full", children: [
1387
- /* @__PURE__ */ jsx(Text, { children: t("tpsl.tpOrderPrice") }),
1388
- renderTPSLPrice({
1389
- price: order.tp_order_price ?? "",
1390
- isOrderPrice: true,
1391
- isEnable: !!order.tp_trigger_price,
1392
- colorType: "TP"
1393
- })
1394
- ] })
1395
- ]
1396
- }
1281
+ classNames: {
1282
+ root: cn(
1283
+ "oui-scaledOrderConfirm-table",
1284
+ "oui-bg-base-7",
1285
+ "oui-rounded-lg",
1286
+ // need to set overflow hidden because table header will avoid the border radius
1287
+ "oui-overflow-hidden",
1288
+ // "oui-text-2xs lg:oui-text-xs",
1289
+ // if orders is greater than 6, set the height to 320px to show scroll bar
1290
+ order.orders?.length >= 6 && "oui-h-[320px]"
1397
1291
  ),
1398
- /* @__PURE__ */ jsxs(
1399
- Flex,
1400
- {
1401
- direction: "column",
1402
- justify: "between",
1403
- itemAlign: "start",
1404
- gap: 1,
1405
- className: "oui-w-full",
1406
- children: [
1407
- /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-w-full", children: [
1408
- /* @__PURE__ */ jsx(Text, { children: t("tpsl.slTriggerPrice") }),
1409
- renderTPSLPrice({
1410
- price: order.sl_trigger_price ?? "",
1411
- isOrderPrice: false,
1412
- isEnable: !!order.sl_trigger_price,
1413
- colorType: "SL"
1414
- })
1415
- ] }),
1416
- /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-w-full", children: [
1417
- /* @__PURE__ */ jsx(Text, { children: t("tpsl.slOrderPrice") }),
1418
- renderTPSLPrice({
1419
- price: order.sl_order_price ?? "",
1420
- isOrderPrice: true,
1421
- isEnable: !!order.sl_trigger_price,
1422
- colorType: "SL"
1423
- })
1424
- ] })
1425
- ]
1426
- }
1427
- )
1428
- ]
1292
+ // set the min height of the table to show 2 rows
1293
+ scroll: "!oui-min-h-[130px]"
1294
+ },
1295
+ dataSource,
1296
+ columns,
1297
+ bordered: true,
1298
+ onRow: () => {
1299
+ return {
1300
+ className: cn("oui-h-[50px]")
1301
+ };
1302
+ }
1429
1303
  }
1430
- )
1431
- ] });
1432
- const orderConfirmCheckbox = /* @__PURE__ */ jsxs(
1433
- Flex,
1434
- {
1435
- gapX: 1,
1436
- pt: 4,
1437
- pb: 5,
1438
- className: "oui-orderEntry-orderConfirmDialog-disableConfirm",
1439
- children: [
1440
- /* @__PURE__ */ jsx(
1441
- Checkbox,
1442
- {
1443
- id: "orderConfirm",
1444
- color: "white",
1445
- className: "oui-orderConfirmDialog-disableConfirm-checkbox",
1446
- onCheckedChange: (checked) => {
1447
- setNeedConfirm(!!!checked);
1448
- }
1449
- }
1450
- ),
1304
+ ),
1305
+ /* @__PURE__ */ jsxs("div", { className: "oui-scaledOrderConfirm-content oui-mb-5 oui-mt-4 oui-text-2xs", children: [
1306
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
1307
+ /* @__PURE__ */ jsx(Text, { children: t("orderEntry.totalOrders") }),
1308
+ /* @__PURE__ */ jsx(Text, { intensity: 80, children: order.orders?.length })
1309
+ ] }),
1310
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", mt: 2, children: [
1311
+ /* @__PURE__ */ jsx(Text, { children: t("orderEntry.totalQuantity") }),
1451
1312
  /* @__PURE__ */ jsx(
1452
- "label",
1313
+ Text.numeral,
1453
1314
  {
1454
- htmlFor: "orderConfirm",
1455
- className: textVariants({
1456
- size: "xs",
1457
- intensity: 54
1458
- }),
1459
- children: t("orderEntry.disableOrderConfirm")
1315
+ rule: "price",
1316
+ unit: base,
1317
+ dp: base_dp,
1318
+ padding: false,
1319
+ intensity: 80,
1320
+ unitClassName: "oui-text-base-contrast-36 oui-ml-1",
1321
+ children: totalQuantity
1460
1322
  }
1461
1323
  )
1462
- ]
1463
- }
1464
- );
1465
- const buttons = /* @__PURE__ */ jsxs(
1466
- Grid,
1467
- {
1468
- cols: 2,
1469
- gapX: 3,
1470
- className: "oui-orderEntry-orderConfirmDialog-actions",
1471
- children: [
1472
- /* @__PURE__ */ jsx(
1473
- Button,
1474
- {
1475
- color: "secondary",
1476
- size: "md",
1477
- className: "oui-cancel-btn",
1478
- onClick: () => onCancel(),
1479
- children: t("common.cancel")
1480
- }
1481
- ),
1324
+ ] }),
1325
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", mt: 2, children: [
1326
+ /* @__PURE__ */ jsx(Text, { children: t("common.notional") }),
1482
1327
  /* @__PURE__ */ jsx(
1483
- Button,
1328
+ Text.numeral,
1484
1329
  {
1485
- size: "md",
1486
- className: "oui-confirm-btn",
1487
- onClick: () => onConfirm(),
1488
- children: t("common.confirm")
1489
- }
1490
- )
1491
- ]
1492
- }
1493
- );
1494
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1495
- header,
1496
- /* @__PURE__ */ jsx(Divider, { className: "oui-my-4" }),
1497
- /* @__PURE__ */ jsxs(
1498
- "div",
1499
- {
1500
- className: textVariants({
1501
- size: "sm",
1502
- intensity: 54,
1503
- className: "oui-orderEntry-orderConfirmDialog-content oui-space-y-1"
1504
- }),
1505
- children: [
1506
- quantityItem,
1507
- triggerPriceItem,
1508
- renderPriceAndTotal()
1509
- ]
1510
- }
1511
- ),
1512
- tpslTriggerPrice,
1513
- orderConfirmCheckbox,
1514
- buttons
1515
- ] });
1516
- };
1517
- var OrderItem = (props) => {
1518
- const { title, value, unit, dp } = props;
1519
- return /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
1520
- /* @__PURE__ */ jsx(Text, { children: title }),
1521
- /* @__PURE__ */ jsx(
1522
- Text.numeral,
1523
- {
1524
- unit,
1525
- rule: "price",
1526
- dp,
1527
- padding: false,
1528
- className: "oui-text-base-contrast",
1529
- unitClassName: "oui-text-base-contrast-36 oui-ml-1",
1530
- children: value
1531
- }
1532
- )
1533
- ] });
1534
- };
1535
- OrderConfirmDialog.displayName = "OrderConfirmDialog";
1536
- var OrderTypeTag = (props) => {
1537
- const { t } = useTranslation();
1538
- const typeStr = useMemo(() => {
1539
- switch (props.type) {
1540
- case OrderType.LIMIT:
1541
- return t("orderEntry.orderType.limit");
1542
- case OrderType.MARKET:
1543
- return t("common.marketPrice");
1544
- case OrderType.STOP_LIMIT:
1545
- return t("orderEntry.orderType.stopLimit");
1546
- case OrderType.STOP_MARKET:
1547
- return t("orderEntry.orderType.stopMarket");
1548
- case OrderType.TRAILING_STOP:
1549
- return t("orderEntry.orderType.trailingStop");
1550
- default:
1551
- return "";
1552
- }
1553
- }, [props.type]);
1554
- return /* @__PURE__ */ jsx(Badge, { color: "neutral", size: "sm", children: typeStr });
1555
- };
1556
- var Dialog = (props) => {
1557
- const { close, resolve, reject, ...rest } = props;
1558
- return /* @__PURE__ */ jsx(
1559
- OrderConfirmDialog,
1560
- {
1561
- ...rest,
1562
- onCancel: () => {
1563
- reject();
1564
- close();
1565
- },
1566
- onConfirm: () => {
1567
- resolve();
1568
- close();
1569
- }
1570
- }
1571
- );
1572
- };
1573
- var orderConfirmDialogId = "orderConfirm";
1574
- registerSimpleDialog(orderConfirmDialogId, Dialog, {
1575
- size: "sm",
1576
- title: () => i18n.t("orderEntry.orderConfirm")
1577
- });
1578
- var MaxQtyConfirm = memo((props) => {
1579
- const { t } = useTranslation();
1580
- return /* @__PURE__ */ jsx(
1581
- SimpleDialog,
1582
- {
1583
- open: props.open,
1584
- title: t("orderEntry.orderConfirm"),
1585
- closable: true,
1586
- onOpenChange: props.onOpenChange,
1587
- size: "sm",
1588
- classNames: {
1589
- footer: "oui-maxQtyConfirm-footer",
1590
- body: "oui-maxQtyConfirm-body"
1591
- },
1592
- actions: {
1593
- primary: {
1594
- label: t("orderEntry.placeOrderNow"),
1595
- className: "oui-primary-btn oui-text-sm oui-font-semibold oui-w-[100%] oui-h-8",
1596
- onClick: () => {
1597
- props.onConfirm();
1598
- return Promise.resolve();
1599
- }
1600
- },
1601
- secondary: {
1602
- label: t("common.cancel"),
1603
- className: "oui-secondary-btn oui-text-sm oui-font-semibold oui-w-[100%] oui-h-8",
1604
- onClick: () => {
1605
- props.onOpenChange(false);
1606
- return Promise.resolve();
1607
- }
1608
- }
1609
- },
1610
- children: /* @__PURE__ */ jsx("div", { className: "oui-maxQtyConfirm-content oui-text-2xs lg:oui-text-sm", children: t("orderEntry.maxQty.reminder.content", {
1611
- maxQty: `${props.maxQty} ${props.base}`
1612
- }) })
1613
- }
1614
- );
1615
- });
1616
- var ScaledOrderConfirm = (props) => {
1617
- const { order, symbolInfo, dataSource, national, askAndBid, totalQuantity } = props;
1618
- const { base, quote, base_dp, quote_dp } = symbolInfo;
1619
- const { t } = useTranslation();
1620
- const onCancel = () => {
1621
- props.reject();
1622
- props.close?.();
1623
- };
1624
- const onConfirm = () => {
1625
- props.resolve();
1626
- props.close?.();
1627
- };
1628
- const columns = useMemo(() => {
1629
- return [
1630
- {
1631
- title: t("common.symbol"),
1632
- dataIndex: "symbol",
1633
- width: 125,
1634
- render: (value, record) => {
1635
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1636
- /* @__PURE__ */ jsx(
1637
- "div",
1638
- {
1639
- className: cn(
1640
- "oui-h-[38px] oui-w-1 oui-shrink-0 oui-rounded-[1px]",
1641
- record.side === OrderSide.BUY ? "oui-bg-trade-profit" : "oui-bg-trade-loss"
1642
- )
1643
- }
1644
- ),
1645
- /* @__PURE__ */ jsxs(Flex, { direction: "column", itemAlign: "start", children: [
1646
- /* @__PURE__ */ jsxs(Flex, { gapX: 1, children: [
1647
- /* @__PURE__ */ jsx(TokenIcon, { symbol: value, className: "oui-size-3" }),
1648
- /* @__PURE__ */ jsx(
1649
- Text.formatted,
1650
- {
1651
- rule: "symbol",
1652
- size: "xs",
1653
- formatString: "base-type",
1654
- children: value
1655
- }
1656
- )
1657
- ] }),
1658
- /* @__PURE__ */ jsx(Badge, { color: "neutral", size: "xs", children: t("orderEntry.orderType.limit") })
1659
- ] })
1660
- ] });
1661
- }
1662
- },
1663
- {
1664
- title: t("common.quantity"),
1665
- dataIndex: "order_quantity",
1666
- width: 100,
1667
- render: (value, record) => {
1668
- return /* @__PURE__ */ jsx(
1669
- Text.numeral,
1670
- {
1671
- rule: "price",
1672
- dp: base_dp,
1673
- padding: false,
1674
- color: record.side === OrderSide.BUY ? "buy" : "sell",
1675
- children: value
1676
- }
1677
- );
1678
- }
1679
- },
1680
- {
1681
- title: t("common.orderPrice"),
1682
- dataIndex: "order_price",
1683
- width: 100,
1684
- render: (value, record) => {
1685
- const showWarning = !!(record.side === OrderSide.BUY ? askAndBid?.[0] && Number(value) >= askAndBid?.[0] : askAndBid?.[1] && Number(value) <= askAndBid?.[1]);
1686
- return /* @__PURE__ */ jsxs(Flex, { gapX: 1, children: [
1687
- /* @__PURE__ */ jsx(Text.numeral, { rule: "price", dp: quote_dp, children: value }),
1688
- showWarning && /* @__PURE__ */ jsx(
1689
- Tooltip,
1690
- {
1691
- content: t(
1692
- "orderEntry.confirmScaledOrder.orderPrice.warning"
1693
- ),
1694
- className: "oui-w-[240px] oui-text-2xs oui-font-semibold oui-text-base-contrast-80",
1695
- children: /* @__PURE__ */ jsx(TooltipIcon, { className: "oui-text-warning-darken" })
1696
- }
1697
- )
1698
- ] });
1699
- }
1700
- }
1701
- ];
1702
- }, [t, symbolInfo, askAndBid, base_dp, quote_dp]);
1703
- return /* @__PURE__ */ jsxs("div", { className: "oui-orderEntry-scaledOrderConfirm oui-font-semibold", children: [
1704
- /* @__PURE__ */ jsx(
1705
- DataTable,
1706
- {
1707
- classNames: {
1708
- root: cn(
1709
- "oui-scaledOrderConfirm-table",
1710
- "oui-bg-base-7",
1711
- "oui-rounded-lg",
1712
- // need to set overflow hidden because table header will avoid the border radius
1713
- "oui-overflow-hidden",
1714
- // "oui-text-2xs lg:oui-text-xs",
1715
- // if orders is greater than 6, set the height to 320px to show scroll bar
1716
- order.orders?.length >= 6 && "oui-h-[320px]"
1717
- ),
1718
- // set the min height of the table to show 2 rows
1719
- scroll: "!oui-min-h-[130px]"
1720
- },
1721
- dataSource,
1722
- columns,
1723
- bordered: true,
1724
- onRow: () => {
1725
- return {
1726
- className: cn("oui-h-[50px]")
1727
- };
1728
- }
1729
- }
1730
- ),
1731
- /* @__PURE__ */ jsxs("div", { className: "oui-scaledOrderConfirm-content oui-mb-5 oui-mt-4 oui-text-2xs", children: [
1732
- /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [
1733
- /* @__PURE__ */ jsx(Text, { children: t("orderEntry.totalOrders") }),
1734
- /* @__PURE__ */ jsx(Text, { intensity: 80, children: order.orders?.length })
1735
- ] }),
1736
- /* @__PURE__ */ jsxs(Flex, { justify: "between", mt: 2, children: [
1737
- /* @__PURE__ */ jsx(Text, { children: t("orderEntry.totalQuantity") }),
1738
- /* @__PURE__ */ jsx(
1739
- Text.numeral,
1740
- {
1741
- rule: "price",
1742
- unit: base,
1743
- dp: base_dp,
1744
- padding: false,
1745
- intensity: 80,
1746
- unitClassName: "oui-text-base-contrast-36 oui-ml-1",
1747
- children: totalQuantity
1748
- }
1749
- )
1750
- ] }),
1751
- /* @__PURE__ */ jsxs(Flex, { justify: "between", mt: 2, children: [
1752
- /* @__PURE__ */ jsx(Text, { children: t("common.notional") }),
1753
- /* @__PURE__ */ jsx(
1754
- Text.numeral,
1755
- {
1756
- rule: "price",
1757
- unit: quote,
1758
- dp: quote_dp,
1759
- padding: false,
1760
- intensity: 80,
1761
- unitClassName: "oui-text-base-contrast-36 oui-ml-1",
1762
- children: national
1330
+ rule: "price",
1331
+ unit: quote,
1332
+ dp: quote_dp,
1333
+ padding: false,
1334
+ intensity: 80,
1335
+ unitClassName: "oui-text-base-contrast-36 oui-ml-1",
1336
+ children: national
1763
1337
  }
1764
1338
  )
1765
1339
  ] })
@@ -1845,17 +1419,580 @@ var ScaledOrderConfirmWidget = (props) => {
1845
1419
  const state = useScaledOrderConfirmScript(props);
1846
1420
  return /* @__PURE__ */ jsx(ScaledOrderConfirm, { ...props, ...state });
1847
1421
  };
1848
- var scaledOrderConfirmDialogId = "scaledOrderConfirm";
1849
- registerSimpleDialog(scaledOrderConfirmDialogId, ScaledOrderConfirmWidget, {
1850
- size: "md",
1851
- title: () => i18n.t("orderEntry.confirmScaledOrder"),
1852
- contentProps: {
1853
- // className: "oui-p-0",
1854
- }
1855
- });
1422
+ var scaledOrderConfirmDialogId = "scaledOrderConfirm";
1423
+ registerSimpleDialog(scaledOrderConfirmDialogId, ScaledOrderConfirmWidget, {
1424
+ size: "md",
1425
+ title: () => i18n.t("orderEntry.confirmScaledOrder"),
1426
+ contentProps: {
1427
+ // className: "oui-p-0",
1428
+ }
1429
+ });
1430
+ var RegularFeesUI = (props) => {
1431
+ const { t } = useTranslation();
1432
+ const { taker, maker } = props;
1433
+ const originalTrailingFees = /* @__PURE__ */ jsx(
1434
+ Flex,
1435
+ {
1436
+ itemAlign: "center",
1437
+ justify: "between",
1438
+ width: "100%",
1439
+ gap: 1,
1440
+ className: "oui-orderEntry-fees",
1441
+ children: /* @__PURE__ */ jsxs(Flex, { width: "100%", itemAlign: "center", justify: "between", children: [
1442
+ /* @__PURE__ */ jsx(Text, { className: "oui-fees-label oui-truncate", size: "2xs", children: t("common.fees") }),
1443
+ /* @__PURE__ */ jsx(
1444
+ AuthGuard,
1445
+ {
1446
+ fallback: () => /* @__PURE__ */ jsxs(Text, { className: "oui-truncate", size: "2xs", children: [
1447
+ t("dmm.taker"),
1448
+ ": --% / ",
1449
+ t("dmm.maker"),
1450
+ ": --%"
1451
+ ] }),
1452
+ children: /* @__PURE__ */ jsxs(Flex, { gap: 1, className: "oui-fees-value-container", children: [
1453
+ /* @__PURE__ */ jsxs(Text, { className: "oui-truncate", size: "2xs", children: [
1454
+ t("dmm.taker"),
1455
+ ":"
1456
+ ] }),
1457
+ /* @__PURE__ */ jsx(Text, { size: "2xs", className: "oui-text-base-contrast-80", children: taker }),
1458
+ /* @__PURE__ */ jsx(Text, { size: "2xs", children: "/" }),
1459
+ /* @__PURE__ */ jsxs(Text, { className: "oui-truncate", size: "2xs", children: [
1460
+ t("dmm.maker"),
1461
+ ":"
1462
+ ] }),
1463
+ /* @__PURE__ */ jsx(Text, { size: "2xs", className: "oui-text-base-contrast-80", children: maker })
1464
+ ] })
1465
+ }
1466
+ )
1467
+ ] })
1468
+ }
1469
+ );
1470
+ return originalTrailingFees;
1471
+ };
1472
+ var RegularFeesWidget = (props) => {
1473
+ return /* @__PURE__ */ jsx(RegularFeesUI, { ...props });
1474
+ };
1475
+ var FeesWidget = ({ symbol }) => {
1476
+ const { takerFee, makerFee, rwaTakerFee, rwaMakerFee } = useFeeState();
1477
+ const info = useRwaSymbolsInfoStore();
1478
+ const isRwa = info?.[symbol] !== void 0;
1479
+ return /* @__PURE__ */ jsx(
1480
+ RegularFeesWidget,
1481
+ {
1482
+ taker: isRwa ? rwaTakerFee : takerFee,
1483
+ maker: isRwa ? rwaMakerFee : makerFee
1484
+ }
1485
+ );
1486
+ };
1487
+ var options = [0.01, 0.05, 0.1];
1488
+ var SlippageEditor = forwardRef((props, ref) => {
1489
+ const { t } = useTranslation();
1490
+ const [value, setValue] = useState();
1491
+ const [customValue, setCustomValue] = useState("");
1492
+ const [error, setError] = useState(void 0);
1493
+ useImperativeHandle(ref, () => ({
1494
+ getValue: () => customValue ? new Decimal(customValue)?.toNumber() : value
1495
+ }));
1496
+ useEffect(() => {
1497
+ if (props.initialValue && !options.includes(props.initialValue)) {
1498
+ setCustomValue(props.initialValue.toString());
1499
+ } else {
1500
+ setValue(props.initialValue);
1501
+ }
1502
+ }, [props.initialValue, open]);
1503
+ const onClick = (val) => {
1504
+ setValue(val);
1505
+ setCustomValue("");
1506
+ setError(void 0);
1507
+ };
1508
+ const onValueChange = (val) => {
1509
+ if (!val) {
1510
+ setCustomValue(val);
1511
+ return;
1512
+ }
1513
+ const d = new Decimal(val);
1514
+ setValue(void 0);
1515
+ if (d.gt(3)) {
1516
+ setCustomValue("3");
1517
+ setError(t("orderEntry.slippage.error.exceed"));
1518
+ } else {
1519
+ setCustomValue(val);
1520
+ setError(void 0);
1521
+ }
1522
+ };
1523
+ const toolTipButton = props.isMobile ? /* @__PURE__ */ jsx(
1524
+ "button",
1525
+ {
1526
+ onClick: () => {
1527
+ modal.alert({
1528
+ title: t("common.tips"),
1529
+ message: /* @__PURE__ */ jsx(Text, { size: "2xs", children: t("orderEntry.slippage.tips") })
1530
+ });
1531
+ },
1532
+ children: /* @__PURE__ */ jsx(ExclamationFillIcon, { className: "oui-text-base-contrast-54", size: 16 })
1533
+ }
1534
+ ) : /* @__PURE__ */ jsx(
1535
+ Tooltip,
1536
+ {
1537
+ content: /* @__PURE__ */ jsx(Text, { intensity: 80, size: "2xs", children: t("orderEntry.slippage.tips") }),
1538
+ className: "oui-w-[260px] oui-bg-base-6",
1539
+ arrow: { className: "oui-fill-base-6" },
1540
+ children: /* @__PURE__ */ jsx(TooltipTrigger, { children: /* @__PURE__ */ jsx(ExclamationFillIcon, { className: "oui-text-base-contrast-54", size: 16 }) })
1541
+ }
1542
+ );
1543
+ return /* @__PURE__ */ jsxs("div", { className: "oui-orderEntry-slippageEditor oui-text-2xs", children: [
1544
+ /* @__PURE__ */ jsxs(Flex, { mb: 2, gapX: 1, children: [
1545
+ /* @__PURE__ */ jsx(Text, { size: "xs", children: t("orderEntry.slippage") }),
1546
+ toolTipButton
1547
+ ] }),
1548
+ /* @__PURE__ */ jsxs(Flex, { gapX: 2, children: [
1549
+ options.map((item) => {
1550
+ const isActive = value === item;
1551
+ return /* @__PURE__ */ jsx(
1552
+ SlippageItem,
1553
+ {
1554
+ value: item,
1555
+ isActive,
1556
+ onClick: () => {
1557
+ onClick(item);
1558
+ }
1559
+ },
1560
+ item
1561
+ );
1562
+ }),
1563
+ /* @__PURE__ */ jsx(
1564
+ Input,
1565
+ {
1566
+ suffix: "%",
1567
+ formatters: [
1568
+ inputFormatter.numberFormatter,
1569
+ inputFormatter.dpFormatter(2)
1570
+ ],
1571
+ value: customValue,
1572
+ onValueChange,
1573
+ classNames: {
1574
+ root: cn(
1575
+ "oui-slippageEditor-customInput",
1576
+ "oui-rounded-md oui-bg-base-6",
1577
+ "oui-h-[40px] oui-w-[74px]"
1578
+ ),
1579
+ input: "oui-text-base-contrast",
1580
+ additional: "oui-pl-1"
1581
+ }
1582
+ }
1583
+ )
1584
+ ] }),
1585
+ !!error && /* @__PURE__ */ jsx(Box, { mt: 5, className: "-oui-mb-5", children: /* @__PURE__ */ jsx(Text, { size: "2xs", color: "danger", children: error }) })
1586
+ ] });
1587
+ });
1588
+ var SlippageItem = ({ value, isActive, onClick }) => {
1589
+ return /* @__PURE__ */ jsx(
1590
+ Flex,
1591
+ {
1592
+ intensity: 600,
1593
+ justify: "center",
1594
+ itemAlign: "center",
1595
+ r: "md",
1596
+ width: 74,
1597
+ height: 40,
1598
+ className: cn(
1599
+ "oui-slippageEditor-option",
1600
+ "oui-cursor-pointer oui-select-none",
1601
+ isActive ? "oui-bg-primary-light oui-text-primary-contrast/80" : "oui-text-base-contrast-80"
1602
+ ),
1603
+ onClick,
1604
+ children: /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
1605
+ value,
1606
+ "%"
1607
+ ] })
1608
+ }
1609
+ );
1610
+ };
1611
+ var SlippageCell = (props) => {
1612
+ const { t } = useTranslation();
1613
+ const [open2, { setTrue: setOpen, setFalse: setClose, toggle }] = useBoolean(false);
1614
+ const { isMobile } = useScreen();
1615
+ const slippageRef = useRef(null);
1616
+ const onConfirm = () => {
1617
+ const val = slippageRef.current?.getValue();
1618
+ props.setSlippage(!val ? "1" : val.toString());
1619
+ setClose();
1620
+ return Promise.resolve(true);
1621
+ };
1622
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1623
+ /* @__PURE__ */ jsx(
1624
+ SimpleDialog,
1625
+ {
1626
+ open: open2,
1627
+ onOpenChange: toggle,
1628
+ title: t("common.settings"),
1629
+ contentProps: { size: isMobile ? "xs" : "sm" },
1630
+ classNames: {
1631
+ footer: "oui-orderEntry-slippage-footer",
1632
+ body: "oui-orderEntry-slippage-body"
1633
+ },
1634
+ actions: {
1635
+ primary: {
1636
+ disabled: false,
1637
+ label: t("common.save"),
1638
+ onClick: onConfirm,
1639
+ className: "oui-slippage-save-btn"
1640
+ },
1641
+ secondary: {
1642
+ label: t("common.cancel"),
1643
+ onClick: () => setClose(),
1644
+ className: "oui-slippage-cancel-btn"
1645
+ }
1646
+ },
1647
+ children: /* @__PURE__ */ jsx(
1648
+ SlippageEditor,
1649
+ {
1650
+ ref: slippageRef,
1651
+ isMobile,
1652
+ initialValue: props.slippage ? Number(props.slippage) : void 0
1653
+ }
1654
+ )
1655
+ }
1656
+ ),
1657
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-orderEntry-slippage", children: [
1658
+ /* @__PURE__ */ jsx(Text, { className: "oui-slippage-label", size: "2xs", children: t("orderEntry.slippage") }),
1659
+ /* @__PURE__ */ jsx(
1660
+ AuthGuard,
1661
+ {
1662
+ fallback: () => /* @__PURE__ */ jsxs(Text, { size: "2xs", children: [
1663
+ t("orderEntry.slippage.est"),
1664
+ ": -% / ",
1665
+ t("common.max"),
1666
+ ": --%"
1667
+ ] }),
1668
+ children: /* @__PURE__ */ jsxs(Flex, { gap: 1, className: "oui-slippage-value-container", children: [
1669
+ /* @__PURE__ */ jsx(
1670
+ Text.numeral,
1671
+ {
1672
+ size: "2xs",
1673
+ rule: "percentages",
1674
+ prefix: `${t("orderEntry.slippage.est")}: `,
1675
+ suffix: ` / ${t("common.max")}: `,
1676
+ children: props.estSlippage ?? 0
1677
+ }
1678
+ ),
1679
+ /* @__PURE__ */ jsx(
1680
+ "button",
1681
+ {
1682
+ className: "oui-slippage-edit-btn oui-text-2xs",
1683
+ onClick: () => setOpen(),
1684
+ children: /* @__PURE__ */ jsxs(Flex, { className: "oui-gap-0.5", as: "span", children: [
1685
+ /* @__PURE__ */ jsx(Text, { size: "2xs", className: "oui-text-primary", children: `${props.slippage || "-"}%` }),
1686
+ /* @__PURE__ */ jsx(
1687
+ EditIcon$1,
1688
+ {
1689
+ className: "oui-slippage-edit-icon oui-text-primary oui-hidden md:oui-block",
1690
+ size: 12,
1691
+ opacity: 1
1692
+ }
1693
+ )
1694
+ ] })
1695
+ }
1696
+ )
1697
+ ] })
1698
+ }
1699
+ )
1700
+ ] })
1701
+ ] });
1702
+ };
1703
+ var SlippageUI = (props) => {
1704
+ return /* @__PURE__ */ jsx(SlippageCell, { ...props });
1705
+ };
1706
+ function AssetInfo(props) {
1707
+ const { canTrade, disableFeatures, orderType, symbol } = props;
1708
+ const { t } = useTranslation();
1709
+ const { isMobile } = useScreen();
1710
+ const displayEstLiqPrice = useGetEstLiqPrice({
1711
+ estLiqPrice: props.estLiqPrice,
1712
+ symbol,
1713
+ side: props.side
1714
+ });
1715
+ return /* @__PURE__ */ jsxs(
1716
+ "div",
1717
+ {
1718
+ className: "oui-orderEntry-assetInfo oui-space-y-[2px] xl:oui-space-y-1",
1719
+ children: [
1720
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-orderEntry-estLiqPrice", children: [
1721
+ isMobile ? /* @__PURE__ */ jsx(Text, { size: "2xs", children: t("orderEntry.estLiqPrice") }) : /* @__PURE__ */ jsx(
1722
+ Tooltip,
1723
+ {
1724
+ content: /* @__PURE__ */ jsxs("div", { className: "oui-min-w-[204px] oui-max-w-[280px] oui-text-2xs oui-leading-normal oui-text-base-contrast-80", children: [
1725
+ /* @__PURE__ */ jsx("div", { className: "oui-text-pretty", children: t("common.liquidationPrice.tooltip") }),
1726
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
1727
+ "a",
1728
+ {
1729
+ href: "https://orderly.network/docs/introduction/trade-on-orderly/perpetual-futures/liquidations",
1730
+ target: "_blank",
1731
+ rel: "noopener noreferrer",
1732
+ className: "oui-text-primary oui-underline",
1733
+ children: t("common.liquidationPrice.tooltip.learnMore")
1734
+ }
1735
+ ) })
1736
+ ] }),
1737
+ children: /* @__PURE__ */ jsx(
1738
+ Text,
1739
+ {
1740
+ size: "2xs",
1741
+ className: "oui-estLiqPrice-label oui-cursor-pointer oui-border-b oui-border-dashed oui-border-line-12",
1742
+ children: t("orderEntry.estLiqPrice")
1743
+ }
1744
+ )
1745
+ }
1746
+ ),
1747
+ /* @__PURE__ */ jsx(
1748
+ Text.numeral,
1749
+ {
1750
+ unit: props.quote,
1751
+ size: "2xs",
1752
+ dp: props.dp,
1753
+ className: "oui-estLiqPrice-value oui-text-base-contrast-80",
1754
+ unitClassName: "oui-ml-1 oui-text-base-contrast-36",
1755
+ children: canTrade ? displayEstLiqPrice ?? "--" : "--"
1756
+ }
1757
+ )
1758
+ ] }),
1759
+ orderType === OrderType.MARKET && !disableFeatures?.includes("slippageSetting") && /* @__PURE__ */ jsx(
1760
+ SlippageUI,
1761
+ {
1762
+ slippage: props.slippage,
1763
+ setSlippage: props.setSlippage,
1764
+ estSlippage: props.estSlippage
1765
+ }
1766
+ ),
1767
+ !disableFeatures?.includes("feesInfo") && /* @__PURE__ */ jsx(FeesWidget, { symbol: props.symbol })
1768
+ ]
1769
+ }
1770
+ );
1771
+ }
1772
+ var calculateLTVColor = (val) => {
1773
+ if (val >= 0 && val < 50) {
1774
+ return "oui-text-success";
1775
+ } else if (val >= 50 && val < 80) {
1776
+ return "oui-text-warning";
1777
+ } else if (val >= 80) {
1778
+ return "oui-text-danger";
1779
+ } else {
1780
+ return "";
1781
+ }
1782
+ };
1783
+ var LTVRiskTooltipUI = (props) => {
1784
+ const { t } = useTranslation();
1785
+ const {
1786
+ ltv_threshold,
1787
+ negative_usdc_threshold,
1788
+ isThresholdLoading,
1789
+ holdingData = [],
1790
+ currentLtv,
1791
+ onConvert,
1792
+ marginMode
1793
+ } = props;
1794
+ return /* @__PURE__ */ jsxs(
1795
+ Flex,
1796
+ {
1797
+ gap: 1,
1798
+ className: "oui-orderEntry-ltvRiskTooltip oui-w-72 oui-max-w-72",
1799
+ direction: "column",
1800
+ itemAlign: "start",
1801
+ children: [
1802
+ /* @__PURE__ */ jsxs(Flex, { width: "100%", justify: "between", itemAlign: "center", children: [
1803
+ /* @__PURE__ */ jsx(Text, { intensity: 36, size: "xs", children: t("common.assets") }),
1804
+ /* @__PURE__ */ jsx(Text, { intensity: 36, size: "xs", children: t("transfer.deposit.collateralContribution") })
1805
+ ] }),
1806
+ holdingData.map((asset, index) => {
1807
+ return /* @__PURE__ */ jsxs(
1808
+ Flex,
1809
+ {
1810
+ width: "100%",
1811
+ justify: "between",
1812
+ itemAlign: "center",
1813
+ children: [
1814
+ /* @__PURE__ */ jsx(Text, { intensity: 80, size: "xs", children: asset.token }),
1815
+ /* @__PURE__ */ jsx(
1816
+ Text,
1817
+ {
1818
+ size: "xs",
1819
+ intensity: 80,
1820
+ className: cn(
1821
+ Number(asset.collateralContribution) < 0 && "oui-text-warning"
1822
+ ),
1823
+ children: removeTrailingZeros(asset.collateralContribution)
1824
+ }
1825
+ )
1826
+ ]
1827
+ },
1828
+ `item-${index}`
1829
+ );
1830
+ }),
1831
+ /* @__PURE__ */ jsx(Divider, { className: "oui-w-full" }),
1832
+ /* @__PURE__ */ jsxs(Flex, { width: "100%", justify: "between", itemAlign: "center", children: [
1833
+ /* @__PURE__ */ jsx(Text, { intensity: 36, size: "xs", children: t("transfer.LTV.currentLTV") }),
1834
+ /* @__PURE__ */ jsxs(
1835
+ Text,
1836
+ {
1837
+ size: "xs",
1838
+ intensity: 36,
1839
+ className: cn("oui-select-none", calculateLTVColor(currentLtv)),
1840
+ children: [
1841
+ currentLtv,
1842
+ "%"
1843
+ ]
1844
+ }
1845
+ )
1846
+ ] }),
1847
+ /* @__PURE__ */ jsx(Text, { className: "oui-py-2", intensity: 54, size: "2xs", children: t("transfer.LTV.tooltip", {
1848
+ threshold: isThresholdLoading ? "-" : ltv_threshold,
1849
+ usdcThreshold: isThresholdLoading ? "-" : negative_usdc_threshold
1850
+ }) }),
1851
+ /* @__PURE__ */ jsx(
1852
+ Button,
1853
+ {
1854
+ fullWidth: true,
1855
+ size: "md",
1856
+ variant: "outlined",
1857
+ color: "secondary",
1858
+ className: "oui-ltvRiskTooltip-convert-btn",
1859
+ onClick: onConvert,
1860
+ children: t("transfer.convert.convertAssets")
1861
+ }
1862
+ )
1863
+ ]
1864
+ }
1865
+ );
1866
+ };
1867
+ var useConvertThreshold = () => {
1868
+ const { data, error, isLoading } = useQuery(
1869
+ "/v1/public/auto_convert_threshold",
1870
+ { errorRetryCount: 3 }
1871
+ );
1872
+ return {
1873
+ ltv_threshold: new Decimal(data?.ltv_threshold ?? 0).mul(100).toNumber(),
1874
+ negative_usdc_threshold: data?.negative_usdc_threshold,
1875
+ isLoading,
1876
+ error
1877
+ };
1878
+ };
1879
+ var useLTVTooltipScript = (marginMode) => {
1880
+ const { data: holdingList = [], isLoading: isHoldingLoading } = useHoldingStream();
1881
+ const {
1882
+ ltv_threshold,
1883
+ negative_usdc_threshold,
1884
+ isLoading: isThresholdLoading
1885
+ } = useConvertThreshold();
1886
+ const tokensInfo = useAppStore((state) => state.tokensInfo);
1887
+ const { getIndexPrice } = useIndexPricesStream();
1888
+ const holdingData = holdingList.map((item) => {
1889
+ const tokenInfo = tokensInfo?.find(({ token }) => token === item.token);
1890
+ const indexPrice = getIndexPrice(item.token);
1891
+ const collateralRatio = tokenInfo ? account.collateralRatio({
1892
+ baseWeight: tokenInfo.base_weight ?? 0,
1893
+ discountFactor: tokenInfo.discount_factor ?? 0,
1894
+ collateralQty: item.holding,
1895
+ collateralCap: tokenInfo?.user_max_qty ?? item.holding,
1896
+ indexPrice
1897
+ }) : zero;
1898
+ const collateralContribution = account.collateralContribution({
1899
+ collateralQty: item.holding,
1900
+ collateralCap: tokenInfo?.user_max_qty ?? item.holding,
1901
+ collateralRatio: collateralRatio.toNumber(),
1902
+ indexPrice
1903
+ });
1904
+ return {
1905
+ ...item,
1906
+ collateralContribution
1907
+ };
1908
+ });
1909
+ const currentLtv = useComputedLTV();
1910
+ const onConvert = useCallback(async () => {
1911
+ return modal.show("ConvertDialogId");
1912
+ }, []);
1913
+ return {
1914
+ holdingData,
1915
+ isHoldingLoading,
1916
+ ltv_threshold,
1917
+ negative_usdc_threshold,
1918
+ isThresholdLoading,
1919
+ currentLtv,
1920
+ onConvert,
1921
+ marginMode
1922
+ };
1923
+ };
1924
+ var LTVRiskTooltipWidget = ({
1925
+ marginMode
1926
+ }) => {
1927
+ const state = useLTVTooltipScript(marginMode);
1928
+ return /* @__PURE__ */ jsx(LTVRiskTooltipUI, { ...state });
1929
+ };
1930
+ var Available = (props) => {
1931
+ const { canTrade, currentLtv, quote, freeCollateral, marginMode } = props;
1932
+ const { t } = useTranslation();
1933
+ const { isMobile } = useScreen();
1934
+ const showLTV = useMemo(() => {
1935
+ return typeof currentLtv === "number" && !Number.isNaN(currentLtv) && currentLtv > 0;
1936
+ }, [currentLtv]);
1937
+ return /* @__PURE__ */ jsxs(
1938
+ Flex,
1939
+ {
1940
+ itemAlign: "center",
1941
+ justify: "between",
1942
+ className: "oui-orderEntry-available",
1943
+ children: [
1944
+ marginMode === MarginMode.ISOLATED ? /* @__PURE__ */ jsx(Tooltip, { content: t("transfer.LTV.isolatedModeUsdcOnly"), children: /* @__PURE__ */ jsx(Text, { className: "oui-available-label oui-cursor-pointer", size: "2xs", children: t("common.available") }) }) : /* @__PURE__ */ jsx(Text, { className: "oui-available-label", size: "2xs", children: t("common.available") }),
1945
+ /* @__PURE__ */ jsxs(Flex, { itemAlign: "center", justify: "center", gap: 1, children: [
1946
+ showLTV && /* @__PURE__ */ jsx(
1947
+ Tooltip,
1948
+ {
1949
+ className: "oui-available-ltvRisk-tooltip oui-bg-base-6 oui-p-2",
1950
+ content: /* @__PURE__ */ jsx(LTVRiskTooltipWidget, { marginMode }),
1951
+ children: /* @__PURE__ */ jsx(
1952
+ InfoCircleIcon,
1953
+ {
1954
+ className: "oui-cursor-pointer oui-text-warning oui-opacity-80"
1955
+ }
1956
+ )
1957
+ }
1958
+ ),
1959
+ /* @__PURE__ */ jsx(
1960
+ Text.numeral,
1961
+ {
1962
+ unit: quote,
1963
+ size: "2xs",
1964
+ className: "oui-available-value oui-text-base-contrast-80",
1965
+ unitClassName: "oui-ml-1 oui-text-base-contrast-54",
1966
+ dp: 2,
1967
+ padding: false,
1968
+ children: canTrade ? freeCollateral : 0
1969
+ }
1970
+ ),
1971
+ /* @__PURE__ */ jsx(
1972
+ Button,
1973
+ {
1974
+ variant: "text",
1975
+ size: "xs",
1976
+ color: "secondary",
1977
+ className: "oui-available-deposit-icon oui-p-0 hover:oui-text-base-contrast-80",
1978
+ onClick: () => {
1979
+ const handleDomId = isMobile ? "DepositAndWithdrawWithSheetId" : "DepositAndWithdrawWithDialogId";
1980
+ modal.show(handleDomId, {
1981
+ activeTab: "deposit"
1982
+ });
1983
+ },
1984
+ children: /* @__PURE__ */ jsx(AddCircleIcon, { opacity: 1 })
1985
+ }
1986
+ )
1987
+ ] })
1988
+ ]
1989
+ }
1990
+ );
1991
+ };
1856
1992
  var OrderTypeSelect = (props) => {
1857
1993
  const { t } = useTranslation();
1858
1994
  const { isMobile } = useScreen();
1995
+ const { marketOrderDisabled = false, marketOrderDisabledTooltip } = props;
1859
1996
  const allOptions = useMemo(() => {
1860
1997
  return [
1861
1998
  { label: t("orderEntry.orderType.limitOrder"), value: OrderType.LIMIT },
@@ -1905,6 +2042,7 @@ var OrderTypeSelect = (props) => {
1905
2042
  [OrderType.TRAILING_STOP]: t("orderEntry.orderType.trailingStop")
1906
2043
  };
1907
2044
  }, [t]);
2045
+ const mobileOptions = useMemo(() => allOptions, [allOptions]);
1908
2046
  if (!isMobile) {
1909
2047
  const baseButtonClassName = "oui-flex oui-flex-1 oui-items-center oui-justify-center oui-gap-x-1 oui-rounded oui-px-3 oui-py-0.5 oui-text-xs oui-font-semibold oui-h-8";
1910
2048
  const selectedButtonClassName = cn(
@@ -1936,7 +2074,24 @@ var OrderTypeSelect = (props) => {
1936
2074
  children: /* @__PURE__ */ jsx(Text, { size: "xs", children: t("orderEntry.orderType.limit") })
1937
2075
  }
1938
2076
  ),
1939
- /* @__PURE__ */ jsx(
2077
+ marketOrderDisabled && marketOrderDisabledTooltip ? /* @__PURE__ */ jsx(
2078
+ Tooltip,
2079
+ {
2080
+ content: marketOrderDisabledTooltip,
2081
+ className: "oui-max-w-[275px]",
2082
+ children: /* @__PURE__ */ jsx("span", { className: "oui-inline-flex oui-flex-1", children: /* @__PURE__ */ jsx(
2083
+ "button",
2084
+ {
2085
+ type: "button",
2086
+ className: unselectedButtonClassName,
2087
+ "aria-pressed": false,
2088
+ disabled: true,
2089
+ "data-testid": "oui-testid-orderEntry-orderType-market",
2090
+ children: /* @__PURE__ */ jsx(Text, { size: "xs", children: t("orderEntry.orderType.market") })
2091
+ }
2092
+ ) })
2093
+ }
2094
+ ) : /* @__PURE__ */ jsx(
1940
2095
  "button",
1941
2096
  {
1942
2097
  type: "button",
@@ -1986,14 +2141,24 @@ var OrderTypeSelect = (props) => {
1986
2141
  }
1987
2142
  );
1988
2143
  }
2144
+ const handleMobileValueChange = (value) => {
2145
+ if (marketOrderDisabled && value === OrderType.MARKET && marketOrderDisabledTooltip) {
2146
+ modal.alert({
2147
+ title: t("common.tips"),
2148
+ message: marketOrderDisabledTooltip
2149
+ });
2150
+ return;
2151
+ }
2152
+ props.onChange(value);
2153
+ };
1989
2154
  return /* @__PURE__ */ jsx(
1990
2155
  Select.options,
1991
2156
  {
1992
2157
  testid: "oui-testid-orderEntry-orderType-button",
1993
2158
  currentValue: props.type,
1994
2159
  value: props.type,
1995
- options: allOptions,
1996
- onValueChange: props.onChange,
2160
+ options: mobileOptions,
2161
+ onValueChange: handleMobileValueChange,
1997
2162
  contentProps: {
1998
2163
  className: cn(
1999
2164
  "oui-orderEntry-orderTypeSelect-content",
@@ -2018,6 +2183,274 @@ var OrderTypeSelect = (props) => {
2018
2183
  }
2019
2184
  );
2020
2185
  };
2186
+ var OrderEntryContext = createContext(
2187
+ {}
2188
+ );
2189
+ var useOrderEntryContext = () => {
2190
+ return useContext(OrderEntryContext);
2191
+ };
2192
+ var SLIDER_MIN = 0;
2193
+ var SLIDER_MAX = 100;
2194
+ var QuantitySlider = memo((props) => {
2195
+ const { canTrade, side, order_quantity, maxQty } = props;
2196
+ const [sliderValue, setSliderValue] = useState(0);
2197
+ const {
2198
+ setOrderValue,
2199
+ manualSetOrderValue,
2200
+ symbolInfo,
2201
+ lastQuantityInputType
2202
+ } = useOrderEntryContext();
2203
+ const { base_dp, base_tick } = symbolInfo;
2204
+ const { t } = useTranslation();
2205
+ const color = useMemo(
2206
+ () => canTrade ? side === OrderSide.BUY ? "buy" : "sell" : void 0,
2207
+ [side, canTrade]
2208
+ );
2209
+ const maxLabel = useMemo(() => {
2210
+ return side === OrderSide.BUY ? t("orderEntry.maxBuy") : t("orderEntry.maxSell");
2211
+ }, [side, t]);
2212
+ const onSliderValueChange = (value) => {
2213
+ lastQuantityInputType.current = 4 /* QUANTITY_SLIDER */;
2214
+ setSliderValue(value);
2215
+ sliderToQuantity(value, true);
2216
+ };
2217
+ const sliderToQuantity = (value, isManual = false) => {
2218
+ const newQty = new Decimal(value).div(SLIDER_MAX).mul(maxQty).toFixed(base_dp, Decimal.ROUND_DOWN);
2219
+ if (isManual) {
2220
+ manualSetOrderValue?.(
2221
+ "order_quantity",
2222
+ utils.formatNumber(newQty, base_tick)
2223
+ );
2224
+ } else {
2225
+ setOrderValue("order_quantity", utils.formatNumber(newQty, base_tick));
2226
+ }
2227
+ };
2228
+ const onMax = () => {
2229
+ onSliderValueChange(SLIDER_MAX);
2230
+ if (sliderValue === SLIDER_MAX) {
2231
+ sliderToQuantity(SLIDER_MAX, true);
2232
+ }
2233
+ };
2234
+ useEffect(() => {
2235
+ if (lastQuantityInputType.current === 4 /* QUANTITY_SLIDER */) {
2236
+ sliderToQuantity(sliderValue);
2237
+ }
2238
+ }, [maxQty]);
2239
+ useEffect(() => {
2240
+ const quantityToSlider = () => {
2241
+ if (order_quantity && Number(order_quantity) !== 0 && maxQty !== 0) {
2242
+ return new Decimal(Math.min(Number(order_quantity), maxQty)).div(maxQty).mul(SLIDER_MAX).todp(2, Decimal.ROUND_DOWN).toNumber();
2243
+ }
2244
+ return 0;
2245
+ };
2246
+ if (lastQuantityInputType.current !== 4 /* QUANTITY_SLIDER */) {
2247
+ setSliderValue(quantityToSlider());
2248
+ }
2249
+ }, [order_quantity, maxQty]);
2250
+ return /* @__PURE__ */ jsxs("div", { className: "oui-orderEntry-quantitySlider", children: [
2251
+ /* @__PURE__ */ jsx(
2252
+ Slider,
2253
+ {
2254
+ disabled: maxQty === 0 || !canTrade,
2255
+ value: [sliderValue],
2256
+ color,
2257
+ markCount: 4,
2258
+ showTip: true,
2259
+ onValueChange: (e) => {
2260
+ onSliderValueChange(e[0]);
2261
+ },
2262
+ min: SLIDER_MIN,
2263
+ max: SLIDER_MAX
2264
+ }
2265
+ ),
2266
+ /* @__PURE__ */ jsxs(
2267
+ Flex,
2268
+ {
2269
+ justify: "between",
2270
+ className: "oui-quantitySlider-footer oui-pt-1 xl:oui-pt-2",
2271
+ children: [
2272
+ /* @__PURE__ */ jsx(
2273
+ Text.numeral,
2274
+ {
2275
+ size: "2xs",
2276
+ color,
2277
+ dp: 2,
2278
+ padding: false,
2279
+ suffix: "%",
2280
+ children: canTrade ? sliderValue : 0
2281
+ }
2282
+ ),
2283
+ /* @__PURE__ */ jsxs(Flex, { children: [
2284
+ /* @__PURE__ */ jsx(
2285
+ "button",
2286
+ {
2287
+ className: textVariants({
2288
+ size: "2xs",
2289
+ className: "oui-quantitySlider-maxQty-btn oui-mr-1"
2290
+ }),
2291
+ onClick: onMax,
2292
+ "data-testid": "oui-testid-orderEntry-maxQty-value-button",
2293
+ children: maxLabel
2294
+ }
2295
+ ),
2296
+ /* @__PURE__ */ jsx(
2297
+ Text.numeral,
2298
+ {
2299
+ size: "2xs",
2300
+ color,
2301
+ dp: base_dp,
2302
+ padding: false,
2303
+ className: "oui-quantitySlider-maxQty-value",
2304
+ "data-testid": "oui-testid-orderEntry-maxQty-value",
2305
+ children: canTrade ? maxQty : 0
2306
+ }
2307
+ )
2308
+ ] })
2309
+ ]
2310
+ }
2311
+ )
2312
+ ] });
2313
+ });
2314
+ QuantitySlider.displayName = "QuantitySlider";
2315
+ var OrderEntryTypeTabsInjectabled = injectable(
2316
+ (props) => {
2317
+ return /* @__PURE__ */ jsx("div", { className: "oui-w-full", children: /* @__PURE__ */ jsx(
2318
+ OrderTypeSelect,
2319
+ {
2320
+ type: props.type,
2321
+ side: props.side,
2322
+ canTrade: props.canTrade,
2323
+ onChange: props.onChange,
2324
+ marketOrderDisabled: props.marketOrderDisabled,
2325
+ marketOrderDisabledTooltip: props.marketOrderDisabledTooltip
2326
+ }
2327
+ ) });
2328
+ },
2329
+ "Trading.OrderEntry.TypeTabs"
2330
+ );
2331
+ var OrderEntryBuySellSwitchInjectabled = injectable(
2332
+ (props) => {
2333
+ const { t } = useTranslation();
2334
+ return /* @__PURE__ */ jsxs(
2335
+ "div",
2336
+ {
2337
+ className: cn(
2338
+ "oui-orderEntry-side",
2339
+ "oui-grid oui-w-full oui-flex-1 oui-gap-x-2 lg:oui-flex lg:oui-gap-x-[6px]",
2340
+ "oui-grid-cols-2"
2341
+ ),
2342
+ children: [
2343
+ /* @__PURE__ */ jsx(
2344
+ Button,
2345
+ {
2346
+ onClick: () => {
2347
+ props.onSideChange(OrderSide.BUY);
2348
+ },
2349
+ size: "md",
2350
+ fullWidth: true,
2351
+ "data-type": OrderSide.BUY,
2352
+ className: cn(
2353
+ "oui-orderEntry-side-buy-btn",
2354
+ props.side === OrderSide.BUY && props.canTrade ? "oui-bg-success-darken hover:oui-bg-success-darken/80 active:oui-bg-success-darken/80" : "oui-bg-base-7 oui-text-base-contrast-36 hover:oui-bg-base-6 active:oui-bg-base-6"
2355
+ ),
2356
+ "data-testid": "oui-testid-orderEntry-side-buy-button",
2357
+ children: t("common.buy")
2358
+ }
2359
+ ),
2360
+ /* @__PURE__ */ jsx(
2361
+ Button,
2362
+ {
2363
+ onClick: () => {
2364
+ props.onSideChange(OrderSide.SELL);
2365
+ },
2366
+ "data-type": OrderSide.SELL,
2367
+ fullWidth: true,
2368
+ size: "md",
2369
+ className: cn(
2370
+ "oui-orderEntry-side-sell-btn",
2371
+ props.side === OrderSide.SELL && props.canTrade ? "oui-bg-danger-darken hover:oui-bg-danger-darken/80 active:oui-bg-danger-darken/80" : "oui-bg-base-7 oui-text-base-contrast-36 hover:oui-bg-base-6 active:oui-bg-base-6"
2372
+ ),
2373
+ "data-testid": "oui-testid-orderEntry-side-sell-button",
2374
+ children: t("common.sell")
2375
+ }
2376
+ )
2377
+ ]
2378
+ }
2379
+ );
2380
+ },
2381
+ "Trading.OrderEntry.BuySellSwitch"
2382
+ );
2383
+ var OrderEntryAvailableInjectabled = injectable(
2384
+ (props) => {
2385
+ return /* @__PURE__ */ jsx(
2386
+ Available,
2387
+ {
2388
+ currentLtv: props.currentLtv,
2389
+ canTrade: props.canTrade,
2390
+ quote: props.quote,
2391
+ freeCollateral: props.freeCollateral,
2392
+ marginMode: props.marginMode
2393
+ }
2394
+ );
2395
+ },
2396
+ "Trading.OrderEntry.Available"
2397
+ );
2398
+ var OrderEntryQuantitySliderInjectabled = injectable(
2399
+ (props) => {
2400
+ return /* @__PURE__ */ jsx(
2401
+ QuantitySlider,
2402
+ {
2403
+ canTrade: props.canTrade,
2404
+ side: props.side,
2405
+ order_quantity: props.order_quantity,
2406
+ maxQty: props.maxQty
2407
+ }
2408
+ );
2409
+ },
2410
+ "Trading.OrderEntry.QuantitySlider"
2411
+ );
2412
+ var OrderEntrySubmitSectionInjectabled = injectable(
2413
+ (props) => {
2414
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2415
+ /* @__PURE__ */ jsx(
2416
+ ThrottledButton,
2417
+ {
2418
+ fullWidth: true,
2419
+ id: "order-entry-submit-button",
2420
+ "data-type": OrderSide.BUY,
2421
+ className: cn(
2422
+ "oui-orderEntry-submit-btn",
2423
+ props.side === OrderSide.BUY ? "orderly-order-entry-submit-button-buy oui-bg-success-darken hover:oui-bg-success-darken/80 active:oui-bg-success-darken/80" : "orderly-order-entry-submit-button-sell oui-bg-danger-darken hover:oui-bg-danger-darken/80 active:oui-bg-danger-darken/80"
2424
+ ),
2425
+ onClick: props.onSubmit,
2426
+ loading: props.isMutating,
2427
+ disabled: !props.canTrade,
2428
+ children: props.buttonLabel
2429
+ }
2430
+ ),
2431
+ /* @__PURE__ */ jsx(
2432
+ AssetInfo,
2433
+ {
2434
+ canTrade: props.assetInfo.canTrade,
2435
+ quote: props.assetInfo.quote,
2436
+ estLiqPrice: props.assetInfo.estLiqPrice,
2437
+ estLiqPriceDistance: props.assetInfo.estLiqPriceDistance,
2438
+ estLeverage: props.assetInfo.estLeverage,
2439
+ currentLeverage: props.assetInfo.currentLeverage,
2440
+ slippage: props.assetInfo.slippage,
2441
+ dp: props.assetInfo.dp,
2442
+ setSlippage: props.assetInfo.setSlippage,
2443
+ estSlippage: props.assetInfo.estSlippage,
2444
+ orderType: props.assetInfo.orderType,
2445
+ disableFeatures: props.assetInfo.disableFeatures,
2446
+ symbol: props.assetInfo.symbol,
2447
+ side: props.assetInfo.side
2448
+ }
2449
+ )
2450
+ ] });
2451
+ },
2452
+ "Trading.OrderEntry.SubmitSection"
2453
+ );
2021
2454
  var MarginModeSwitch = (props) => {
2022
2455
  const { t } = useTranslation();
2023
2456
  const handleSelect = (mode) => {
@@ -2096,10 +2529,11 @@ var MarginModeSwitch = (props) => {
2096
2529
  {
2097
2530
  className: "oui-tracking-[0.03em]",
2098
2531
  rule: "symbol",
2099
- formatString: "base-type",
2532
+ formatString: "base",
2100
2533
  size: "base",
2101
2534
  weight: "semibold",
2102
2535
  intensity: 98,
2536
+ suffix: /* @__PURE__ */ jsx(SymbolBadge, { symbol: props.symbol }),
2103
2537
  children: props.symbol
2104
2538
  }
2105
2539
  )
@@ -2111,7 +2545,8 @@ var MarginModeSwitch = (props) => {
2111
2545
  mode: MarginMode.CROSS,
2112
2546
  selected: props.selectedMarginMode === MarginMode.CROSS,
2113
2547
  isCurrent: props.currentMarginMode === MarginMode.CROSS,
2114
- onClick: () => handleSelect(MarginMode.CROSS)
2548
+ onClick: () => handleSelect(MarginMode.CROSS),
2549
+ disabled: props.isPermissionlessListing
2115
2550
  }
2116
2551
  ),
2117
2552
  /* @__PURE__ */ jsx(
@@ -2174,9 +2609,11 @@ var OptionCard = (props) => {
2174
2609
  "oui-relative oui-w-full oui-rounded-md oui-p-2",
2175
2610
  "oui-bg-base-6",
2176
2611
  "oui-text-left",
2177
- props.selected ? "oui-border oui-border-[#38e2fe]" : "oui-border oui-border-transparent hover:oui-border-line-12"
2612
+ props.disabled ? "oui-cursor-not-allowed oui-opacity-50 oui-border oui-border-transparent" : props.selected ? "oui-border oui-border-[#38e2fe]" : "oui-border oui-border-transparent hover:oui-border-line-12"
2178
2613
  ),
2179
- onClick: props.onClick,
2614
+ onClick: props.disabled ? void 0 : props.onClick,
2615
+ disabled: props.disabled,
2616
+ "aria-disabled": props.disabled,
2180
2617
  "data-testid": `oui-testid-marginModeSwitch-option-${props.mode}`,
2181
2618
  children: [
2182
2619
  /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, itemAlign: "start", className: "oui-w-full", children: [
@@ -2209,7 +2646,11 @@ var useMarginModeSwitchScript = (options2) => {
2209
2646
  const { symbol, close } = options2;
2210
2647
  const { isMobile } = useScreen();
2211
2648
  const { t } = useTranslation();
2212
- const { marginMode: currentMarginMode, update } = useMarginModeBySymbol(symbol);
2649
+ const {
2650
+ marginMode: currentMarginMode,
2651
+ update,
2652
+ isPermissionlessListing
2653
+ } = useMarginModeBySymbol(symbol);
2213
2654
  const [selectedMarginMode, setSelectedMarginMode] = useState(currentMarginMode);
2214
2655
  useEffect(() => {
2215
2656
  setSelectedMarginMode(currentMarginMode);
@@ -2247,11 +2688,13 @@ var useMarginModeSwitchScript = (options2) => {
2247
2688
  setSelectedMarginMode,
2248
2689
  applyMarginMode,
2249
2690
  close,
2250
- onSelect
2691
+ onSelect,
2692
+ isPermissionlessListing
2251
2693
  };
2252
2694
  };
2253
2695
  var useMarginModeSettingsScript = (options2) => {
2254
2696
  const { isMobile } = useScreen();
2697
+ const { t } = useTranslation();
2255
2698
  const [markets] = useMarkets(MarketsType.ALL);
2256
2699
  const items = useMemo(() => {
2257
2700
  if (!markets || markets.length === 0) {
@@ -2260,10 +2703,20 @@ var useMarginModeSettingsScript = (options2) => {
2260
2703
  return markets.map((market) => ({
2261
2704
  key: market.symbol,
2262
2705
  // Original symbol: "PERP_BTC_USDC"
2263
- symbol: formatSymbol(market.symbol, "base-type")
2706
+ symbol: formatSymbol(market.symbol, "base"),
2264
2707
  // Formatted: "BTC-PERP"
2708
+ brokerId: market.broker_id
2265
2709
  }));
2266
2710
  }, [markets]);
2711
+ const brokerLockedKeys = useMemo(() => {
2712
+ const locked = /* @__PURE__ */ new Set();
2713
+ for (const item of items) {
2714
+ if (item.brokerId) {
2715
+ locked.add(item.key);
2716
+ }
2717
+ }
2718
+ return locked;
2719
+ }, [items]);
2267
2720
  const [searchKeyword, setSearchKeyword] = useState("");
2268
2721
  const [selectedKeys, setSelectedKeys] = useState(
2269
2722
  () => /* @__PURE__ */ new Set()
@@ -2284,11 +2737,15 @@ var useMarginModeSettingsScript = (options2) => {
2284
2737
  const itemMarginModes = useMemo(() => {
2285
2738
  const result = {};
2286
2739
  for (const item of items) {
2740
+ if (brokerLockedKeys.has(item.key)) {
2741
+ result[item.key] = MarginMode.ISOLATED;
2742
+ continue;
2743
+ }
2287
2744
  const marginMode = marginModes[item.key];
2288
2745
  result[item.key] = marginMode ?? MarginMode.CROSS;
2289
2746
  }
2290
2747
  return result;
2291
- }, [items, marginModes]);
2748
+ }, [brokerLockedKeys, items, marginModes]);
2292
2749
  const filteredItems = useMemo(() => {
2293
2750
  const keyword = searchKeyword.trim().toLowerCase();
2294
2751
  if (!keyword) return items;
@@ -2324,17 +2781,21 @@ var useMarginModeSettingsScript = (options2) => {
2324
2781
  const onSearchChange = useCallback((keyword) => {
2325
2782
  setSearchKeyword(keyword);
2326
2783
  }, []);
2327
- const onToggleItem = useCallback((key) => {
2328
- setSelectedKeys((prev) => {
2329
- const next = new Set(prev);
2330
- if (next.has(key)) {
2331
- next.delete(key);
2332
- } else {
2333
- next.add(key);
2334
- }
2335
- return next;
2336
- });
2337
- }, []);
2784
+ const onToggleItem = useCallback(
2785
+ (key) => {
2786
+ if (brokerLockedKeys.has(key)) return;
2787
+ setSelectedKeys((prev) => {
2788
+ const next = new Set(prev);
2789
+ if (next.has(key)) {
2790
+ next.delete(key);
2791
+ } else {
2792
+ next.add(key);
2793
+ }
2794
+ return next;
2795
+ });
2796
+ },
2797
+ [brokerLockedKeys]
2798
+ );
2338
2799
  const onToggleSelectAll = useCallback(() => {
2339
2800
  setSelectedKeys((prev) => {
2340
2801
  const next = new Set(prev);
@@ -2345,31 +2806,39 @@ var useMarginModeSettingsScript = (options2) => {
2345
2806
  return next;
2346
2807
  }
2347
2808
  for (const item of filteredItems) {
2809
+ if (brokerLockedKeys.has(item.key)) continue;
2348
2810
  next.add(item.key);
2349
2811
  }
2350
2812
  return next;
2351
2813
  });
2352
- }, [filteredItems, isSelectAll]);
2814
+ }, [brokerLockedKeys, filteredItems, isSelectAll]);
2353
2815
  const onSetMarginMode = useCallback(
2354
2816
  async (mode) => {
2355
2817
  if (selectedKeys.size === 0) return;
2818
+ const editableSymbolList = Array.from(selectedKeys).filter(
2819
+ (key) => !brokerLockedKeys.has(key)
2820
+ );
2821
+ if (editableSymbolList.length === 0) {
2822
+ toast.error(t("marginMode.noEditableSymbolsSelected"));
2823
+ return;
2824
+ }
2356
2825
  setIsOperationLoading(true);
2357
2826
  try {
2358
2827
  const payload = {
2359
- symbol_list: Array.from(selectedKeys),
2828
+ symbol_list: editableSymbolList,
2360
2829
  default_margin_mode: mode
2361
2830
  };
2362
2831
  await updateMarginMode(payload);
2363
- toast.success("Updated successfully");
2832
+ toast.success(t("marginMode.updatedSuccessfully"));
2364
2833
  } catch (error) {
2365
2834
  toast.error(
2366
- error instanceof Error ? error.message : "Failed to update margin mode"
2835
+ error instanceof Error ? error.message : t("marginMode.failedToUpdateMarginMode")
2367
2836
  );
2368
2837
  } finally {
2369
2838
  setIsOperationLoading(false);
2370
2839
  }
2371
2840
  },
2372
- [selectedKeys, updateMarginMode]
2841
+ [brokerLockedKeys, selectedKeys, updateMarginMode]
2373
2842
  );
2374
2843
  const isLoading = isDataLoading || isMarginModesLoading || isOperationLoading || isSettingMarginMode;
2375
2844
  return {
@@ -2517,7 +2986,8 @@ var MarginModeSettings = (props) => {
2517
2986
  item,
2518
2987
  checked: props.selectedKeys.has(item.key),
2519
2988
  marginMode: props.itemMarginModes[item.key] ?? MarginMode.CROSS,
2520
- onToggle: props.onToggleItem
2989
+ onToggle: props.onToggleItem,
2990
+ disabled: !!item.brokerId
2521
2991
  },
2522
2992
  item.key
2523
2993
  ))
@@ -2620,13 +3090,15 @@ var MarginModeSettings = (props) => {
2620
3090
  var SymbolRow = (props) => {
2621
3091
  const { t } = useTranslation();
2622
3092
  const handleCheckedChange = useCallback(() => {
3093
+ if (props.disabled) return;
2623
3094
  props.onToggle(props.item.key);
2624
3095
  }, [props]);
2625
- return /* @__PURE__ */ jsx(Flex, { itemAlign: "center", className: "oui-w-full", children: /* @__PURE__ */ jsxs(
3096
+ const row = /* @__PURE__ */ jsx(Flex, { itemAlign: "center", className: "oui-w-full", children: /* @__PURE__ */ jsxs(
2626
3097
  "label",
2627
3098
  {
2628
3099
  className: cn(
2629
- "oui-flex oui-items-center oui-gap-2 oui-flex-1 oui-cursor-pointer oui-select-none oui-w-full"
3100
+ "oui-flex oui-items-center oui-gap-2 oui-flex-1 oui-cursor-pointer oui-select-none oui-w-full",
3101
+ props.disabled ? "oui-cursor-not-allowed oui-opacity-50" : ""
2630
3102
  ),
2631
3103
  "data-testid": `oui-testid-marginModeSettings-item-${props.item.key}`,
2632
3104
  children: [
@@ -2636,10 +3108,12 @@ var SymbolRow = (props) => {
2636
3108
  color: "white",
2637
3109
  checked: props.checked,
2638
3110
  onCheckedChange: handleCheckedChange,
2639
- "aria-label": props.item.symbol
3111
+ "aria-label": props.item.symbol,
3112
+ disabled: props.disabled
2640
3113
  }
2641
3114
  ),
2642
3115
  /* @__PURE__ */ jsx(Text, { className: "oui-text-sm oui-font-semibold oui-text-base-contrast-80", children: props.item.symbol }),
3116
+ /* @__PURE__ */ jsx(SymbolBadge, { symbol: props.item.key }),
2643
3117
  /* @__PURE__ */ jsx(
2644
3118
  "span",
2645
3119
  {
@@ -2655,6 +3129,17 @@ var SymbolRow = (props) => {
2655
3129
  ]
2656
3130
  }
2657
3131
  ) });
3132
+ if (props.disabled) {
3133
+ return /* @__PURE__ */ jsx(
3134
+ Tooltip,
3135
+ {
3136
+ content: t("marginMode.disabledSymbolTooltip"),
3137
+ className: "oui-max-w-[280px] oui-text-2xs oui-text-base-contrast-80",
3138
+ children: row
3139
+ }
3140
+ );
3141
+ }
3142
+ return row;
2658
3143
  };
2659
3144
  var SearchGlyph = (props) => {
2660
3145
  return /* @__PURE__ */ jsx(
@@ -2826,7 +3311,6 @@ var LeverageBadge = (props) => {
2826
3311
  };
2827
3312
  function OrderEntryHeader(props) {
2828
3313
  const { canTrade, side, order_type, setOrderValue } = props;
2829
- const { t } = useTranslation();
2830
3314
  return /* @__PURE__ */ jsxs(Fragment, { children: [
2831
3315
  /* @__PURE__ */ jsx("div", { className: "oui-w-full", children: /* @__PURE__ */ jsx(
2832
3316
  LeverageBadge,
@@ -2838,71 +3322,31 @@ function OrderEntryHeader(props) {
2838
3322
  disabled: !props.canTrade
2839
3323
  }
2840
3324
  ) }),
2841
- /* @__PURE__ */ jsx("div", { className: "oui-w-full", children: /* @__PURE__ */ jsx(
2842
- OrderTypeSelect,
3325
+ /* @__PURE__ */ jsx(
3326
+ OrderEntryTypeTabsInjectabled,
2843
3327
  {
2844
3328
  type: order_type,
2845
3329
  side,
2846
3330
  canTrade,
2847
3331
  onChange: (type) => {
2848
3332
  setOrderValue("order_type", type);
2849
- }
3333
+ },
3334
+ marketOrderDisabled: props.marketOrderDisabled,
3335
+ marketOrderDisabledTooltip: props.marketOrderDisabledTooltip
2850
3336
  }
2851
- ) }),
2852
- /* @__PURE__ */ jsxs(
2853
- "div",
3337
+ ),
3338
+ /* @__PURE__ */ jsx(
3339
+ OrderEntryBuySellSwitchInjectabled,
2854
3340
  {
2855
- className: cn(
2856
- "oui-orderEntry-side",
2857
- "oui-grid oui-w-full oui-flex-1 oui-gap-x-2 lg:oui-flex lg:oui-gap-x-[6px]",
2858
- "oui-grid-cols-2"
2859
- ),
2860
- children: [
2861
- /* @__PURE__ */ jsx(
2862
- Button,
2863
- {
2864
- onClick: () => {
2865
- props.setOrderValue("side", OrderSide.BUY);
2866
- },
2867
- size: "md",
2868
- fullWidth: true,
2869
- "data-type": OrderSide.BUY,
2870
- className: cn(
2871
- "oui-orderEntry-side-buy-btn",
2872
- side === OrderSide.BUY && canTrade ? "oui-bg-success-darken hover:oui-bg-success-darken/80 active:oui-bg-success-darken/80" : "oui-bg-base-7 oui-text-base-contrast-36 hover:oui-bg-base-6 active:oui-bg-base-6"
2873
- ),
2874
- "data-testid": "oui-testid-orderEntry-side-buy-button",
2875
- children: t("common.buy")
2876
- }
2877
- ),
2878
- /* @__PURE__ */ jsx(
2879
- Button,
2880
- {
2881
- onClick: () => {
2882
- props.setOrderValue("side", OrderSide.SELL);
2883
- },
2884
- "data-type": OrderSide.SELL,
2885
- fullWidth: true,
2886
- size: "md",
2887
- className: cn(
2888
- "oui-orderEntry-side-sell-btn",
2889
- side === OrderSide.SELL && props.canTrade ? "oui-bg-danger-darken hover:oui-bg-danger-darken/80 active:oui-bg-danger-darken/80" : "oui-bg-base-7 oui-text-base-contrast-36 hover:oui-bg-base-6 active:oui-bg-base-6"
2890
- ),
2891
- "data-testid": "oui-testid-orderEntry-side-sell-button",
2892
- children: t("common.sell")
2893
- }
2894
- )
2895
- ]
3341
+ side,
3342
+ canTrade,
3343
+ onSideChange: (nextSide) => {
3344
+ props.setOrderValue("side", nextSide);
3345
+ }
2896
3346
  }
2897
3347
  )
2898
3348
  ] });
2899
3349
  }
2900
- var OrderEntryContext = createContext(
2901
- {}
2902
- );
2903
- var useOrderEntryContext = () => {
2904
- return useContext(OrderEntryContext);
2905
- };
2906
3350
  var OrderEntryProvider = (props) => {
2907
3351
  const {
2908
3352
  errorMsgVisible,
@@ -2911,6 +3355,7 @@ var OrderEntryProvider = (props) => {
2911
3355
  onBlur,
2912
3356
  getErrorMsg,
2913
3357
  setOrderValue,
3358
+ manualSetOrderValue,
2914
3359
  setOrderValues,
2915
3360
  currentFocusInput,
2916
3361
  errors,
@@ -2929,6 +3374,7 @@ var OrderEntryProvider = (props) => {
2929
3374
  onBlur,
2930
3375
  getErrorMsg,
2931
3376
  setOrderValue,
3377
+ manualSetOrderValue,
2932
3378
  setOrderValues,
2933
3379
  currentFocusInput,
2934
3380
  errors,
@@ -2947,6 +3393,7 @@ var OrderEntryProvider = (props) => {
2947
3393
  onBlur,
2948
3394
  getErrorMsg,
2949
3395
  setOrderValue,
3396
+ manualSetOrderValue,
2950
3397
  setOrderValues,
2951
3398
  currentFocusInput,
2952
3399
  errors,
@@ -4370,116 +4817,6 @@ function OrderInput(props) {
4370
4817
  )
4371
4818
  ] });
4372
4819
  }
4373
- var SLIDER_MIN = 0;
4374
- var SLIDER_MAX = 100;
4375
- var QuantitySlider = memo((props) => {
4376
- const { canTrade, side, order_quantity, maxQty } = props;
4377
- const [sliderValue, setSliderValue] = useState(0);
4378
- const { setOrderValue, symbolInfo, lastQuantityInputType } = useOrderEntryContext();
4379
- const { base_dp, base_tick } = symbolInfo;
4380
- const { t } = useTranslation();
4381
- const color = useMemo(
4382
- () => canTrade ? side === OrderSide.BUY ? "buy" : "sell" : void 0,
4383
- [side, canTrade]
4384
- );
4385
- const maxLabel = useMemo(() => {
4386
- return side === OrderSide.BUY ? t("orderEntry.maxBuy") : t("orderEntry.maxSell");
4387
- }, [side, t]);
4388
- const onSliderValueChange = (value) => {
4389
- lastQuantityInputType.current = 4 /* QUANTITY_SLIDER */;
4390
- setSliderValue(value);
4391
- };
4392
- const sliderToQuantity = (value) => {
4393
- const newQty = new Decimal(value).div(SLIDER_MAX).mul(maxQty).toFixed(base_dp, Decimal.ROUND_DOWN);
4394
- setOrderValue("order_quantity", utils.formatNumber(newQty, base_tick));
4395
- };
4396
- const onMax = () => {
4397
- onSliderValueChange(SLIDER_MAX);
4398
- if (sliderValue === SLIDER_MAX) {
4399
- sliderToQuantity(SLIDER_MAX);
4400
- }
4401
- };
4402
- useEffect(() => {
4403
- if (lastQuantityInputType.current === 4 /* QUANTITY_SLIDER */) {
4404
- sliderToQuantity(sliderValue);
4405
- }
4406
- }, [sliderValue, maxQty]);
4407
- useEffect(() => {
4408
- const quantityToSlider = () => {
4409
- if (order_quantity && Number(order_quantity) !== 0 && maxQty !== 0) {
4410
- return new Decimal(Math.min(Number(order_quantity), maxQty)).div(maxQty).mul(SLIDER_MAX).todp(2, Decimal.ROUND_DOWN).toNumber();
4411
- }
4412
- return 0;
4413
- };
4414
- if (lastQuantityInputType.current !== 4 /* QUANTITY_SLIDER */) {
4415
- setSliderValue(quantityToSlider());
4416
- }
4417
- }, [order_quantity, maxQty]);
4418
- return /* @__PURE__ */ jsxs("div", { className: "oui-orderEntry-quantitySlider", children: [
4419
- /* @__PURE__ */ jsx(
4420
- Slider,
4421
- {
4422
- disabled: maxQty === 0 || !canTrade,
4423
- value: [sliderValue],
4424
- color,
4425
- markCount: 4,
4426
- showTip: true,
4427
- onValueChange: (e) => {
4428
- onSliderValueChange(e[0]);
4429
- },
4430
- min: SLIDER_MIN,
4431
- max: SLIDER_MAX
4432
- }
4433
- ),
4434
- /* @__PURE__ */ jsxs(
4435
- Flex,
4436
- {
4437
- justify: "between",
4438
- className: "oui-quantitySlider-footer oui-pt-1 xl:oui-pt-2",
4439
- children: [
4440
- /* @__PURE__ */ jsx(
4441
- Text.numeral,
4442
- {
4443
- size: "2xs",
4444
- color,
4445
- dp: 2,
4446
- padding: false,
4447
- suffix: "%",
4448
- children: canTrade ? sliderValue : 0
4449
- }
4450
- ),
4451
- /* @__PURE__ */ jsxs(Flex, { children: [
4452
- /* @__PURE__ */ jsx(
4453
- "button",
4454
- {
4455
- className: textVariants({
4456
- size: "2xs",
4457
- className: "oui-quantitySlider-maxQty-btn oui-mr-1"
4458
- }),
4459
- onClick: onMax,
4460
- "data-testid": "oui-testid-orderEntry-maxQty-value-button",
4461
- children: maxLabel
4462
- }
4463
- ),
4464
- /* @__PURE__ */ jsx(
4465
- Text.numeral,
4466
- {
4467
- size: "2xs",
4468
- color,
4469
- dp: base_dp,
4470
- padding: false,
4471
- className: "oui-quantitySlider-maxQty-value",
4472
- "data-testid": "oui-testid-orderEntry-maxQty-value",
4473
- children: canTrade ? maxQty : 0
4474
- }
4475
- )
4476
- ] })
4477
- ]
4478
- }
4479
- )
4480
- ] });
4481
- });
4482
- QuantitySlider.displayName = "QuantitySlider";
4483
4820
  var ReduceOnlySwitch = ({
4484
4821
  checked,
4485
4822
  onCheckedChange,
@@ -4523,10 +4860,19 @@ var usePnlInputContext = () => {
4523
4860
  };
4524
4861
 
4525
4862
  // src/components/pnlInput/useBuilder.script.ts
4863
+ function normalizeSlPnlForStore(raw) {
4864
+ const v = `${raw}`.replace(/,/g, "").trim();
4865
+ if (v === "" || v === "-") return v;
4866
+ const withoutTrailingDot = v.replace(/\.$/, "");
4867
+ const num = Number(withoutTrailingDot);
4868
+ if (!isNaN(num) && num === 0) return "0";
4869
+ if (v.startsWith("-")) return v;
4870
+ return `-${v}`;
4871
+ }
4526
4872
  var usePNLInputBuilder = (props) => {
4527
4873
  const { type, values, quote_dp } = props;
4528
4874
  const { t } = useTranslation();
4529
- const [focus, setFocus] = useState(true);
4875
+ const [, setFocus] = useState(true);
4530
4876
  const { mode, setMode, tipsEle } = usePnlInputContext();
4531
4877
  const [tipVisible, setTipVisible] = useState(false);
4532
4878
  const [isFocused, setIsFocused] = useState(false);
@@ -4536,10 +4882,14 @@ var usePNLInputBuilder = (props) => {
4536
4882
  return `${type.toLowerCase()}_offset`;
4537
4883
  case "Offset%" /* PERCENTAGE */:
4538
4884
  return `${type.toLowerCase()}_offset_percentage`;
4885
+ case "OffsetFromMark" /* OFFSET_FROM_MARK */:
4886
+ return `${type.toLowerCase()}_offset_from_mark`;
4887
+ case "PercentageFromMark" /* PERCENTAGE_FROM_MARK */:
4888
+ return `${type.toLowerCase()}_offset_percentage_from_mark`;
4539
4889
  default:
4540
4890
  return `${type.toLowerCase()}_pnl`;
4541
4891
  }
4542
- }, [mode]);
4892
+ }, [mode, type]);
4543
4893
  const [innerValue, setInnerValue] = useState(
4544
4894
  values[mode]
4545
4895
  );
@@ -4562,23 +4912,39 @@ var usePNLInputBuilder = (props) => {
4562
4912
  testId: `${"Offset" /* OFFSET */}_mneu_item`
4563
4913
  },
4564
4914
  {
4565
- label: `${t("tpsl.offset")}%`,
4915
+ label: t("tpsl.offsetPercent"),
4566
4916
  value: "Offset%" /* PERCENTAGE */,
4567
4917
  testId: `${"Offset%" /* PERCENTAGE */}_menu_item`
4918
+ },
4919
+ {
4920
+ // @ts-ignore
4921
+ label: t("tpsl.offsetMark"),
4922
+ value: "OffsetFromMark" /* OFFSET_FROM_MARK */,
4923
+ testId: `${"OffsetFromMark" /* OFFSET_FROM_MARK */}_menu_item`
4924
+ },
4925
+ {
4926
+ // @ts-ignore
4927
+ label: t("tpsl.offsetPercentMark"),
4928
+ value: "PercentageFromMark" /* PERCENTAGE_FROM_MARK */,
4929
+ testId: `${"PercentageFromMark" /* PERCENTAGE_FROM_MARK */}_menu_item`
4568
4930
  }
4569
4931
  ];
4570
4932
  }, [t]);
4571
4933
  const modeLabelMap = useMemo(() => {
4572
4934
  return {
4573
4935
  ["PnL" /* PnL */]: t("tpsl.pnl"),
4574
- ["Offset" /* OFFSET */]: t("tpsl.offset"),
4575
- ["Offset%" /* PERCENTAGE */]: `${t("tpsl.offset")}%`
4936
+ ["Offset" /* OFFSET */]: t("tpsl.offsetHolder"),
4937
+ ["Offset%" /* PERCENTAGE */]: `${t("tpsl.offsetHolder")}`,
4938
+ // Extend locale keys; not yet in LocaleMessages typings
4939
+ ["OffsetFromMark" /* OFFSET_FROM_MARK */]: t("tpsl.offsetHolder"),
4940
+ ["PercentageFromMark" /* PERCENTAGE_FROM_MARK */]: t("tpsl.offsetHolder")
4576
4941
  };
4577
4942
  }, [t]);
4578
4943
  const percentageSuffix = useRef("");
4579
4944
  const onValueChange = (value) => {
4580
4945
  setInnerValue(value);
4581
- props.onChange(key, value);
4946
+ const outgoing = key === "sl_pnl" ? normalizeSlPnlForStore(value) : value;
4947
+ props.onChange(key, outgoing);
4582
4948
  };
4583
4949
  const onFocus = () => {
4584
4950
  setTipVisible(true);
@@ -4587,27 +4953,29 @@ var usePNLInputBuilder = (props) => {
4587
4953
  const onBlur = () => {
4588
4954
  setTipVisible(false);
4589
4955
  setIsFocused(false);
4590
- props.onChange(key, innerValue);
4956
+ const outgoing = key === "sl_pnl" ? normalizeSlPnlForStore(innerValue) : innerValue;
4957
+ props.onChange(key, outgoing);
4591
4958
  };
4592
4959
  const formatter = (options2) => {
4593
4960
  const { dp = 2 } = options2;
4594
4961
  return {
4595
4962
  onRenderBefore: (value, options3) => {
4596
4963
  value = `${value}`;
4597
- if (focus) {
4598
- if (type === "SL" && mode === "PnL" /* PnL */) {
4599
- value = value.startsWith("-") ? value : "-" + value;
4600
- }
4964
+ if (type === "SL" && mode === "PnL" /* PnL */) {
4965
+ value = value.startsWith("-") ? value : "-" + value;
4601
4966
  }
4602
4967
  if (value === "" || value === "-") return "";
4603
- if (mode === "Offset%" /* PERCENTAGE */) {
4604
- return `${new Decimal(
4605
- value.replace(
4606
- new RegExp(percentageSuffix.current.replace(".", "\\.") + "$"),
4607
- ""
4608
- )
4609
- ).mul(100).todp(2, 4).toString()}${percentageSuffix.current}`;
4610
- } else if (mode === "Offset" /* OFFSET */) {
4968
+ if (mode === "Offset%" /* PERCENTAGE */ || mode === "PercentageFromMark" /* PERCENTAGE_FROM_MARK */) {
4969
+ let normalized = value.replace(
4970
+ new RegExp(percentageSuffix.current.replace(".", "\\.") + "$"),
4971
+ ""
4972
+ ).replace(/,/g, "");
4973
+ normalized = normalized.replace(/\.$/, "");
4974
+ if (isNaN(Number(normalized)) || normalized === "" || normalized === "-") {
4975
+ return value;
4976
+ }
4977
+ return `${new Decimal(normalized).mul(100).todp(2, 4).toString()}${percentageSuffix.current}`;
4978
+ } else if (mode === "Offset" /* OFFSET */ || mode === "OffsetFromMark" /* OFFSET_FROM_MARK */) {
4611
4979
  value = todpIfNeed(value, dp);
4612
4980
  } else ;
4613
4981
  return `${value}`;
@@ -4616,7 +4984,7 @@ var usePNLInputBuilder = (props) => {
4616
4984
  if (/^\-?0{2,}$/.test(value)) {
4617
4985
  return "0";
4618
4986
  }
4619
- if (mode === "Offset%" /* PERCENTAGE */) {
4987
+ if (mode === "Offset%" /* PERCENTAGE */ || mode === "PercentageFromMark" /* PERCENTAGE_FROM_MARK */) {
4620
4988
  if (value !== "") {
4621
4989
  value = todpIfNeed(value, 2);
4622
4990
  const endStr = value.match(/\.0{0,2}$/);
@@ -4625,10 +4993,13 @@ var usePNLInputBuilder = (props) => {
4625
4993
  } else {
4626
4994
  percentageSuffix.current = "";
4627
4995
  }
4996
+ if (isNaN(Number(value))) {
4997
+ return value;
4998
+ }
4628
4999
  value = new Decimal(value).div(100).toString();
4629
5000
  value = `${value}${percentageSuffix.current}`;
4630
5001
  }
4631
- } else if (mode === "PnL" /* PnL */ && type === "SL" && focus) {
5002
+ } else if (mode === "PnL" /* PnL */ && type === "SL") {
4632
5003
  value = value.startsWith("-") ? value : "-" + value;
4633
5004
  } else {
4634
5005
  value = todpIfNeed(value, dp);
@@ -4672,21 +5043,28 @@ var PNLInput = (props) => {
4672
5043
  setFocus
4673
5044
  } = props;
4674
5045
  const [prefix, setPrefix] = useState(mode);
5046
+ const isPercentageMode = mode === "Offset%" /* PERCENTAGE */ || mode === "PercentageFromMark" /* PERCENTAGE_FROM_MARK */;
4675
5047
  const [placeholder, setPlaceholder] = useState(
4676
- mode === "Offset%" /* PERCENTAGE */ ? "%" : quote
5048
+ isPercentageMode ? "%" : quote
4677
5049
  );
4678
5050
  useEffect(() => {
4679
5051
  setPrefix(mode);
4680
- setPlaceholder(mode === "Offset%" /* PERCENTAGE */ ? "%" : quote);
4681
- }, [mode]);
5052
+ setPlaceholder(isPercentageMode ? "%" : quote);
5053
+ }, [mode, isPercentageMode, quote]);
4682
5054
  useEffect(() => {
4683
5055
  setPrefix(!!value ? "" : mode);
4684
5056
  }, [value]);
4685
- const id = useMemo(() => `${type.toLowerCase()}_${mode.toLowerCase()}`, []);
5057
+ const id = useMemo(
5058
+ () => `${type.toLowerCase()}_${mode.toLowerCase()}`,
5059
+ [type, mode]
5060
+ );
5061
+ const prefixLabel = prefix === "" ? "" : String(
5062
+ modeLabelMap[prefix] ?? prefix ?? ""
5063
+ );
4686
5064
  return /* @__PURE__ */ jsx(
4687
5065
  Input.tooltip,
4688
5066
  {
4689
- prefix: modeLabelMap[prefix] || prefix,
5067
+ prefix: prefixLabel,
4690
5068
  size: "md",
4691
5069
  placeholder,
4692
5070
  id,
@@ -4723,11 +5101,11 @@ var PNLInput = (props) => {
4723
5101
  },
4724
5102
  onBlur: () => {
4725
5103
  setPrefix(!!value ? "" : mode);
4726
- setPlaceholder(mode === "Offset%" /* PERCENTAGE */ ? "%" : quote);
5104
+ setPlaceholder(isPercentageMode ? "%" : quote);
4727
5105
  onBlur();
4728
5106
  },
4729
5107
  suffix: /* @__PURE__ */ jsxs(Fragment, { children: [
4730
- mode === "Offset%" /* PERCENTAGE */ && !!value && /* @__PURE__ */ jsx(Text, { size: "2xs", color: "inherit", className: "oui-ml-[2px]", children: "%" }),
5108
+ isPercentageMode && !!value && /* @__PURE__ */ jsx(Text, { size: "2xs", color: "inherit", className: "oui-ml-[2px]", children: "%" }),
4731
5109
  /* @__PURE__ */ jsx(
4732
5110
  PNLMenus,
4733
5111
  {
@@ -4872,8 +5250,8 @@ var OrderTPSL = (props) => {
4872
5250
  {
4873
5251
  className: cn(
4874
5252
  "oui-orderEntry-tpsl-body",
4875
- "oui-max-h-0 oui-overflow-hidden oui-transition-all",
4876
- props.switchState && "oui-max-h-[120px]"
5253
+ "oui-overflow-hidden oui-transition-all",
5254
+ props.switchState ? "oui-max-h-[120px]" : "oui-max-h-0"
4877
5255
  ),
4878
5256
  onTransitionEnd: () => {
4879
5257
  tpslFormRef.current?.style.setProperty(
@@ -5147,6 +5525,8 @@ var TPSLInputRow = (props) => {
5147
5525
  PnL: props.values.PnL,
5148
5526
  Offset: props.values.Offset,
5149
5527
  "Offset%": props.values["Offset%"],
5528
+ OffsetFromMark: props.values.OffsetFromMark,
5529
+ PercentageFromMark: props.values.PercentageFromMark,
5150
5530
  ROI: props.values.ROI
5151
5531
  }
5152
5532
  }
@@ -5158,7 +5538,9 @@ var OrderEntry = (props) => {
5158
5538
  side,
5159
5539
  formattedOrder,
5160
5540
  setOrderValue,
5541
+ manualSetOrderValue,
5161
5542
  setOrderValues,
5543
+ setOrderValuesRaw,
5162
5544
  symbolInfo,
5163
5545
  maxQty,
5164
5546
  freeCollateral,
@@ -5174,9 +5556,13 @@ var OrderEntry = (props) => {
5174
5556
  fillMiddleValue,
5175
5557
  soundAlert,
5176
5558
  setSoundAlert,
5177
- currentFocusInput
5559
+ currentFocusInput,
5560
+ walletAddress,
5561
+ isPermissionlessListing,
5562
+ symbol
5178
5563
  } = props;
5179
5564
  const [maxQtyConfirmOpen, setMaxQtyConfirmOpen] = useState(false);
5565
+ const [permissionlessAcknowledgedKeys, setPermissionlessAcknowledgedKeys] = useLocalStorage("orderly-permissionless-market-notice", []);
5180
5566
  const { t } = useTranslation();
5181
5567
  const { isMobile } = useScreen();
5182
5568
  const [hasAdvancedTPSLResult, setHasAdvancedTPSLResult] = useState(false);
@@ -5213,11 +5599,11 @@ var OrderEntry = (props) => {
5213
5599
  return;
5214
5600
  }
5215
5601
  if (slippage) {
5216
- setOrderValue("slippage", Number(slippage));
5602
+ manualSetOrderValue("slippage", Number(slippage));
5217
5603
  } else {
5218
- setOrderValue("slippage", void 0);
5604
+ manualSetOrderValue("slippage", void 0);
5219
5605
  }
5220
- }, [slippage, disableFeatures]);
5606
+ }, [slippage, disableFeatures, manualSetOrderValue]);
5221
5607
  useEffect(() => {
5222
5608
  const clickHandler = (event) => {
5223
5609
  const target = event.target;
@@ -5246,22 +5632,7 @@ var OrderEntry = (props) => {
5246
5632
  helper.validate(isSlPriceError ? props.slPriceError : void 0).then(
5247
5633
  // validate success, it return the order
5248
5634
  // TODO: get order from other function
5249
- (order) => {
5250
- if (isScaledOrder) {
5251
- return modal.show(scaledOrderConfirmDialogId, {
5252
- order,
5253
- symbolInfo,
5254
- size: isMobile ? "sm" : "md"
5255
- });
5256
- }
5257
- if (needConfirm) {
5258
- return modal.show(orderConfirmDialogId, {
5259
- order: formattedOrder,
5260
- symbolInfo
5261
- });
5262
- }
5263
- return true;
5264
- },
5635
+ (order) => order,
5265
5636
  // should catch validate error first, then submit
5266
5637
  (errors2) => {
5267
5638
  if (errors2.slippage) {
@@ -5270,7 +5641,38 @@ var OrderEntry = (props) => {
5270
5641
  setErrorMsgVisible(true);
5271
5642
  return Promise.reject();
5272
5643
  }
5273
- ).then(() => {
5644
+ ).then((order) => {
5645
+ const shouldShowPermissionlessNotice = isPermissionlessListing && walletAddress && !(permissionlessAcknowledgedKeys ?? []).includes(
5646
+ `${walletAddress}_${symbol}`
5647
+ );
5648
+ if (shouldShowPermissionlessNotice) {
5649
+ return modal.show(
5650
+ isMobile ? permissionlessMarketNoticeDialogId : permissionlessMarketNoticeDesktopDialogId
5651
+ ).then(() => {
5652
+ setPermissionlessAcknowledgedKeys([
5653
+ ...Array.isArray(permissionlessAcknowledgedKeys) ? permissionlessAcknowledgedKeys : [],
5654
+ `${walletAddress}_${symbol}`
5655
+ ]);
5656
+ return order;
5657
+ });
5658
+ }
5659
+ return Promise.resolve(order);
5660
+ }).then((order) => {
5661
+ if (isScaledOrder) {
5662
+ return modal.show(scaledOrderConfirmDialogId, {
5663
+ order,
5664
+ symbolInfo,
5665
+ size: isMobile ? "sm" : "md"
5666
+ });
5667
+ }
5668
+ if (needConfirm) {
5669
+ return modal.show(orderConfirmDialogId, {
5670
+ order: formattedOrder,
5671
+ symbolInfo
5672
+ });
5673
+ }
5674
+ return true;
5675
+ }).then(() => {
5274
5676
  return submit({ resetOnSuccess: false }).then((result) => {
5275
5677
  if (!result.success && result.message) {
5276
5678
  toast.error(result.message);
@@ -5291,12 +5693,12 @@ var OrderEntry = (props) => {
5291
5693
  return new Decimal(maxQty).todp(symbolInfo.base_dp, Decimal.ROUND_DOWN).toString();
5292
5694
  }, [maxQty, symbolInfo.base_dp]);
5293
5695
  const onMaxQtyConfirm = useCallback(() => {
5294
- setOrderValue("order_quantity", formattedMaxQty);
5696
+ manualSetOrderValue("order_quantity", formattedMaxQty);
5295
5697
  requestAnimationFrame(() => {
5296
5698
  onSubmit();
5297
5699
  });
5298
5700
  setMaxQtyConfirmOpen(false);
5299
- }, [setOrderValue, formattedMaxQty]);
5701
+ }, [manualSetOrderValue, formattedMaxQty, onSubmit]);
5300
5702
  const validateSubmit = async () => {
5301
5703
  if (formattedOrder.reduce_only && maxQty === 0) {
5302
5704
  return modal.confirm({
@@ -5304,7 +5706,7 @@ var OrderEntry = (props) => {
5304
5706
  content: t("orderEntry.reduceOnly.reminder.content"),
5305
5707
  okLabel: t("orderEntry.placeOrderNow"),
5306
5708
  onOk: async () => {
5307
- setOrderValue("reduce_only", false);
5709
+ manualSetOrderValue("reduce_only", false);
5308
5710
  requestAnimationFrame(() => {
5309
5711
  props.resetMetaState();
5310
5712
  onSubmit();
@@ -5336,14 +5738,16 @@ var OrderEntry = (props) => {
5336
5738
  };
5337
5739
  const onSubmitAdvancedTPSL = (order) => {
5338
5740
  if (order.side !== formattedOrder.side) {
5339
- setOrderValue("side", order.side);
5741
+ manualSetOrderValue("side", order.side);
5340
5742
  }
5341
- setOrderValues({
5743
+ setOrderValuesRaw({
5342
5744
  position_type: order.position_type,
5343
5745
  tp_order_type: order.tp_order_type,
5344
5746
  tp_pnl: order.tp_pnl,
5345
5747
  tp_offset: order.tp_offset,
5346
5748
  tp_offset_percentage: order.tp_offset_percentage,
5749
+ tp_offset_from_mark: order.tp_offset_from_mark,
5750
+ tp_offset_percentage_from_mark: order.tp_offset_percentage_from_mark,
5347
5751
  tp_ROI: order.tp_ROI,
5348
5752
  tp_trigger_price: order.tp_trigger_price,
5349
5753
  tp_order_price: order.tp_order_price,
@@ -5353,6 +5757,8 @@ var OrderEntry = (props) => {
5353
5757
  sl_pnl: order.sl_pnl,
5354
5758
  sl_offset: order.sl_offset,
5355
5759
  sl_offset_percentage: order.sl_offset_percentage,
5760
+ sl_offset_from_mark: order.sl_offset_from_mark,
5761
+ sl_offset_percentage_from_mark: order.sl_offset_percentage_from_mark,
5356
5762
  sl_ROI: order.sl_ROI
5357
5763
  });
5358
5764
  setShowTPSLAdvanced(false);
@@ -5369,6 +5775,14 @@ var OrderEntry = (props) => {
5369
5775
  sl_order_type: OrderType.MARKET,
5370
5776
  tp_pnl: void 0,
5371
5777
  sl_pnl: void 0,
5778
+ tp_offset: void 0,
5779
+ tp_offset_percentage: void 0,
5780
+ tp_offset_from_mark: void 0,
5781
+ tp_offset_percentage_from_mark: void 0,
5782
+ sl_offset: void 0,
5783
+ sl_offset_percentage: void 0,
5784
+ sl_offset_from_mark: void 0,
5785
+ sl_offset_percentage_from_mark: void 0,
5372
5786
  position_type: PositionType.FULL
5373
5787
  });
5374
5788
  };
@@ -5384,7 +5798,7 @@ var OrderEntry = (props) => {
5384
5798
  setNeedConfirm,
5385
5799
  hidden,
5386
5800
  setHidden,
5387
- onValueChange: setOrderValue,
5801
+ onValueChange: manualSetOrderValue,
5388
5802
  orderTypeExtra: formattedOrder["order_type_ext"],
5389
5803
  showExtra: formattedOrder["order_type"] === OrderType.LIMIT && !props.tpslSwitch
5390
5804
  };
@@ -5399,6 +5813,7 @@ var OrderEntry = (props) => {
5399
5813
  onBlur: props.onBlur,
5400
5814
  getErrorMsg,
5401
5815
  setOrderValue,
5816
+ manualSetOrderValue,
5402
5817
  setOrderValues,
5403
5818
  currentFocusInput: currentFocusInput.current,
5404
5819
  priceInputRef: props.priceInputRef,
@@ -5434,13 +5849,17 @@ var OrderEntry = (props) => {
5434
5849
  canTrade: props.canTrade,
5435
5850
  side,
5436
5851
  order_type: formattedOrder.order_type,
5437
- setOrderValue,
5852
+ setOrderValue: manualSetOrderValue,
5438
5853
  symbolLeverage: props.symbolLeverage,
5439
- marginMode: props.marginMode
5854
+ marginMode: props.marginMode,
5855
+ marketOrderDisabled: props.isSymbolPostOnly,
5856
+ marketOrderDisabledTooltip: t(
5857
+ "orderEntry.orderType.symbolPostOnly.tooltip"
5858
+ )
5440
5859
  }
5441
5860
  ),
5442
5861
  /* @__PURE__ */ jsx(
5443
- Available,
5862
+ OrderEntryAvailableInjectabled,
5444
5863
  {
5445
5864
  currentLtv,
5446
5865
  canTrade: props.canTrade,
@@ -5464,7 +5883,7 @@ var OrderEntry = (props) => {
5464
5883
  }
5465
5884
  ),
5466
5885
  /* @__PURE__ */ jsx(
5467
- QuantitySlider,
5886
+ OrderEntryQuantitySliderInjectabled,
5468
5887
  {
5469
5888
  canTrade: props.canTrade,
5470
5889
  side: props.side,
@@ -5473,38 +5892,29 @@ var OrderEntry = (props) => {
5473
5892
  }
5474
5893
  ),
5475
5894
  /* @__PURE__ */ jsx(
5476
- ThrottledButton,
5477
- {
5478
- fullWidth: true,
5479
- id: "order-entry-submit-button",
5480
- "data-type": OrderSide.BUY,
5481
- className: cn(
5482
- "oui-orderEntry-submit-btn",
5483
- side === OrderSide.BUY ? "orderly-order-entry-submit-button-buy oui-bg-success-darken hover:oui-bg-success-darken/80 active:oui-bg-success-darken/80" : "orderly-order-entry-submit-button-sell oui-bg-danger-darken hover:oui-bg-danger-darken/80 active:oui-bg-danger-darken/80"
5484
- ),
5485
- onClick: validateSubmit,
5486
- loading: props.isMutating,
5487
- disabled: !props.canTrade,
5488
- children: buttonLabel
5489
- }
5490
- ),
5491
- /* @__PURE__ */ jsx(
5492
- AssetInfo,
5895
+ OrderEntrySubmitSectionInjectabled,
5493
5896
  {
5897
+ buttonLabel,
5898
+ side,
5494
5899
  canTrade: props.canTrade,
5495
- quote: symbolInfo.quote,
5496
- estLiqPrice: props.estLiqPrice,
5497
- estLiqPriceDistance: props.estLiqPriceDistance,
5498
- estLeverage: props.estLeverage,
5499
- currentLeverage: props.currentLeverage,
5500
- slippage,
5501
- dp: symbolInfo.quote_dp,
5502
- setSlippage,
5503
- estSlippage: props.estSlippage,
5504
- orderType: formattedOrder.order_type,
5505
- disableFeatures,
5506
- symbol: props.symbol,
5507
- side
5900
+ isMutating: props.isMutating,
5901
+ onSubmit: validateSubmit,
5902
+ assetInfo: {
5903
+ canTrade: props.canTrade,
5904
+ quote: symbolInfo.quote,
5905
+ estLiqPrice: props.estLiqPrice,
5906
+ estLiqPriceDistance: props.estLiqPriceDistance,
5907
+ estLeverage: props.estLeverage,
5908
+ currentLeverage: props.currentLeverage,
5909
+ slippage,
5910
+ dp: symbolInfo.quote_dp,
5911
+ setSlippage,
5912
+ estSlippage: props.estSlippage,
5913
+ orderType: formattedOrder.order_type,
5914
+ disableFeatures,
5915
+ symbol: props.symbol,
5916
+ side
5917
+ }
5508
5918
  }
5509
5919
  ),
5510
5920
  /* @__PURE__ */ jsx(Divider, { className: "oui-w-full" }),
@@ -5529,10 +5939,10 @@ var OrderEntry = (props) => {
5529
5939
  onSwitchChanged: props.setTpslSwitch,
5530
5940
  orderType: formattedOrder.order_type,
5531
5941
  errors: validated || props.slPriceError !== void 0 ? { ...errors, ...props.slPriceError } : null,
5532
- setOrderValue,
5942
+ setOrderValue: manualSetOrderValue,
5533
5943
  reduceOnlyChecked: formattedOrder.reduce_only ?? false,
5534
5944
  onReduceOnlyChange: (checked) => {
5535
- setOrderValue("reduce_only", checked);
5945
+ manualSetOrderValue("reduce_only", checked);
5536
5946
  },
5537
5947
  values: {
5538
5948
  position_type: formattedOrder.position_type ?? PositionType.PARTIAL,
@@ -5541,6 +5951,8 @@ var OrderEntry = (props) => {
5541
5951
  PnL: formattedOrder.tp_pnl ?? "",
5542
5952
  Offset: formattedOrder.tp_offset ?? "",
5543
5953
  "Offset%": formattedOrder.tp_offset_percentage ?? "",
5954
+ OffsetFromMark: formattedOrder.tp_offset_from_mark ?? "",
5955
+ PercentageFromMark: formattedOrder.tp_offset_percentage_from_mark ?? "",
5544
5956
  ROI: formattedOrder.tp_ROI ?? ""
5545
5957
  },
5546
5958
  sl: {
@@ -5548,6 +5960,8 @@ var OrderEntry = (props) => {
5548
5960
  PnL: formattedOrder.sl_pnl ?? "",
5549
5961
  Offset: formattedOrder.sl_offset ?? "",
5550
5962
  "Offset%": formattedOrder.sl_offset_percentage ?? "",
5963
+ OffsetFromMark: formattedOrder.sl_offset_from_mark ?? "",
5964
+ PercentageFromMark: formattedOrder.sl_offset_percentage_from_mark ?? "",
5551
5965
  ROI: formattedOrder.sl_ROI ?? ""
5552
5966
  }
5553
5967
  },
@@ -5569,7 +5983,7 @@ var OrderEntry = (props) => {
5569
5983
  {
5570
5984
  checked: formattedOrder.reduce_only ?? false,
5571
5985
  onCheckedChange: (checked) => {
5572
- setOrderValue("reduce_only", checked);
5986
+ manualSetOrderValue("reduce_only", checked);
5573
5987
  }
5574
5988
  }
5575
5989
  ),
@@ -5658,7 +6072,7 @@ var OrderEntry = (props) => {
5658
6072
  children: showTPSLAdvanced && /* @__PURE__ */ jsx(
5659
6073
  TPSLAdvancedWidget,
5660
6074
  {
5661
- setOrderValue,
6075
+ setOrderValue: manualSetOrderValue,
5662
6076
  order: formattedOrder,
5663
6077
  onSubmit: onSubmitAdvancedTPSL,
5664
6078
  onClose: () => {
@@ -5834,11 +6248,14 @@ var useOrderEntryScript = (inputs) => {
5834
6248
  defaultSoundValue ?? null
5835
6249
  );
5836
6250
  const canTrade = useCanTrade();
5837
- const { marginMode } = useMarginModeBySymbol(symbol);
6251
+ const { state: accountState } = useAccount();
6252
+ const { marginMode, isPermissionlessListing } = useMarginModeBySymbol(symbol);
6253
+ const walletAddress = accountState?.address;
5838
6254
  const {
5839
6255
  formattedOrder,
5840
6256
  setValue,
5841
6257
  setValues: setOrderValues,
6258
+ setValuesRaw: setOrderValuesRaw,
5842
6259
  symbolInfo,
5843
6260
  symbolLeverage,
5844
6261
  ...state
@@ -5937,6 +6354,12 @@ var useOrderEntryScript = (inputs) => {
5937
6354
  );
5938
6355
  }
5939
6356
  );
6357
+ const manualSetOrderValue = useMemoizedFn(
6358
+ (key, value, options2) => {
6359
+ lastUserActiveTimeRef.current = Date.now();
6360
+ setOrderValue(key, value, options2);
6361
+ }
6362
+ );
5940
6363
  const onTPSLSwitchChanged = (state2) => {
5941
6364
  setTpslSwitch(state2);
5942
6365
  if (state2) {
@@ -6028,6 +6451,16 @@ var useOrderEntryScript = (inputs) => {
6028
6451
  setValue("distribution_type", DistributionType.FLAT);
6029
6452
  }
6030
6453
  }, [formattedOrder.order_type, formattedOrder.distribution_type]);
6454
+ const isSymbolPostOnly = symbolInfo?.status === "POST_ONLY";
6455
+ useEffect(() => {
6456
+ if (isSymbolPostOnly && (formattedOrder.order_type === OrderType.MARKET || formattedOrder.order_type === OrderType.STOP_MARKET)) {
6457
+ setLocalOrderType(OrderType.LIMIT);
6458
+ setOrderValues({
6459
+ order_type: OrderType.LIMIT,
6460
+ order_type_ext: void 0
6461
+ });
6462
+ }
6463
+ }, [isSymbolPostOnly, formattedOrder.order_type, setOrderValues]);
6031
6464
  const currentLtv = useComputedLTV();
6032
6465
  const askAndBid = useAskAndBid();
6033
6466
  const fillMiddleValue = () => {
@@ -6045,10 +6478,24 @@ var useOrderEntryScript = (inputs) => {
6045
6478
  const { priceInputContainerRef, priceInputContainerWidth } = usePriceInputContainer({
6046
6479
  order_type_ext: formattedOrder.order_type_ext
6047
6480
  });
6481
+ const effectiveEstLiqPriceForSlCheck = useMemo(() => {
6482
+ const estLiqPrice = state.estLiqPrice;
6483
+ if (estLiqPrice == null || formattedOrder.side == null || state.markPrice == null) {
6484
+ return null;
6485
+ }
6486
+ if (formattedOrder.side === OrderSide.BUY && estLiqPrice > state.markPrice || formattedOrder.side === OrderSide.SELL && estLiqPrice < state.markPrice) {
6487
+ return null;
6488
+ }
6489
+ if (!Number.isFinite(estLiqPrice) || estLiqPrice <= 0) {
6490
+ return null;
6491
+ }
6492
+ return estLiqPrice;
6493
+ }, [state.estLiqPrice, state.markPrice, formattedOrder.side]);
6048
6494
  const slPriceError = useTpslPriceChecker({
6049
6495
  slPrice: formattedOrder.sl_trigger_price,
6050
- liqPrice: state.estLiqPrice,
6496
+ liqPrice: effectiveEstLiqPriceForSlCheck,
6051
6497
  side: formattedOrder.side,
6498
+ markPrice: state.markPrice,
6052
6499
  currentPosition: state.currentPosition,
6053
6500
  orderQuantity: Number(formattedOrder.order_quantity)
6054
6501
  });
@@ -6063,22 +6510,16 @@ var useOrderEntryScript = (inputs) => {
6063
6510
  }
6064
6511
  }, [tpslSwitch]);
6065
6512
  useEffect(() => {
6066
- lastUserActiveTimeRef.current = Date.now();
6067
- }, [
6068
- formattedOrder.order_price,
6069
- formattedOrder.order_quantity,
6070
- formattedOrder.side
6071
- ]);
6072
- useEffect(() => {
6513
+ const estLiqPrice = effectiveEstLiqPriceForSlCheck;
6073
6514
  const lastActive = lastUserActiveTimeRef.current;
6074
6515
  const now = Date.now();
6075
6516
  const isUserActive = now - lastActive <= ORDER_ENTRY_EST_LIQ_ACTIVE_WINDOW_MS;
6076
6517
  ee.emit(ORDER_ENTRY_EST_LIQ_PRICE_CHANGE, {
6077
6518
  symbol,
6078
- estLiqPrice: state.estLiqPrice ?? null,
6519
+ estLiqPrice,
6079
6520
  isUserActive
6080
6521
  });
6081
- }, [ee, symbol, state.estLiqPrice]);
6522
+ }, [ee, symbol, effectiveEstLiqPriceForSlCheck]);
6082
6523
  useEffect(() => {
6083
6524
  setOrderValue("margin_mode", marginMode);
6084
6525
  }, [marginMode]);
@@ -6090,7 +6531,9 @@ var useOrderEntryScript = (inputs) => {
6090
6531
  level: formattedOrder.level,
6091
6532
  formattedOrder,
6092
6533
  setOrderValue,
6534
+ manualSetOrderValue,
6093
6535
  setOrderValues,
6536
+ setOrderValuesRaw,
6094
6537
  // account-level leverage (for other consumers)
6095
6538
  currentLeverage,
6096
6539
  // symbol-level leverage & margin mode for this order entry
@@ -6119,7 +6562,10 @@ var useOrderEntryScript = (inputs) => {
6119
6562
  symbol,
6120
6563
  soundAlert,
6121
6564
  setSoundAlert,
6122
- currentFocusInput
6565
+ currentFocusInput,
6566
+ walletAddress,
6567
+ isPermissionlessListing,
6568
+ isSymbolPostOnly
6123
6569
  };
6124
6570
  };
6125
6571
  var InjectableOrderEntry = injectable(
@@ -6138,6 +6584,6 @@ var OrderEntryWidget = (props) => {
6138
6584
  );
6139
6585
  };
6140
6586
 
6141
- export { AdditionalInfo, FeesWidget, LTVRiskTooltipWidget, OrderConfirmDialog, OrderEntry, OrderEntryWidget, useOrderEntryScript };
6587
+ export { AdditionalInfo, FeesWidget, LTVRiskTooltipWidget, OrderConfirmDialog, OrderEntry, OrderEntryWidget, SymbolBadge, useOrderEntryScript };
6142
6588
  //# sourceMappingURL=index.mjs.map
6143
6589
  //# sourceMappingURL=index.mjs.map