@orderly.network/ui-order-entry 3.0.0-beta.1 → 3.0.0-beta.3

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 },
@@ -1936,7 +2073,24 @@ var OrderTypeSelect = (props) => {
1936
2073
  children: /* @__PURE__ */ jsx(Text, { size: "xs", children: t("orderEntry.orderType.limit") })
1937
2074
  }
1938
2075
  ),
1939
- /* @__PURE__ */ jsx(
2076
+ marketOrderDisabled && marketOrderDisabledTooltip ? /* @__PURE__ */ jsx(
2077
+ Tooltip,
2078
+ {
2079
+ content: marketOrderDisabledTooltip,
2080
+ className: "oui-max-w-[275px]",
2081
+ children: /* @__PURE__ */ jsx("span", { className: "oui-inline-flex oui-flex-1", children: /* @__PURE__ */ jsx(
2082
+ "button",
2083
+ {
2084
+ type: "button",
2085
+ className: unselectedButtonClassName,
2086
+ "aria-pressed": false,
2087
+ disabled: true,
2088
+ "data-testid": "oui-testid-orderEntry-orderType-market",
2089
+ children: /* @__PURE__ */ jsx(Text, { size: "xs", children: t("orderEntry.orderType.market") })
2090
+ }
2091
+ ) })
2092
+ }
2093
+ ) : /* @__PURE__ */ jsx(
1940
2094
  "button",
1941
2095
  {
1942
2096
  type: "button",
@@ -1986,14 +2140,25 @@ var OrderTypeSelect = (props) => {
1986
2140
  }
1987
2141
  );
1988
2142
  }
2143
+ const mobileOptions = useMemo(() => allOptions, [allOptions]);
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",
@@ -2011,13 +2176,281 @@ var OrderTypeSelect = (props) => {
2011
2176
  if (!item) {
2012
2177
  return /* @__PURE__ */ jsx(Text, { size: "xs", children: option.placeholder });
2013
2178
  }
2014
- const label = displayLabelMap[value];
2015
- return /* @__PURE__ */ jsx(Text, { size: "xs", className: "oui-text-base-contrast-80", children: label });
2016
- },
2017
- size: "md"
2018
- }
2019
- );
2020
- };
2179
+ const label = displayLabelMap[value];
2180
+ return /* @__PURE__ */ jsx(Text, { size: "xs", className: "oui-text-base-contrast-80", children: label });
2181
+ },
2182
+ size: "md"
2183
+ }
2184
+ );
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,
@@ -4601,12 +4938,15 @@ var usePNLInputBuilder = (props) => {
4601
4938
  }
4602
4939
  if (value === "" || value === "-") return "";
4603
4940
  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}`;
4941
+ let normalized = value.replace(
4942
+ new RegExp(percentageSuffix.current.replace(".", "\\.") + "$"),
4943
+ ""
4944
+ ).replace(/,/g, "");
4945
+ normalized = normalized.replace(/\.$/, "");
4946
+ if (isNaN(Number(normalized)) || normalized === "" || normalized === "-") {
4947
+ return value;
4948
+ }
4949
+ return `${new Decimal(normalized).mul(100).todp(2, 4).toString()}${percentageSuffix.current}`;
4610
4950
  } else if (mode === "Offset" /* OFFSET */) {
4611
4951
  value = todpIfNeed(value, dp);
4612
4952
  } else ;
@@ -4625,6 +4965,9 @@ var usePNLInputBuilder = (props) => {
4625
4965
  } else {
4626
4966
  percentageSuffix.current = "";
4627
4967
  }
4968
+ if (isNaN(Number(value))) {
4969
+ return value;
4970
+ }
4628
4971
  value = new Decimal(value).div(100).toString();
4629
4972
  value = `${value}${percentageSuffix.current}`;
4630
4973
  }
@@ -4872,8 +5215,8 @@ var OrderTPSL = (props) => {
4872
5215
  {
4873
5216
  className: cn(
4874
5217
  "oui-orderEntry-tpsl-body",
4875
- "oui-max-h-0 oui-overflow-hidden oui-transition-all",
4876
- props.switchState && "oui-max-h-[120px]"
5218
+ "oui-overflow-hidden oui-transition-all",
5219
+ props.switchState ? "oui-max-h-[120px]" : "oui-max-h-0"
4877
5220
  ),
4878
5221
  onTransitionEnd: () => {
4879
5222
  tpslFormRef.current?.style.setProperty(
@@ -5158,7 +5501,9 @@ var OrderEntry = (props) => {
5158
5501
  side,
5159
5502
  formattedOrder,
5160
5503
  setOrderValue,
5504
+ manualSetOrderValue,
5161
5505
  setOrderValues,
5506
+ setOrderValuesRaw,
5162
5507
  symbolInfo,
5163
5508
  maxQty,
5164
5509
  freeCollateral,
@@ -5174,9 +5519,13 @@ var OrderEntry = (props) => {
5174
5519
  fillMiddleValue,
5175
5520
  soundAlert,
5176
5521
  setSoundAlert,
5177
- currentFocusInput
5522
+ currentFocusInput,
5523
+ walletAddress,
5524
+ isPermissionlessListing,
5525
+ symbol
5178
5526
  } = props;
5179
5527
  const [maxQtyConfirmOpen, setMaxQtyConfirmOpen] = useState(false);
5528
+ const [permissionlessAcknowledgedKeys, setPermissionlessAcknowledgedKeys] = useLocalStorage("orderly-permissionless-market-notice", []);
5180
5529
  const { t } = useTranslation();
5181
5530
  const { isMobile } = useScreen();
5182
5531
  const [hasAdvancedTPSLResult, setHasAdvancedTPSLResult] = useState(false);
@@ -5213,11 +5562,11 @@ var OrderEntry = (props) => {
5213
5562
  return;
5214
5563
  }
5215
5564
  if (slippage) {
5216
- setOrderValue("slippage", Number(slippage));
5565
+ manualSetOrderValue("slippage", Number(slippage));
5217
5566
  } else {
5218
- setOrderValue("slippage", void 0);
5567
+ manualSetOrderValue("slippage", void 0);
5219
5568
  }
5220
- }, [slippage, disableFeatures]);
5569
+ }, [slippage, disableFeatures, manualSetOrderValue]);
5221
5570
  useEffect(() => {
5222
5571
  const clickHandler = (event) => {
5223
5572
  const target = event.target;
@@ -5246,22 +5595,7 @@ var OrderEntry = (props) => {
5246
5595
  helper.validate(isSlPriceError ? props.slPriceError : void 0).then(
5247
5596
  // validate success, it return the order
5248
5597
  // 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
- },
5598
+ (order) => order,
5265
5599
  // should catch validate error first, then submit
5266
5600
  (errors2) => {
5267
5601
  if (errors2.slippage) {
@@ -5270,7 +5604,38 @@ var OrderEntry = (props) => {
5270
5604
  setErrorMsgVisible(true);
5271
5605
  return Promise.reject();
5272
5606
  }
5273
- ).then(() => {
5607
+ ).then((order) => {
5608
+ const shouldShowPermissionlessNotice = isPermissionlessListing && walletAddress && !(permissionlessAcknowledgedKeys ?? []).includes(
5609
+ `${walletAddress}_${symbol}`
5610
+ );
5611
+ if (shouldShowPermissionlessNotice) {
5612
+ return modal.show(
5613
+ isMobile ? permissionlessMarketNoticeDialogId : permissionlessMarketNoticeDesktopDialogId
5614
+ ).then(() => {
5615
+ setPermissionlessAcknowledgedKeys([
5616
+ ...Array.isArray(permissionlessAcknowledgedKeys) ? permissionlessAcknowledgedKeys : [],
5617
+ `${walletAddress}_${symbol}`
5618
+ ]);
5619
+ return order;
5620
+ });
5621
+ }
5622
+ return Promise.resolve(order);
5623
+ }).then((order) => {
5624
+ if (isScaledOrder) {
5625
+ return modal.show(scaledOrderConfirmDialogId, {
5626
+ order,
5627
+ symbolInfo,
5628
+ size: isMobile ? "sm" : "md"
5629
+ });
5630
+ }
5631
+ if (needConfirm) {
5632
+ return modal.show(orderConfirmDialogId, {
5633
+ order: formattedOrder,
5634
+ symbolInfo
5635
+ });
5636
+ }
5637
+ return true;
5638
+ }).then(() => {
5274
5639
  return submit({ resetOnSuccess: false }).then((result) => {
5275
5640
  if (!result.success && result.message) {
5276
5641
  toast.error(result.message);
@@ -5291,12 +5656,12 @@ var OrderEntry = (props) => {
5291
5656
  return new Decimal(maxQty).todp(symbolInfo.base_dp, Decimal.ROUND_DOWN).toString();
5292
5657
  }, [maxQty, symbolInfo.base_dp]);
5293
5658
  const onMaxQtyConfirm = useCallback(() => {
5294
- setOrderValue("order_quantity", formattedMaxQty);
5659
+ manualSetOrderValue("order_quantity", formattedMaxQty);
5295
5660
  requestAnimationFrame(() => {
5296
5661
  onSubmit();
5297
5662
  });
5298
5663
  setMaxQtyConfirmOpen(false);
5299
- }, [setOrderValue, formattedMaxQty]);
5664
+ }, [manualSetOrderValue, formattedMaxQty, onSubmit]);
5300
5665
  const validateSubmit = async () => {
5301
5666
  if (formattedOrder.reduce_only && maxQty === 0) {
5302
5667
  return modal.confirm({
@@ -5304,7 +5669,7 @@ var OrderEntry = (props) => {
5304
5669
  content: t("orderEntry.reduceOnly.reminder.content"),
5305
5670
  okLabel: t("orderEntry.placeOrderNow"),
5306
5671
  onOk: async () => {
5307
- setOrderValue("reduce_only", false);
5672
+ manualSetOrderValue("reduce_only", false);
5308
5673
  requestAnimationFrame(() => {
5309
5674
  props.resetMetaState();
5310
5675
  onSubmit();
@@ -5336,9 +5701,9 @@ var OrderEntry = (props) => {
5336
5701
  };
5337
5702
  const onSubmitAdvancedTPSL = (order) => {
5338
5703
  if (order.side !== formattedOrder.side) {
5339
- setOrderValue("side", order.side);
5704
+ manualSetOrderValue("side", order.side);
5340
5705
  }
5341
- setOrderValues({
5706
+ setOrderValuesRaw({
5342
5707
  position_type: order.position_type,
5343
5708
  tp_order_type: order.tp_order_type,
5344
5709
  tp_pnl: order.tp_pnl,
@@ -5384,7 +5749,7 @@ var OrderEntry = (props) => {
5384
5749
  setNeedConfirm,
5385
5750
  hidden,
5386
5751
  setHidden,
5387
- onValueChange: setOrderValue,
5752
+ onValueChange: manualSetOrderValue,
5388
5753
  orderTypeExtra: formattedOrder["order_type_ext"],
5389
5754
  showExtra: formattedOrder["order_type"] === OrderType.LIMIT && !props.tpslSwitch
5390
5755
  };
@@ -5399,6 +5764,7 @@ var OrderEntry = (props) => {
5399
5764
  onBlur: props.onBlur,
5400
5765
  getErrorMsg,
5401
5766
  setOrderValue,
5767
+ manualSetOrderValue,
5402
5768
  setOrderValues,
5403
5769
  currentFocusInput: currentFocusInput.current,
5404
5770
  priceInputRef: props.priceInputRef,
@@ -5434,13 +5800,17 @@ var OrderEntry = (props) => {
5434
5800
  canTrade: props.canTrade,
5435
5801
  side,
5436
5802
  order_type: formattedOrder.order_type,
5437
- setOrderValue,
5803
+ setOrderValue: manualSetOrderValue,
5438
5804
  symbolLeverage: props.symbolLeverage,
5439
- marginMode: props.marginMode
5805
+ marginMode: props.marginMode,
5806
+ marketOrderDisabled: props.isSymbolPostOnly,
5807
+ marketOrderDisabledTooltip: t(
5808
+ "orderEntry.orderType.symbolPostOnly.tooltip"
5809
+ )
5440
5810
  }
5441
5811
  ),
5442
5812
  /* @__PURE__ */ jsx(
5443
- Available,
5813
+ OrderEntryAvailableInjectabled,
5444
5814
  {
5445
5815
  currentLtv,
5446
5816
  canTrade: props.canTrade,
@@ -5464,7 +5834,7 @@ var OrderEntry = (props) => {
5464
5834
  }
5465
5835
  ),
5466
5836
  /* @__PURE__ */ jsx(
5467
- QuantitySlider,
5837
+ OrderEntryQuantitySliderInjectabled,
5468
5838
  {
5469
5839
  canTrade: props.canTrade,
5470
5840
  side: props.side,
@@ -5473,38 +5843,29 @@ var OrderEntry = (props) => {
5473
5843
  }
5474
5844
  ),
5475
5845
  /* @__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,
5846
+ OrderEntrySubmitSectionInjectabled,
5493
5847
  {
5848
+ buttonLabel,
5849
+ side,
5494
5850
  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
5851
+ isMutating: props.isMutating,
5852
+ onSubmit: validateSubmit,
5853
+ assetInfo: {
5854
+ canTrade: props.canTrade,
5855
+ quote: symbolInfo.quote,
5856
+ estLiqPrice: props.estLiqPrice,
5857
+ estLiqPriceDistance: props.estLiqPriceDistance,
5858
+ estLeverage: props.estLeverage,
5859
+ currentLeverage: props.currentLeverage,
5860
+ slippage,
5861
+ dp: symbolInfo.quote_dp,
5862
+ setSlippage,
5863
+ estSlippage: props.estSlippage,
5864
+ orderType: formattedOrder.order_type,
5865
+ disableFeatures,
5866
+ symbol: props.symbol,
5867
+ side
5868
+ }
5508
5869
  }
5509
5870
  ),
5510
5871
  /* @__PURE__ */ jsx(Divider, { className: "oui-w-full" }),
@@ -5529,10 +5890,10 @@ var OrderEntry = (props) => {
5529
5890
  onSwitchChanged: props.setTpslSwitch,
5530
5891
  orderType: formattedOrder.order_type,
5531
5892
  errors: validated || props.slPriceError !== void 0 ? { ...errors, ...props.slPriceError } : null,
5532
- setOrderValue,
5893
+ setOrderValue: manualSetOrderValue,
5533
5894
  reduceOnlyChecked: formattedOrder.reduce_only ?? false,
5534
5895
  onReduceOnlyChange: (checked) => {
5535
- setOrderValue("reduce_only", checked);
5896
+ manualSetOrderValue("reduce_only", checked);
5536
5897
  },
5537
5898
  values: {
5538
5899
  position_type: formattedOrder.position_type ?? PositionType.PARTIAL,
@@ -5569,7 +5930,7 @@ var OrderEntry = (props) => {
5569
5930
  {
5570
5931
  checked: formattedOrder.reduce_only ?? false,
5571
5932
  onCheckedChange: (checked) => {
5572
- setOrderValue("reduce_only", checked);
5933
+ manualSetOrderValue("reduce_only", checked);
5573
5934
  }
5574
5935
  }
5575
5936
  ),
@@ -5658,7 +6019,7 @@ var OrderEntry = (props) => {
5658
6019
  children: showTPSLAdvanced && /* @__PURE__ */ jsx(
5659
6020
  TPSLAdvancedWidget,
5660
6021
  {
5661
- setOrderValue,
6022
+ setOrderValue: manualSetOrderValue,
5662
6023
  order: formattedOrder,
5663
6024
  onSubmit: onSubmitAdvancedTPSL,
5664
6025
  onClose: () => {
@@ -5834,11 +6195,14 @@ var useOrderEntryScript = (inputs) => {
5834
6195
  defaultSoundValue ?? null
5835
6196
  );
5836
6197
  const canTrade = useCanTrade();
5837
- const { marginMode } = useMarginModeBySymbol(symbol);
6198
+ const { state: accountState } = useAccount();
6199
+ const { marginMode, isPermissionlessListing } = useMarginModeBySymbol(symbol);
6200
+ const walletAddress = accountState?.address;
5838
6201
  const {
5839
6202
  formattedOrder,
5840
6203
  setValue,
5841
6204
  setValues: setOrderValues,
6205
+ setValuesRaw: setOrderValuesRaw,
5842
6206
  symbolInfo,
5843
6207
  symbolLeverage,
5844
6208
  ...state
@@ -5937,6 +6301,12 @@ var useOrderEntryScript = (inputs) => {
5937
6301
  );
5938
6302
  }
5939
6303
  );
6304
+ const manualSetOrderValue = useMemoizedFn(
6305
+ (key, value, options2) => {
6306
+ lastUserActiveTimeRef.current = Date.now();
6307
+ setOrderValue(key, value, options2);
6308
+ }
6309
+ );
5940
6310
  const onTPSLSwitchChanged = (state2) => {
5941
6311
  setTpslSwitch(state2);
5942
6312
  if (state2) {
@@ -6028,6 +6398,16 @@ var useOrderEntryScript = (inputs) => {
6028
6398
  setValue("distribution_type", DistributionType.FLAT);
6029
6399
  }
6030
6400
  }, [formattedOrder.order_type, formattedOrder.distribution_type]);
6401
+ const isSymbolPostOnly = symbolInfo?.status === "POST_ONLY";
6402
+ useEffect(() => {
6403
+ if (isSymbolPostOnly && (formattedOrder.order_type === OrderType.MARKET || formattedOrder.order_type === OrderType.STOP_MARKET)) {
6404
+ setLocalOrderType(OrderType.LIMIT);
6405
+ setOrderValues({
6406
+ order_type: OrderType.LIMIT,
6407
+ order_type_ext: void 0
6408
+ });
6409
+ }
6410
+ }, [isSymbolPostOnly, formattedOrder.order_type, setOrderValues]);
6031
6411
  const currentLtv = useComputedLTV();
6032
6412
  const askAndBid = useAskAndBid();
6033
6413
  const fillMiddleValue = () => {
@@ -6063,22 +6443,21 @@ var useOrderEntryScript = (inputs) => {
6063
6443
  }
6064
6444
  }, [tpslSwitch]);
6065
6445
  useEffect(() => {
6066
- lastUserActiveTimeRef.current = Date.now();
6067
- }, [
6068
- formattedOrder.order_price,
6069
- formattedOrder.order_quantity,
6070
- formattedOrder.side
6071
- ]);
6072
- useEffect(() => {
6446
+ let estLiqPrice = state.estLiqPrice;
6447
+ if (estLiqPrice == null || formattedOrder.side == null || state.markPrice == null) {
6448
+ estLiqPrice = null;
6449
+ } else if (formattedOrder.side === OrderSide.BUY && estLiqPrice > state.markPrice || formattedOrder.side === OrderSide.SELL && estLiqPrice < state.markPrice) {
6450
+ estLiqPrice = null;
6451
+ }
6073
6452
  const lastActive = lastUserActiveTimeRef.current;
6074
6453
  const now = Date.now();
6075
6454
  const isUserActive = now - lastActive <= ORDER_ENTRY_EST_LIQ_ACTIVE_WINDOW_MS;
6076
6455
  ee.emit(ORDER_ENTRY_EST_LIQ_PRICE_CHANGE, {
6077
6456
  symbol,
6078
- estLiqPrice: state.estLiqPrice ?? null,
6457
+ estLiqPrice,
6079
6458
  isUserActive
6080
6459
  });
6081
- }, [ee, symbol, state.estLiqPrice]);
6460
+ }, [ee, symbol, state.estLiqPrice, state.markPrice, formattedOrder.side]);
6082
6461
  useEffect(() => {
6083
6462
  setOrderValue("margin_mode", marginMode);
6084
6463
  }, [marginMode]);
@@ -6090,7 +6469,9 @@ var useOrderEntryScript = (inputs) => {
6090
6469
  level: formattedOrder.level,
6091
6470
  formattedOrder,
6092
6471
  setOrderValue,
6472
+ manualSetOrderValue,
6093
6473
  setOrderValues,
6474
+ setOrderValuesRaw,
6094
6475
  // account-level leverage (for other consumers)
6095
6476
  currentLeverage,
6096
6477
  // symbol-level leverage & margin mode for this order entry
@@ -6119,7 +6500,10 @@ var useOrderEntryScript = (inputs) => {
6119
6500
  symbol,
6120
6501
  soundAlert,
6121
6502
  setSoundAlert,
6122
- currentFocusInput
6503
+ currentFocusInput,
6504
+ walletAddress,
6505
+ isPermissionlessListing,
6506
+ isSymbolPostOnly
6123
6507
  };
6124
6508
  };
6125
6509
  var InjectableOrderEntry = injectable(
@@ -6138,6 +6522,6 @@ var OrderEntryWidget = (props) => {
6138
6522
  );
6139
6523
  };
6140
6524
 
6141
- export { AdditionalInfo, FeesWidget, LTVRiskTooltipWidget, OrderConfirmDialog, OrderEntry, OrderEntryWidget, useOrderEntryScript };
6525
+ export { AdditionalInfo, FeesWidget, LTVRiskTooltipWidget, OrderConfirmDialog, OrderEntry, OrderEntryWidget, SymbolBadge, useOrderEntryScript };
6142
6526
  //# sourceMappingURL=index.mjs.map
6143
6527
  //# sourceMappingURL=index.mjs.map