UNPKG

@orderly.network/trading

Version:

1,388 lines (1,380 loc) 327 kB
import { useBadgeBySymbol, useGetRwaSymbolOpenStatus, useLocalStorage, useGetRwaSymbolCloseTimeInterval, usePositionStream, useOrderStream, useAccount, useFundingDetails, useFundingRateBySymbol, useFundingRate, useSymbolsInfo, useOrderbookStream, useEventEmitter, useCollateral, useMarginRatio, useLeverage, useDebouncedCallback, useMediaQuery, useAssetsHistory, useGetRwaSymbolInfo, useWalletConnector, useConfig, useMutation, useChains, useReferralInfo, useCurEpochEstimate, TWType, useEpochInfo, useMarketTradeStream, useAccountInstance, useComputedLTV, useTickerStream } from '@orderly.network/hooks'; import React12, { forwardRef, useMemo, createContext, useEffect, useState, useRef, useCallback, useContext, createElement } from 'react'; import { useDataTap, useAppContext } from '@orderly.network/react-app'; import { TradingviewFullscreenKey, OrderEntrySortKeys, AlgoOrderRootType, OrderStatus, OrderSide, AccountStatusEnum, AssetHistoryStatusEnum, AssetHistorySideEnum, ChainNamespace, EMPTY_LIST } from '@orderly.network/types'; import { i18n, useTranslation, Trans } from '@orderly.network/i18n'; import { injectable, cn, Button, formatAddress, registerSimpleDialog, registerSimpleSheet, Box, Flex, Text, toast as toast$1, useScreen, ExclamationFillIcon, CloseIcon, TooltipRoot, TooltipTrigger, TooltipContent as TooltipContent$1, TooltipArrow, parseNumber, Divider, ListView, Grid, ArrowDownShortIcon, gradientTextVariants, EyeIcon, EyeCloseIcon, ChevronDownIcon, modal, Tooltip, Tabs, TabPanel, DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuPortal, DropdownMenuContent, Statistic, RefreshIcon, ArrowLeftRightIcon, ArrowUpShortIcon, InfoCircleIcon, NewsFillIcon, SimpleSheet, SimpleDialog, ChainIcon, useModal, ArrowRightShortIcon, Switch, Checkbox, Sheet, SheetTrigger, SheetContent, SettingFillIcon, Spinner, PopoverRoot, PopoverTrigger, PopoverContent, Select, Popover, CaretUpIcon, CaretDownIcon, Picker } from '@orderly.network/ui'; import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import { PositionHistoryWidget, LiquidationWidget, PositionsWidget, CloseAllPositionsWidget, MobileLiquidationWidget, MobilePositionsWidget, MobilePositionHistoryWidget, useReversePositionEnabled } from '@orderly.network/ui-positions'; import { Decimal, getPrecisionByNumber, commifyOptional, removeTrailingZeros, isTestnet, formatSymbol, optimizeSymbolDisplay } from '@orderly.network/utils'; import { AssetsModule } from '@orderly.network/portfolio'; import { DesktopOrderListWidget, TabType, MobileOrderListWidget } from '@orderly.network/ui-orders'; import { AuthGuard } from '@orderly.network/ui-connector'; import { OrderEntryWidget, LTVRiskTooltipWidget } from '@orderly.network/ui-order-entry'; import { DepositStatusWidget, DepositAndWithdrawWithSheetId, TransferSheetId, DepositAndWithdrawWithDialogId, TransferDialogId } from '@orderly.network/ui-transfer'; import { TradingviewWidget } from '@orderly.network/ui-tradingview'; import Split from '@uiw/react-split'; import { ScanQRCodeWidget } from '@orderly.network/ui-scaffold'; import { ChainSelectorSheetId } from '@orderly.network/ui-chain-selector'; import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter, DragOverlay } from '@dnd-kit/core'; import { restrictToVerticalAxis } from '@dnd-kit/modifiers'; import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, useSortable, arrayMove } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { HorizontalMarketsWidget, SideMarketsWidget, SymbolInfoBarFullWidget, SymbolInfoBarWidget, SymbolInfoBarRiskNotice, MarketsSheetWidget } from '@orderly.network/markets'; var __defProp = Object.defineProperty; var __getOwnPropNames = Object.getOwnPropertyNames; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var useTradingLocalStorage; var init_useTradingLocalStorage = __esm({ "src/hooks/useTradingLocalStorage.ts"() { useTradingLocalStorage = (props) => { const [unPnlPriceBasis, setUnPnlPriceBasic] = useLocalStorage( "unPnlPriceBasis", "markPrice" ); const [pnlNotionalDecimalPrecision, setPnlNotionalDecimalPrecision] = useLocalStorage( "pnlNotionalDecimalPrecision", props?.pnlNotionalDecimalPrecision ?? 2 ); const [showAllSymbol, setShowAllSymbol] = useLocalStorage( "showAllSymbol", true ); const [hideAssets, setHideAssets] = useLocalStorage("hideAssets", false); return { unPnlPriceBasis, setUnPnlPriceBasic, pnlNotionalDecimalPrecision, setPnlNotionalDecimalPrecision, showAllSymbol, setShowAllSymbol, hideAssets, setHideAssets }; }; } }); var usePositionsCount; var init_usePositionsCount = __esm({ "src/hooks/usePositionsCount.ts"() { init_useTradingLocalStorage(); usePositionsCount = (symbol) => { const { showAllSymbol } = useTradingLocalStorage(); const [data] = usePositionStream(showAllSymbol ? void 0 : symbol); const count = useMemo(() => { return data.rows?.length; }, [data.rows?.length]); const positionCount = useDataTap(count) ?? 0; return { positionCount }; }; } }); var usePendingOrderCount; var init_usePendingOrderCount = __esm({ "src/hooks/usePendingOrderCount.ts"() { init_useTradingLocalStorage(); usePendingOrderCount = (symbol) => { const { showAllSymbol } = useTradingLocalStorage(); const [pendingOrders] = useOrderStream( { symbol: showAllSymbol ? void 0 : symbol, status: OrderStatus.INCOMPLETE, excludes: [AlgoOrderRootType.POSITIONAL_TP_SL, AlgoOrderRootType.TP_SL], // size: pendingOrderPageSize, size: 500 // sourceTypeAll: true, }, { keeplive: true } ); const [tpslOrders] = useOrderStream( { symbol: showAllSymbol ? void 0 : symbol, status: OrderStatus.INCOMPLETE, includes: [AlgoOrderRootType.POSITIONAL_TP_SL, AlgoOrderRootType.TP_SL], // size: tpslOrderPageSize, size: 500 // sourceTypeAll: true, }, { keeplive: true } ); const pendingCount = useMemo(() => { if (showAllSymbol) { return pendingOrders?.length ?? 0; } return pendingOrders?.filter((item) => item.symbol === symbol)?.length ?? 0; }, [pendingOrders, showAllSymbol, symbol]); const tpslCount = useMemo(() => { if (showAllSymbol) { return tpslOrders?.length ?? 0; } return tpslOrders?.filter((item) => item.symbol === symbol)?.length ?? 0; }, [tpslOrders, showAllSymbol, symbol]); const pendingOrderCount = useDataTap(pendingCount) ?? 0; const tpSlOrderCount = useDataTap(tpslCount) ?? 0; return { pendingOrderCount, tpSlOrderCount }; }; } }); // src/hooks/index.ts var init_hooks = __esm({ "src/hooks/index.ts"() { init_useTradingLocalStorage(); init_usePositionsCount(); init_usePendingOrderCount(); } }); var TradingPageContext, useTradingPageContext; var init_tradingPageContext = __esm({ "src/provider/tradingPageContext.tsx"() { TradingPageContext = createContext({}); useTradingPageContext = () => { return useContext(TradingPageContext); }; } }); // src/components/desktop/dataList/dataList.script.tsx var useDataListScript; var init_dataList_script = __esm({ "src/components/desktop/dataList/dataList.script.tsx"() { init_hooks(); init_tradingPageContext(); useDataListScript = (inputs) => { const { current, pnlNotionalDecimalPrecision, sharePnLConfig, symbol, includedPendingOrder } = inputs; const localStorage2 = useTradingLocalStorage({ pnlNotionalDecimalPrecision }); const { onSymbolChange } = useTradingPageContext(); const { positionCount } = usePositionsCount(symbol); const { pendingOrderCount, tpSlOrderCount } = usePendingOrderCount(symbol); return { current, sharePnLConfig, symbol, calcMode: localStorage2.unPnlPriceBasis, includedPendingOrder, ...localStorage2, positionCount, pendingOrderCount, tpSlOrderCount, onSymbolChange }; }; } }); var Setting, UnPnlPriceBasisCheckBox, DecimalPrecisionCheckbox, RadioButton, SelIcon, UnselIcon; var init_setting_ui = __esm({ "src/components/desktop/dataList/setting/setting.ui.tsx"() { Setting = (props) => { const [open, setOpen] = useState(false); const { t } = useTranslation(); const { isMobile } = useScreen(); const SettingsContent = useMemo(() => { return () => /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-flex-col oui-text-sm", children: [ /* @__PURE__ */ jsx( Flex, { itemAlign: "center", justify: isMobile ? "center" : "start", className: "oui-w-full", children: /* @__PURE__ */ jsx(Text, { className: "oui-text-base oui-pb-3", children: t("trading.portfolioSettings") }) } ), /* @__PURE__ */ jsx(Divider, {}), /* @__PURE__ */ jsx(Text, { className: "oui-pb-3 oui-text-base-contrast-54 oui-mt-2", children: t("trading.portfolioSettings.decimalPrecision") }), /* @__PURE__ */ jsx( DecimalPrecisionCheckbox, { value: props.pnlNotionalDecimalPrecision, onValueChange: (e) => { props.setPnlNotionalDecimalPrecision(e); setOpen(false); } } ), /* @__PURE__ */ jsx(Divider, { className: "oui-my-3" }), /* @__PURE__ */ jsx(Text, { className: "oui-pb-3 oui-text-base-contrast-54 oui-mt-2", children: t("trading.portfolioSettings.unrealPnlPriceBasis") }), /* @__PURE__ */ jsx( UnPnlPriceBasisCheckBox, { value: props.unPnlPriceBasis, onValueChange: (e) => { props.setUnPnlPriceBasic(e); setOpen(false); } } ) ] }), /* @__PURE__ */ jsx(Divider, { className: "oui-my-3" }), /* @__PURE__ */ jsxs(Flex, { itemAlign: "center", gap: 1, justify: "between", children: [ /* @__PURE__ */ jsxs(Flex, { gap: 1, itemAlign: "center", children: [ /* @__PURE__ */ jsx(Text, { size: "sm", intensity: 54, children: t("trading.portfolioSettings.reversePosition") }), isMobile ? /* @__PURE__ */ jsx( ExclamationFillIcon, { size: 14, className: "oui-text-base-contrast-54 hover:oui-text-base-contrast-80 oui-cursor-pointer", onClick: () => { modal.alert({ title: t("common.tips"), message: t( "trading.portfolioSettings.reversePosition.tooltip" ) }); } } ) : /* @__PURE__ */ jsx( Tooltip, { content: t("trading.portfolioSettings.reversePosition.tooltip"), className: "oui-max-w-[300px]", children: /* @__PURE__ */ jsx( ExclamationFillIcon, { size: 14, className: "oui-text-base-contrast-54 hover:oui-text-base-contrast-80 oui-cursor-pointer" } ) } ) ] }), /* @__PURE__ */ jsx( Switch, { checked: props.reversePosition, onCheckedChange: (checked) => { props.setReversePosition(checked); } } ) ] }) ] }); }, [ t, isMobile, props.pnlNotionalDecimalPrecision, props.unPnlPriceBasis, props.reversePosition ]); const triggerButton = /* @__PURE__ */ jsx( Button, { size: "xs", type: "button", variant: "contained", className: "oui-preference-trigger-btn oui-bg-transparent hover:oui-bg-transparent", children: /* @__PURE__ */ jsx( SettingFillIcon, { size: 16, color: "white", opacity: 1, className: "oui-text-base-contrast-36 hover:oui-text-base-contrast-80" } ) } ); return /* @__PURE__ */ jsxs(Flex, { className: "oui-preference", gap: 0, children: [ /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [ /* @__PURE__ */ jsx( Checkbox, { id: "oui-checkbox-hideOtherSymbols", className: "oui-checkbox-hideOtherSymbols", color: "white", checked: props.hideOtherSymbols, onCheckedChange: (checked) => { props.setHideOtherSymbols(checked); } } ), /* @__PURE__ */ jsx( "label", { className: "oui-text-xs oui-text-base-contrast-54 oui-cursor-pointer", htmlFor: "oui-checkbox-hideOtherSymbols", children: t("trading.hideOtherSymbols") } ) ] }), isMobile ? /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [ /* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: triggerButton }), /* @__PURE__ */ jsx(SheetContent, { side: "bottom", className: "oui-px-5 oui-pt-3", children: /* @__PURE__ */ jsx( "div", { style: { paddingBottom: `max(32px, calc(12px + env(safe-area-inset-bottom)))` }, children: /* @__PURE__ */ jsx(SettingsContent, {}) } ) }) ] }) : /* @__PURE__ */ jsxs(DropdownMenuRoot, { open, onOpenChange: setOpen, children: [ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: triggerButton }), /* @__PURE__ */ jsx( DropdownMenuContent, { className: "oui-px-5 oui-py-3 oui-w-[360px]", alignOffset: 2, align: "end", children: /* @__PURE__ */ jsx(SettingsContent, {}) } ) ] }) ] }); }; UnPnlPriceBasisCheckBox = (props) => { const { value, onValueChange } = props; const { t } = useTranslation(); return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [ /* @__PURE__ */ jsx( RadioButton, { sel: value === "markPrice", label: t("common.markPrice"), value: "markPrice", onCheckChange: onValueChange } ), /* @__PURE__ */ jsx( RadioButton, { sel: value === "lastPrice", label: t("common.lastPrice"), value: "lastPrice", onCheckChange: onValueChange } ) ] }); }; DecimalPrecisionCheckbox = (props) => { const { value, onValueChange } = props; return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [ /* @__PURE__ */ jsx( RadioButton, { sel: value === 0, label: 1, value: 0, onCheckChange: onValueChange } ), /* @__PURE__ */ jsx( RadioButton, { sel: value === 1, label: 0.1, value: 1, onCheckChange: onValueChange } ), /* @__PURE__ */ jsx( RadioButton, { sel: value === 2, label: 0.01, value: 2, onCheckChange: onValueChange } ) ] }); }; RadioButton = (props) => { const { sel, label, value, onCheckChange } = props; return /* @__PURE__ */ jsxs( Flex, { onClick: (e) => { onCheckChange(value); e.stopPropagation(); }, gap: 1, className: "oui-cursor-pointer", children: [ sel ? /* @__PURE__ */ jsx(SelIcon, { className: "oui-fill-base-contrast" }) : /* @__PURE__ */ jsx(UnselIcon, { className: "oui-fill-base-contrast-54" }), /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: sel ? 98 : 54, children: label }) ] } ); }; SelIcon = (props) => { return /* @__PURE__ */ jsxs( "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", xmlns: "http://www.w3.org/2000/svg", className: props.className, children: [ /* @__PURE__ */ jsx("path", { d: "M8.01 1.333a6.667 6.667 0 1 0 0 13.333 6.667 6.667 0 0 0 0-13.333m0 1.333a5.334 5.334 0 1 1-.001 10.667 5.334 5.334 0 0 1 0-10.667" }), /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "3.333" }) ] } ); }; UnselIcon = (props) => { return /* @__PURE__ */ jsx( "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", xmlns: "http://www.w3.org/2000/svg", className: props.className, children: /* @__PURE__ */ jsx("path", { d: "M8.01 1.333a6.667 6.667 0 1 0 0 13.333 6.667 6.667 0 0 0 0-13.333m0 1.333a5.334 5.334 0 1 1-.001 10.667 5.334 5.334 0 0 1 0-10.667" }) } ); }; } }); var useSettingScript; var init_setting_script = __esm({ "src/components/desktop/dataList/setting/setting.script.tsx"() { useSettingScript = (props) => { const { isEnabled, setEnabled } = useReversePositionEnabled(); return { ...props, reversePosition: isEnabled, setReversePosition: setEnabled }; }; } }); var SettingWidget; var init_setting_widget = __esm({ "src/components/desktop/dataList/setting/setting.widget.tsx"() { init_setting_script(); init_setting_ui(); SettingWidget = (props) => { const state = useSettingScript(props); return /* @__PURE__ */ jsx(Setting, { ...state }); }; } }); // src/components/desktop/dataList/setting/index.ts var setting_exports = {}; __export(setting_exports, { Setting: () => Setting, SettingWidget: () => SettingWidget }); var init_setting = __esm({ "src/components/desktop/dataList/setting/index.ts"() { init_setting_ui(); init_setting_widget(); } }); var PositionHeader, MobileLayout, DesktopLayout, UnrealPnL, Notional; var init_positionHeader_ui = __esm({ "src/components/base/positionHeader/positionHeader.ui.tsx"() { init_setting(); PositionHeader = (props) => { const { isMobile } = useScreen(); return isMobile ? /* @__PURE__ */ jsx(MobileLayout, { ...props }) : /* @__PURE__ */ jsx(DesktopLayout, { ...props }); }; MobileLayout = (props) => { const { t } = useTranslation(); return /* @__PURE__ */ jsxs( Flex, { className: "oui-positionHeader oui-rounded-b-xl oui-bg-base-9", direction: "column", gap: 2, width: "100%", itemAlign: "start", p: 2, children: [ /* @__PURE__ */ jsxs(Flex, { width: "100%", justify: "between", gap: 2, children: [ /* @__PURE__ */ jsx( UnrealPnL, { classNames: { label: "oui-text-2xs oui-text-base-contrast-54", root: "oui-text-sm" }, ...props } ), /* @__PURE__ */ jsx( Notional, { classNames: { label: "oui-text-2xs oui-text-base-contrast-54", root: "oui-text-sm" }, ...props } ) ] }), /* @__PURE__ */ jsx(Divider, { className: "oui-w-full" }), /* @__PURE__ */ jsxs( Flex, { className: "oui-cursor-pointer oui-gap-[2px]", justify: "between", width: "100%", children: [ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx( SettingWidget, { pnlNotionalDecimalPrecision: props.pnlNotionalDecimalPrecision, setPnlNotionalDecimalPrecision: props.setPnlNotionalDecimalPrecision, unPnlPriceBasis: props.unPnlPriceBasis, setUnPnlPriceBasic: props.setUnPnlPriceBasic, hideOtherSymbols: !props.showAllSymbol, setHideOtherSymbols: (value) => { props.setShowAllSymbol(!value); } } ) }), /* @__PURE__ */ jsx(CloseAllPositionsWidget, { symbol: props.symbol }) ] } ) ] } ); }; DesktopLayout = (props) => { return /* @__PURE__ */ jsxs( Flex, { className: "oui-positionHeader", py: 2, px: 3, gap: 6, width: "100%", justify: "between", children: [ /* @__PURE__ */ jsxs(Flex, { gap: 5, children: [ /* @__PURE__ */ jsx( UnrealPnL, { ...props, classNames: { label: "oui-text-base-contrast-54" } } ), /* @__PURE__ */ jsx( Notional, { ...props, classNames: { label: "oui-text-base-contrast-54" } } ) ] }), /* @__PURE__ */ jsx(CloseAllPositionsWidget, { symbol: props.symbol }) ] } ); }; UnrealPnL = (props) => { const { t } = useTranslation(); const unrealPnLClsName = typeof props.unrealPnL === "number" ? props.unrealPnL >= 0 ? "oui-text-trade-profit" : "oui-text-trade-loss" : "oui-text-base-contrast-80"; const unrealPnLROIClsName = typeof props.unrealPnL === "number" && props.unrealPnlROI ? props.unrealPnlROI >= 0 ? "oui-text-success-darken" : "oui-text-danger-darken" : "oui-text-base-contrast-80"; return /* @__PURE__ */ jsx(Statistic, { label: t("common.unrealizedPnl"), classNames: props.classNames, children: /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [ /* @__PURE__ */ jsx( Text.pnl, { dp: props.pnlNotionalDecimalPrecision, intensity: 80, className: unrealPnLClsName, children: props.unrealPnL ?? "--" } ), typeof props.unrealPnlROI !== "undefined" && /* @__PURE__ */ jsx( Text.roi, { prefix: "(", suffix: ")", rule: "percentages", size: "2xs", dp: props.pnlNotionalDecimalPrecision, className: unrealPnLROIClsName, children: props.unrealPnlROI } ) ] }) }); }; Notional = (props) => { const { t } = useTranslation(); return /* @__PURE__ */ jsx(Statistic, { label: t("common.notional"), classNames: props.classNames, children: /* @__PURE__ */ jsx( Text.numeral, { dp: props.pnlNotionalDecimalPrecision, rm: Decimal.ROUND_DOWN, intensity: 80, children: props.notional ?? "--" } ) }); }; } }); var usePositionHeaderScript; var init_positionHeader_script = __esm({ "src/components/base/positionHeader/positionHeader.script.tsx"() { init_hooks(); usePositionHeaderScript = (inputs) => { const { pnlNotionalDecimalPrecision, setPnlNotionalDecimalPrecision, unPnlPriceBasis, setUnPnlPriceBasic, symbol } = inputs; const calcMode = unPnlPriceBasis; const [data] = usePositionStream(symbol, { calcMode }); const aggregated = useDataTap(data.aggregated); const unrealPnL = aggregated?.total_unreal_pnl; const unrealPnlROI = aggregated?.unrealPnlROI; const notional = aggregated?.notional; const { showAllSymbol, setShowAllSymbol } = useTradingLocalStorage(); return { pnlNotionalDecimalPrecision, unrealPnL, unrealPnlROI, notional, showAllSymbol, setShowAllSymbol, symbol, setPnlNotionalDecimalPrecision, unPnlPriceBasis, setUnPnlPriceBasic }; }; } }); var PositionHeaderWidget; var init_positionHeader_widget = __esm({ "src/components/base/positionHeader/positionHeader.widget.tsx"() { init_positionHeader_script(); init_positionHeader_ui(); PositionHeaderWidget = (props) => { const state = usePositionHeaderScript(props); return /* @__PURE__ */ jsx(PositionHeader, { ...state }); }; } }); // src/components/base/positionHeader/index.ts var positionHeader_exports = {}; __export(positionHeader_exports, { PositionHeader: () => PositionHeader, PositionHeaderWidget: () => PositionHeaderWidget }); var init_positionHeader = __esm({ "src/components/base/positionHeader/index.ts"() { init_positionHeader_ui(); init_positionHeader_widget(); } }); var LazySettingWidget, LazyPositionHeaderWidget, PositionsView, LiquidationTab, DataList; var init_dataList_ui = __esm({ "src/components/desktop/dataList/dataList.ui.tsx"() { init_dataList_script(); LazySettingWidget = React12.lazy( () => Promise.resolve().then(() => (init_setting(), setting_exports)).then((mod) => { return { default: mod.SettingWidget }; }) ); LazyPositionHeaderWidget = React12.lazy( () => Promise.resolve().then(() => (init_positionHeader(), positionHeader_exports)).then((mod) => { return { default: mod.PositionHeaderWidget }; }) ); PositionsView = (props) => { return /* @__PURE__ */ jsxs(Flex, { direction: "column", width: "100%", height: "100%", children: [ /* @__PURE__ */ jsx(React12.Suspense, { fallback: null, children: /* @__PURE__ */ jsx( LazyPositionHeaderWidget, { setPnlNotionalDecimalPrecision: props.setPnlNotionalDecimalPrecision, pnlNotionalDecimalPrecision: props.pnlNotionalDecimalPrecision, symbol: !!props.showAllSymbol ? void 0 : props.symbol, setUnPnlPriceBasic: props.setUnPnlPriceBasic, unPnlPriceBasis: props.unPnlPriceBasis } ) }), /* @__PURE__ */ jsx(Divider, { className: "oui-w-full" }), /* @__PURE__ */ jsx(Box, { className: "oui-h-[calc(100%_-_60px)]", width: "100%", children: /* @__PURE__ */ jsx( PositionsWidget, { symbol: !!props.showAllSymbol ? void 0 : props.symbol, pnlNotionalDecimalPrecision: props.pnlNotionalDecimalPrecision, sharePnLConfig: props.sharePnLConfig, calcMode: props.calcMode, includedPendingOrder: props.includedPendingOrder, onSymbolChange: props.onSymbolChange } ) }) ] }); }; LiquidationTab = () => { const { t } = useTranslation(); return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-space-x-1", children: [ /* @__PURE__ */ jsx("span", { children: t("positions.liquidation") }), /* @__PURE__ */ jsx( Tooltip, { className: "oui-max-w-[275px] oui-bg-base-6", content: /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx("div", { className: "oui-text-pretty", children: t("positions.Liquidation.tooltip.liquidation") }), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx( "a", { href: "https://orderly.network/docs/introduction/trade-on-orderly/perpetual-futures/liquidations", target: "_blank", rel: "noopener noreferrer", className: "oui-text-primary", children: t("positions.Liquidation.tooltip.viewMore") } ) }) ] }), arrow: { className: "oui-fill-base-6" }, children: /* @__PURE__ */ jsx("span", { className: "oui-hidden oui-cursor-pointer group-data-[state=active]:oui-block", children: /* @__PURE__ */ jsx(InfoCircleIcon, {}) }) } ) ] }); }; DataList = (props) => { const { t } = useTranslation(); const { positionCount = 0, pendingOrderCount = 0, tpSlOrderCount = 0, showAllSymbol, symbol, onSymbolChange, pnlNotionalDecimalPrecision, sharePnLConfig, setShowAllSymbol, current, unPnlPriceBasis, setUnPnlPriceBasic, setPnlNotionalDecimalPrecision } = props; const tabPanelItems = [ { value: "Positions" /* positions */, title: `${t("common.positions")} ${positionCount > 0 ? `(${positionCount})` : ""}`, content: /* @__PURE__ */ jsx(PositionsView, { ...props }) }, { value: "Pending" /* pending */, title: `${t("orders.status.pending")} ${pendingOrderCount > 0 ? `(${pendingOrderCount})` : ""}`, content: /* @__PURE__ */ jsx( DesktopOrderListWidget, { type: TabType.pending, ordersStatus: OrderStatus.INCOMPLETE, symbol: showAllSymbol ? void 0 : symbol, onSymbolChange, testIds: { tableBody: "oui-testid-dataList-pending-table-body" } } ) }, { value: "TP/SL" /* tp_sl */, title: `${t("common.tpsl")} ${tpSlOrderCount > 0 ? `(${tpSlOrderCount})` : ""}`, content: /* @__PURE__ */ jsx( DesktopOrderListWidget, { type: TabType.tp_sl, ordersStatus: OrderStatus.INCOMPLETE, symbol: showAllSymbol ? void 0 : symbol, onSymbolChange, testIds: { tableBody: "oui-testid-dataList-tpsl-table-body" } } ) }, { value: "Filled" /* filled */, title: t("orders.status.filled"), content: /* @__PURE__ */ jsx( DesktopOrderListWidget, { type: TabType.filled, symbol: showAllSymbol ? void 0 : symbol, pnlNotionalDecimalPrecision, ordersStatus: OrderStatus.FILLED, onSymbolChange, testIds: { tableBody: "oui-testid-dataList-filled-table-body" }, sharePnLConfig } ) }, { value: "Position history" /* positionHistory */, title: t("positions.positionHistory"), content: /* @__PURE__ */ jsx( PositionHistoryWidget, { pnlNotionalDecimalPrecision, symbol: showAllSymbol ? void 0 : symbol, onSymbolChange, sharePnLConfig } ) }, { value: "Order history" /* orderHistory */, title: t("orders.orderHistory"), content: /* @__PURE__ */ jsx( DesktopOrderListWidget, { type: TabType.orderHistory, pnlNotionalDecimalPrecision, symbol: showAllSymbol ? void 0 : symbol, onSymbolChange, testIds: { tableBody: "oui-testid-dataList-orderHistory-table-body" }, sharePnLConfig } ) }, { value: "Liquidation" /* liquidation */, title: /* @__PURE__ */ jsx(LiquidationTab, {}), content: /* @__PURE__ */ jsx(LiquidationWidget, { symbol: showAllSymbol ? void 0 : symbol }) }, { value: "Assets" /* assets */, title: t("common.assets"), content: /* @__PURE__ */ jsx( Flex, { width: "100%", height: "100%", className: "oui-overflow-y-auto oui-hide-scrollbar oui-pt-3", children: /* @__PURE__ */ jsx( AssetsModule.AssetsDataTableWidget, { classNames: { scrollRoot: "oui-h-full oui-mb-6 oui-mt-0 oui-p-0 oui-pt-3 oui-h-[calc(100%_-_40px)]", root: "oui-gap-4 oui-h-full", desc: "oui-ml-1" }, dataTableClassNames: { header: "oui-bg-base-9", root: "oui-h-[calc(100%_-_28px)]" } } ) } ) } ]; return /* @__PURE__ */ jsx( Tabs, { className: "oui-trading-dataList-tabs oui-h-full", defaultValue: current || "Positions" /* positions */, variant: "contained", trailing: /* @__PURE__ */ jsx(React12.Suspense, { fallback: null, children: /* @__PURE__ */ jsx( LazySettingWidget, { pnlNotionalDecimalPrecision, setPnlNotionalDecimalPrecision, unPnlPriceBasis, setUnPnlPriceBasic, hideOtherSymbols: !showAllSymbol, setHideOtherSymbols: (value) => setShowAllSymbol(!value) } ) }), size: "lg", classNames: { trigger: "oui-group", tabsContent: "oui-h-[calc(100%_-_32px)]" }, children: tabPanelItems.map((item) => { const { content, ...rest } = item; return /* @__PURE__ */ createElement(TabPanel, { ...rest, key: `item-${rest.value}` }, content); }) } ); }; } }); var DataListWidget; var init_dataList_widget = __esm({ "src/components/desktop/dataList/dataList.widget.tsx"() { init_dataList_script(); init_dataList_ui(); DataListWidget = (props) => { const state = useDataListScript(props); return /* @__PURE__ */ jsx(DataList, { ...state }); }; } }); // src/components/desktop/dataList/index.ts var dataList_exports = {}; __export(dataList_exports, { DataList: () => DataList, DataListWidget: () => DataListWidget }); var init_dataList = __esm({ "src/components/desktop/dataList/index.ts"() { init_dataList_ui(); init_dataList_widget(); } }); var LastTrades, Row, Header, List; var init_lastTrades_ui = __esm({ "src/components/base/lastTrades/lastTrades.ui.tsx"() { LastTrades = (props) => { return /* @__PURE__ */ jsxs( Box, { className: cn( "oui-lastTrades", "oui-grid oui-grid-rows=[auto,1fr] oui-h-full oui-w-full", props.classNames?.root ), style: props.style, children: [ /* @__PURE__ */ jsx(Box, { className: "oui-pr-1", children: /* @__PURE__ */ jsx( Header, { base: props.base, quote: props.quote, className: props.classNames?.listHeader } ) }), /* @__PURE__ */ jsx( List, { data: props.data, isLoading: props.isLoading, baseDp: props.baseDp, quoteDp: props.quoteDp, classNames: props.classNames?.listItem, className: props.classNames?.list } ) ] } ); }; Row = (props) => { const { left, mid, right, classNames } = props; return ( // <Flex // key={key} // height={20} // gap={2} // width={"100%"} // className={cn("oui-text-xs oui-tabular-nums", classNames?.root)} // > // <Box className={cn("oui-flex-1", classNames?.left)}>{left}</Box> // <Box className={cn("oui-flex-1", classNames?.mid)}>{mid}</Box> // <Box className={cn("oui-flex-1 oui-text-right", classNames?.right)}> // {right} // </Box> // </Flex> /* @__PURE__ */ jsxs( Grid, { cols: 3, gapX: 2, width: "100%", className: cn("oui-text-xs oui-tabular-nums", classNames?.root), children: [ /* @__PURE__ */ jsx("div", { className: cn("oui-flex-1", classNames?.left), children: left }), /* @__PURE__ */ jsx("div", { className: cn("oui-flex-1", classNames?.mid), children: mid }), /* @__PURE__ */ jsx("div", { className: cn("oui-flex-1 oui-text-right", classNames?.right), children: right }) ] } ) ); }; Header = (props) => { const { t } = useTranslation(); return /* @__PURE__ */ jsx( Row, { left: t("common.time"), mid: `${t("common.price")}(${props.quote})`, right: `${t("common.qty")}(${props.base})`, classNames: { root: cn( "oui-text-base-contrast-54 oui-h-[32px] oui-sticky", props.className ) } } ); }; List = (props) => { return /* @__PURE__ */ jsx( ListView, { dataSource: props.data, className: cn( "oui-last-trades-list", "oui-w-full oui-h-full", props.className, "oui-overflow-auto" ), contentClassName: "!oui-space-y-0 oui-pr-[-4px]", renderItem: (item, index) => { return /* @__PURE__ */ jsx( Row, { left: /* @__PURE__ */ jsx(Text.formatted, { rule: "date", formatString: "HH:mm:ss", children: item?.ts }), mid: commifyOptional(item?.price, { fix: props.quoteDp }), right: commifyOptional(item?.size, { fix: props.baseDp }), classNames: { left: cn("oui-text-base-contrast-80", props.classNames?.left), right: cn( item.side === OrderSide.BUY ? "oui-text-trade-profit" : "oui-text-trade-loss", props.classNames?.mid ), mid: cn( item.side === OrderSide.BUY ? "oui-text-trade-profit" : "oui-text-trade-loss", props.classNames?.right ) } }, index ); } } ); }; } }); var useLastTradesScript; var init_lastTrades_script = __esm({ "src/components/base/lastTrades/lastTrades.script.tsx"() { useLastTradesScript = (symbol) => { const { data, isLoading } = useMarketTradeStream(symbol); const config = useSymbolsInfo()?.[symbol]; const base = config?.("base"); const quote = config?.("quote"); const baseDp = config?.("base_dp"); const quoteDp = config?.("quote_dp"); return { base, quote, data, isLoading, baseDp, quoteDp }; }; } }); var LastTradesWidget; var init_lastTrades_widget = __esm({ "src/components/base/lastTrades/lastTrades.widget.tsx"() { init_lastTrades_script(); init_lastTrades_ui(); LastTradesWidget = (props) => { const state = useLastTradesScript(props.symbol); return /* @__PURE__ */ jsx(LastTrades, { ...state, classNames: props.classNames, style: props.style }); }; } }); // src/components/base/lastTrades/index.ts var lastTrades_exports = {}; __export(lastTrades_exports, { LastTrades: () => LastTrades, LastTradesWidget: () => LastTradesWidget }); var init_lastTrades = __esm({ "src/components/base/lastTrades/index.ts"() { init_lastTrades_ui(); init_lastTrades_widget(); } }); function FaucetUi(props) { const { t } = useTranslation(); if (!props.showFaucet) { return null; } return /* @__PURE__ */ jsx( Button, { variant: "outlined", fullWidth: true, size: "md", onClick: props.getFaucet, loading: props.loading, className: "oui-faucet-btn oui-rounded oui-border-primary-light oui-text-primary-light", "data-testid": "oui-testid-assetView-getFaucet-button", children: t("trading.faucet.getTestUSDC") } ); } var init_faucet_ui = __esm({ "src/components/desktop/assetView/faucet/faucet.ui.tsx"() { } }); function useFaucetScript() { const { t } = useTranslation(); const { connectedChain, namespace } = useWalletConnector(); const { state, account } = useAccount(); const config = useConfig(); const operatorUrl = config.get("operatorUrl"); const [getTestUSDC, { isMutating }] = useMutation( `${operatorUrl}/v1/faucet/usdc` ); const [loading, setLoading] = useState(false); const showFaucet = useMemo(() => { if (!connectedChain || !connectedChain.id) { return false; } return (state.status === AccountStatusEnum.EnableTrading || state.status === AccountStatusEnum.EnableTradingWithoutConnected) && isTestnet(parseInt(connectedChain.id)); }, [state, connectedChain]); const getFaucet = () => { if (loading) { return; } setLoading(true); const message = t("trading.faucet.getTestUSDC.success", { quantity: namespace === ChainNamespace.solana ? "100" : "1,000" }); return getTestUSDC({ chain_id: account.walletAdapter?.chainId.toString(), user_address: state.address, broker_id: config.get("brokerId") }).then( (res) => { setLoading(false); if (res.success) { return modal.alert({ title: t("trading.faucet.getTestUSDC"), message, onOk: () => { return new Promise((resolve) => resolve(true)); } }); } res.message && toast$1.error(res.message); }, (error) => { toast$1.error(error.message); } ); }; return { getFaucet, showFaucet, loading }; } var init_faucet_script = __esm({ "src/components/desktop/assetView/faucet/faucet.script.tsx"() { } }); function FaucetWidget() { const state = useFaucetScript(); return /* @__PURE__ */ jsx(FaucetUi, { ...state }); } var init_faucet_widget = __esm({ "src/components/desktop/assetView/faucet/faucet.widget.tsx"() { init_faucet_ui(); init_faucet_script(); } }); var calculateTextColor, useCurrentStatusText, TooltipContent, TotalValue, AssetDetail, LTVDetail, AssetValueList, AssetView; var init_assetView_ui = __esm({ "src/components/desktop/assetView/assetView.ui.tsx"() { init_faucet_widget(); calculateTextColor = (val) => { if (val >= 0 && val < 50) { return "oui-text-success"; } else if (val >= 50 && val < 80) { return "oui-text-warning"; } else if (val >= 80) { return "oui-text-danger"; } else { return ""; } }; useCurrentStatusText = () => { const { state } = useAccount(); const { wrongNetwork, disabledConnect } = useAppContext(); const { t } = useTranslation(); return useMemo(() => { const statusText = { wrongNetwork: { title: t("connector.wrongNetwork"), description: t("connector.wrongNetwork.tooltip"), titleColor: "warning" }, connectWallet: { title: t("connector.connectWallet"), description: t("connector.trade.connectWallet.tooltip"), titleClsName: "oui-text-transparent oui-bg-clip-text oui-gradient-brand" }, createAccount: { title: t("connector.createAccount"), description: t("connector.trade.createAccount.tooltip"), titleColor: "primary" }, enableTrading: { title: t("connector.enableTrading"), description: t("connector.trade.enableTrading.tooltip"), titleColor: "primary" }, empty: { title: "", description: "" } }; if (disabledConnect) { return statusText.connectWallet; } if (wrongNetwork) { return statusText.wrongNetwork; } if (state.status === AccountStatusEnum.EnableTradingWithoutConnected) { return statusText.empty; } if (state.status <= AccountStatusEnum.NotConnected) { return statusText.connectWallet; } if (state.status <= AccountStatusEnum.NotSignedIn) { return statusText.createAccount; } if (state.status < AccountStatusEnum.EnableTrading) { return statusText.enableTrading; } return statusText.empty; }, [t, state.status, wrongNetwork, disabledConnect]); }; TooltipContent = (props) => { const { description, formula } = props; return /* @__PURE__ */ jsxs("div", { className: "oui-min-w-[204px] oui-max-w-[240px] oui-text-2xs oui-leading-normal oui-text-base-contrast-80", children: [ typeof description !== "undefined" && description !== null && /* @__PURE__ */ jsx("span", { children: description }), /* @__PURE__ */ jsx(Divider, { color: "oui-border-line-10", my: 2 }), typeof formula !== "undefined" && formula !== null && /* @__PURE__ */ jsx("span", { children: formula }) ] }); }; TotalValue = (props) => { const { t } = useTranslation(); const { totalValue, visible = true, onToggleVisibility } = props; return /* @__PURE__ */ jsxs( Flex, { direction: "column", gap: 1, className: "oui-text-2xs", itemAlign: "center", children: [ /* @__PURE__ */ jsx( Text.numeral, { visible, weight: "bold", size: "2xl", className: gradientTextVariants({ color: "brand" }), as: "div", padding: false, dp: 2, children: totalValue ?? "--" } ), /* @__PURE__ */ jsxs(Flex, { gap: 1, itemAlign: "center", children: [ /* @__PURE__ */ jsx(Text, { size: "2xs", color: "neutral", weight: "semibold", children: `${t("trading.asset.myAssets")} (USDC)` }), /* @__PURE__ */ jsx( "button", { className: "oui-assetView-toggle-visibility-btn", onClick: onToggleVisibility, children: visible ? /* @__PURE__ */ jsx(EyeIcon, { size: 18, className: "oui-text-base-contrast-54" }) : /* @__PURE__ */ jsx(EyeCloseIcon, { size: 18, className: "oui-text-base-contrast-54" }) } ) ] }) ] } ); }; AssetDetail = (props) => { const { label, description, formula, visible, value, unit, rule, placeholder } = props; return /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [ /* @__PURE__ */ jsx( Tooltip, { className: "", content: /* @__PURE__ */ jsx(TooltipContent, { description, formula }), children: /* @__PURE__ */ jsx( Text, { size: "2xs", color: "neutral", weight: "semibold", className: "oui-cursor-pointer oui-border-b oui-border-dashed oui-border-line-12", children: label } ) } ), /* @__PURE__ */ jsx( Text.numeral, { visible, size: "2xs", unit, unitClassName: "oui-text-base-contrast-36 oui-ml-0.5", as: "div", rule, padding: false, dp: 2, placeholder, children: value || "--" } ) ] }); }; LTVDetail = (props) => { const { visible, value } = props; const { t } = useTranslation(); return /* @__PURE__ */ jsxs(Flex, { justify: "between", children: [ /* @__PURE__ */ jsx( Tooltip, { className: cn("oui-bg-base-6 oui-p-2"), content: /* @__PURE__ */ jsx(LTVRiskTooltipWidget, {}), children: /* @__PURE__ */ jsx( Text, { size: "2xs", color: "neutral", weight: "semibold", className: "oui-cursor-pointer oui-border-b oui-border-dashed oui-border-line-12", children: t("transfer.LTV") } ) } ), /* @__PURE__ */ jsx( Text, { size: "2xs", className: cn( "select-none",