diff --git a/src/constants/trade.ts b/src/constants/trade.ts index ff042cf..658134d 100644 --- a/src/constants/trade.ts +++ b/src/constants/trade.ts @@ -4,7 +4,6 @@ import { AlertType } from '@/constants/alerts'; import { STRING_KEYS } from '@/constants/localization'; import { TimeUnitShort } from '@/constants/time'; -// TODO: rename to OrderType export enum TradeTypes { MARKET = 'MARKET', LIMIT = 'LIMIT', @@ -15,6 +14,16 @@ export enum TradeTypes { TRAILING_STOP = 'TRAILING_STOP', } +enum ClosingTradeTypes { + LIQUIDATED = 'LIQUIDATED', + LIQUIDATION = 'LIQUIDATION', + OFFSETTING = 'OFFSETTING', + DELEVERAGED = 'DELEVERAGED', + FINAL_SETTLEMENT = 'FINAL_SETTLEMENT', +} + +export type OrderType = TradeTypes | ClosingTradeTypes; + export enum TimeInForceOptions { GTT = 'GTT', FOK = 'FOK', @@ -40,49 +49,74 @@ export const POSITION_SIDE_STRINGS: Record = { [PositionSide.Short]: STRING_KEYS.SHORT_POSITION_SHORT, }; -export const TRADE_TYPE_STRINGS: Record< - TradeTypes, +export const ORDER_TYPE_STRINGS: Record< + OrderType, { - tradeTypeKeyShort: string; - tradeTypeKey: string; - descriptionKey: string; + orderTypeKeyShort: string; + orderTypeKey: string; + descriptionKey: string | null; } > = { [TradeTypes.LIMIT]: { - tradeTypeKeyShort: STRING_KEYS.LIMIT_ORDER_SHORT, - tradeTypeKey: STRING_KEYS.LIMIT_ORDER, + orderTypeKeyShort: STRING_KEYS.LIMIT_ORDER_SHORT, + orderTypeKey: STRING_KEYS.LIMIT_ORDER, descriptionKey: STRING_KEYS.LIMIT_ORDER_DESCRIPTION, }, [TradeTypes.MARKET]: { - tradeTypeKeyShort: STRING_KEYS.MARKET_ORDER_SHORT, - tradeTypeKey: STRING_KEYS.MARKET_ORDER, + orderTypeKeyShort: STRING_KEYS.MARKET_ORDER_SHORT, + orderTypeKey: STRING_KEYS.MARKET_ORDER, descriptionKey: STRING_KEYS.MARKET_ORDER_DESCRIPTION, }, [TradeTypes.STOP_LIMIT]: { - tradeTypeKeyShort: STRING_KEYS.STOP_LIMIT, - tradeTypeKey: STRING_KEYS.STOP_LIMIT, + orderTypeKeyShort: STRING_KEYS.STOP_LIMIT, + orderTypeKey: STRING_KEYS.STOP_LIMIT, descriptionKey: STRING_KEYS.STOP_LIMIT_DESCRIPTION, }, [TradeTypes.STOP_MARKET]: { - tradeTypeKeyShort: STRING_KEYS.STOP_MARKET, - tradeTypeKey: STRING_KEYS.STOP_MARKET, + orderTypeKeyShort: STRING_KEYS.STOP_MARKET, + orderTypeKey: STRING_KEYS.STOP_MARKET, descriptionKey: STRING_KEYS.STOP_MARKET_DESCRIPTION, }, [TradeTypes.TAKE_PROFIT]: { - tradeTypeKeyShort: STRING_KEYS.TAKE_PROFIT_LIMIT, - tradeTypeKey: STRING_KEYS.TAKE_PROFIT_LIMIT, + orderTypeKeyShort: STRING_KEYS.TAKE_PROFIT_LIMIT, + orderTypeKey: STRING_KEYS.TAKE_PROFIT_LIMIT, descriptionKey: STRING_KEYS.TAKE_PROFIT_LIMIT_DESCRIPTION, }, [TradeTypes.TAKE_PROFIT_MARKET]: { - tradeTypeKeyShort: STRING_KEYS.TAKE_PROFIT_MARKET, - tradeTypeKey: STRING_KEYS.TAKE_PROFIT_MARKET, + orderTypeKeyShort: STRING_KEYS.TAKE_PROFIT_MARKET, + orderTypeKey: STRING_KEYS.TAKE_PROFIT_MARKET, descriptionKey: STRING_KEYS.TAKE_PROFIT_MARKET_DESCRIPTION, }, [TradeTypes.TRAILING_STOP]: { - tradeTypeKeyShort: STRING_KEYS.TRAILING_STOP, - tradeTypeKey: STRING_KEYS.TRAILING_STOP, + orderTypeKeyShort: STRING_KEYS.TRAILING_STOP, + orderTypeKey: STRING_KEYS.TRAILING_STOP, descriptionKey: STRING_KEYS.TRAILING_STOP_DESCRIPTION, }, + [ClosingTradeTypes.LIQUIDATED]: { + orderTypeKeyShort: STRING_KEYS.LIQUIDATED, + orderTypeKey: STRING_KEYS.LIQUIDATED, + descriptionKey: null, + }, + [ClosingTradeTypes.LIQUIDATION]: { + orderTypeKeyShort: STRING_KEYS.LIQUIDATION, + orderTypeKey: STRING_KEYS.LIQUIDATION, + descriptionKey: null, + }, + [ClosingTradeTypes.OFFSETTING]: { + orderTypeKeyShort: STRING_KEYS.OFFSETTING, + orderTypeKey: STRING_KEYS.OFFSETTING, + descriptionKey: null, + }, + [ClosingTradeTypes.DELEVERAGED]: { + orderTypeKeyShort: STRING_KEYS.DELEVERAGED, + orderTypeKey: STRING_KEYS.DELEVERAGED, + descriptionKey: null, + }, + [ClosingTradeTypes.FINAL_SETTLEMENT]: { + orderTypeKeyShort: STRING_KEYS.FINAL_SETTLEMENT, + orderTypeKey: STRING_KEYS.FINAL_SETTLEMENT, + descriptionKey: null, + }, }; export const GOOD_TIL_TIME_TIMESCALE_STRINGS: Record = { diff --git a/src/hooks/tradingView/useTradingView.ts b/src/hooks/tradingView/useTradingView.ts index 68065d8..dc8a641 100644 --- a/src/hooks/tradingView/useTradingView.ts +++ b/src/hooks/tradingView/useTradingView.ts @@ -5,9 +5,11 @@ import isEmpty from 'lodash/isEmpty'; import { LanguageCode, ResolutionString, widget } from 'public/tradingview/charting_library'; import { DEFAULT_RESOLUTION } from '@/constants/candles'; -import { SUPPORTED_LOCALE_BASE_TAGS } from '@/constants/localization'; +import { SUPPORTED_LOCALE_BASE_TAGS, STRING_KEYS } from '@/constants/localization'; + import { LocalStorageKey } from '@/constants/localStorage'; -import { useDydxClient, useLocalStorage } from '@/hooks'; + +import { useDydxClient, useLocalStorage, useStringGetter } from '@/hooks'; import { store } from '@/state/_store'; import { getSelectedNetwork } from '@/state/appSelectors'; @@ -23,14 +25,19 @@ import { getSavedResolution, getWidgetOptions, getWidgetOverrides } from '@/lib/ */ export const useTradingView = ({ tvWidgetRef, + displayButtonRef, setIsChartReady, }: { tvWidgetRef: React.MutableRefObject; + displayButtonRef: React.MutableRefObject; setIsChartReady: React.Dispatch>; }) => { - const marketId = useSelector(getCurrentMarketId); + const stringGetter = useStringGetter(); + const appTheme = useSelector(getAppTheme); const appColorMode = useSelector(getAppColorMode); + + const marketId = useSelector(getCurrentMarketId); const marketIds = useSelector(getMarketIds, shallowEqual); const selectedLocale = useSelector(getSelectedLocale); const selectedNetwork = useSelector(getSelectedNetwork); @@ -49,7 +56,6 @@ export const useTradingView = ({ const widgetOptions = getWidgetOptions(); const widgetOverrides = getWidgetOverrides({ appTheme, appColorMode }); const options = { - // debug: true, ...widgetOptions, ...widgetOverrides, datafeed: getDydxDatafeed(store, getCandlesForDatafeed), @@ -63,6 +69,17 @@ export const useTradingView = ({ tvWidgetRef.current = tvChartWidget; tvWidgetRef.current.onChartReady(() => { + tvWidgetRef?.current?.headerReady().then(() => { + displayButtonRef.current = tvWidgetRef?.current?.createButton(); + displayButtonRef.current.innerHTML = `${stringGetter({ + key: STRING_KEYS.ORDER_LINES, + })}
`; + displayButtonRef.current.setAttribute( + 'title', + stringGetter({ key: STRING_KEYS.ORDER_LINES_TOOLTIP }) + ); + }); + tvWidgetRef?.current?.subscribe('onAutoSaveNeeded', () => tvWidgetRef?.current?.save((chartConfig: object) => setTvChartConfig(chartConfig)) ); @@ -72,6 +89,8 @@ export const useTradingView = ({ } return () => { + displayButtonRef.current?.remove(); + displayButtonRef.current = null; tvWidgetRef.current?.remove(); tvWidgetRef.current = null; setIsChartReady(false); diff --git a/src/hooks/tradingView/useTradingViewTheme.ts b/src/hooks/tradingView/useTradingViewTheme.ts index b0ed677..d9b4467 100644 --- a/src/hooks/tradingView/useTradingViewTheme.ts +++ b/src/hooks/tradingView/useTradingViewTheme.ts @@ -1,12 +1,16 @@ import { useEffect } from 'react'; import { useSelector } from 'react-redux'; -import type { IChartingLibraryWidget, ThemeName } from 'public/tradingview/charting_library'; +import type { + IChartingLibraryWidget, + IOrderLineAdapter, + ThemeName, +} from 'public/tradingview/charting_library'; import { AppColorMode, AppTheme } from '@/state/configs'; import { getAppTheme, getAppColorMode } from '@/state/configsSelectors'; -import { getWidgetOverrides } from '@/lib/tradingView/utils'; +import { getWidgetOverrides, getOrderLineColors } from '@/lib/tradingView/utils'; /** * @description Method to define a type guard and check that an element is an IFRAME @@ -22,9 +26,11 @@ const isIFrame = (element: HTMLElement | null): element is HTMLIFrameElement => * In order to support our Classic along with Dark/Light, we are directly accessing the within the iFrame. */ export const useTradingViewTheme = ({ + orderLines, tvWidget, isWidgetReady, }: { + orderLines: Record; tvWidget: (IChartingLibraryWidget & { _id?: string; _ready?: boolean }) | null; isWidgetReady?: boolean; }) => { @@ -37,8 +43,8 @@ export const useTradingViewTheme = ({ .changeTheme?.( { [AppTheme.Classic]: '', - [AppTheme.Dark]: 'Dark', - [AppTheme.Light]: 'Light', + [AppTheme.Dark]: 'dark', + [AppTheme.Light]: 'light', }[appTheme] as ThemeName ) .then(() => { @@ -49,9 +55,17 @@ export const useTradingViewTheme = ({ if (isIFrame(frame) && frame.contentWindow) { const innerHtml = frame.contentWindow.document.documentElement; - - if (appTheme === AppTheme.Classic) { - innerHtml?.classList.remove('theme-dark', 'theme-light'); + switch (appTheme) { + case AppTheme.Classic: + innerHtml?.classList.remove('theme-dark', 'theme-light'); + break; + case AppTheme.Dark: + innerHtml?.classList.remove('theme-light'); + innerHtml?.classList.add('theme-dark'); + break; + case AppTheme.Light: + innerHtml?.classList.remove('theme-dark'); + innerHtml?.classList.add('theme-light'); } } } @@ -73,7 +87,22 @@ export const useTradingViewTheme = ({ 'volume.color.1': studies_overrides['volume.volume.color.1'], }); } + + // Necessary to update existing chart lines + Object.entries(orderLines).forEach(([key, line]) => { + const { orderColor, borderColor, backgroundColor, textColor, textButtonColor } = + getOrderLineColors({ side: key.split('-')[0], appTheme, appColorMode }); + + line + .setLineColor(orderColor) + .setQuantityBackgroundColor(orderColor) + .setQuantityBorderColor(borderColor) + .setBodyBackgroundColor(backgroundColor) + .setBodyBorderColor(borderColor) + .setBodyTextColor(textColor) + .setQuantityTextColor(textButtonColor); + }); }); } - }, [appTheme, appColorMode]); + }, [appTheme, appColorMode, isWidgetReady]); }; diff --git a/src/lib/tradingView/utils.ts b/src/lib/tradingView/utils.ts index 471a468..3e55537 100644 --- a/src/lib/tradingView/utils.ts +++ b/src/lib/tradingView/utils.ts @@ -1,6 +1,8 @@ +import { OrderSide } from '@dydxprotocol/v4-client-js'; + import { Candle, TradingViewBar, TradingViewSymbol } from '@/constants/candles'; -import type { AppTheme, AppColorMode } from '@/state/configs'; +import { AppTheme, type AppColorMode } from '@/state/configs'; import { Themes } from '@/styles/themes'; @@ -47,6 +49,30 @@ export const getHistorySlice = ({ return bars.filter(({ time }) => time >= fromMs); }; +export const getOrderLineColors = ({ + appTheme, + appColorMode, + side, +}: { + appTheme: AppTheme; + appColorMode: AppColorMode; + side: OrderSide; +}) => { + const theme = Themes[appTheme][appColorMode]; + const orderColor = { + [OrderSide.BUY]: theme.positive, + [OrderSide.SELL]: theme.negative, + }[side]; + + return { + orderColor, + borderColor: theme.borderDefault, + backgroundColor: theme.layer1, + textColor: theme.textTertiary, + textButtonColor: theme.textButton, + }; +}; + export const getWidgetOverrides = ({ appTheme, appColorMode, @@ -57,6 +83,7 @@ export const getWidgetOverrides = ({ const theme = Themes[appTheme][appColorMode]; return { + theme: appTheme === AppTheme.Dark ? 'dark' : AppTheme.Light ? 'light' : '', overrides: { 'paneProperties.background': theme.layer2, 'paneProperties.horzGridProperties.color': theme.layer3, diff --git a/src/pages/trade/TradeDialogTrigger.tsx b/src/pages/trade/TradeDialogTrigger.tsx index 79e4094..e746142 100644 --- a/src/pages/trade/TradeDialogTrigger.tsx +++ b/src/pages/trade/TradeDialogTrigger.tsx @@ -3,7 +3,7 @@ import { useSelector, shallowEqual } from 'react-redux'; import styled, { AnyStyledComponent } from 'styled-components'; import { STRING_KEYS } from '@/constants/localization'; -import { TRADE_TYPE_STRINGS } from '@/constants/trade'; +import { ORDER_TYPE_STRINGS } from '@/constants/trade'; import { layoutMixins } from '@/styles/layoutMixins'; @@ -43,7 +43,7 @@ export const TradeDialogTrigger = () => { - {stringGetter({ key: TRADE_TYPE_STRINGS[selectedTradeType].tradeTypeKey })} + {stringGetter({ key: ORDER_TYPE_STRINGS[selectedTradeType].orderTypeKey })} diff --git a/src/views/charts/TvChart.tsx b/src/views/charts/TvChart.tsx index f3586ff..783549c 100644 --- a/src/views/charts/TvChart.tsx +++ b/src/views/charts/TvChart.tsx @@ -1,28 +1,52 @@ import { useEffect, useRef, useState } from 'react'; + +import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import styled, { type AnyStyledComponent, css } from 'styled-components'; -import { useDispatch, useSelector } from 'react-redux'; -import type { IChartingLibraryWidget, ResolutionString } from 'public/tradingview/charting_library'; +import type { + IChartingLibraryWidget, + IOrderLineAdapter, + ResolutionString, +} from 'public/tradingview/charting_library'; -import { DEFAULT_MARKETID } from '@/constants/markets'; +import { AbacusOrderStatus } from '@/constants/abacus'; import { DEFAULT_RESOLUTION, RESOLUTION_CHART_CONFIGS } from '@/constants/candles'; +import { DEFAULT_MARKETID } from '@/constants/markets'; +import { type OrderType, ORDER_TYPE_STRINGS } from '@/constants/trade'; + +import { useStringGetter } from '@/hooks'; import { useTradingView, useTradingViewTheme } from '@/hooks/tradingView'; import { LoadingSpace } from '@/components/Loading/LoadingSpinner'; +import { getCurrentMarketOrders } from '@/state/accountSelectors'; +import { getAppTheme, getAppColorMode } from '@/state/configsSelectors'; import { setTvChartResolution } from '@/state/perpetuals'; - import { getCurrentMarketId, getSelectedResolutionForMarket } from '@/state/perpetualsSelectors'; import { layoutMixins } from '@/styles/layoutMixins'; +import { MustBigNumber } from '@/lib/numbers'; +import { getOrderLineColors } from '@/lib/tradingView/utils'; + type TvWidget = IChartingLibraryWidget & { _id?: string; _ready?: boolean }; -export const TvChart = () => { - const [isChartReady, setIsChartReady] = useState(false); +let orderLines: Record = {}; +export const TvChart = () => { const dispatch = useDispatch(); + const stringGetter = useStringGetter(); + + const [isChartReady, setIsChartReady] = useState(false); + const [showOrderLines, setShowOrderLines] = useState(false); + + const displayButtonRef = useRef(null); + + const appTheme = useSelector(getAppTheme); + const appColorMode = useSelector(getAppColorMode); + const currentMarketId: string = useSelector(getCurrentMarketId) || DEFAULT_MARKETID; + const currentMarketOrders = useSelector(getCurrentMarketOrders, shallowEqual); const selectedResolution: string = useSelector(getSelectedResolutionForMarket(currentMarketId)) || DEFAULT_RESOLUTION; @@ -33,8 +57,8 @@ export const TvChart = () => { const chart = isWidgetReady ? tvWidget?.chart() : undefined; const chartResolution = chart?.resolution?.(); - const { savedResolution } = useTradingView({ tvWidgetRef, setIsChartReady }); - useTradingViewTheme({ tvWidget, isWidgetReady }); + const { savedResolution } = useTradingView({ tvWidgetRef, displayButtonRef, setIsChartReady }); + useTradingViewTheme({ tvWidget, isWidgetReady, orderLines }); const setVisibleRangeForResolution = ({ resolution }: { resolution: ResolutionString }) => { // Different resolutions have different timeframes to display data efficiently. @@ -49,6 +73,9 @@ export const TvChart = () => { tvWidget?.activeChart().setVisibleRange(newRange, { percentRightMargin: 10 }); }; + /** + * @description Hook to handle changing chart resolution + */ useEffect(() => { if (chartResolution) { if (chartResolution !== selectedResolution) { @@ -69,6 +96,111 @@ export const TvChart = () => { } }, [currentMarketId, isWidgetReady]); + /** + * @description Hook to handle order line toggle state + */ + useEffect(() => { + if (isChartReady && displayButtonRef && displayButtonRef.current) { + displayButtonRef.current.onclick = () => { + const newShowOrderLinesState = !showOrderLines; + if (newShowOrderLinesState) { + displayButtonRef.current?.classList?.add('order-lines-active'); + } else { + displayButtonRef.current?.classList?.remove('order-lines-active'); + } + setShowOrderLines(newShowOrderLinesState); + }; + } + }, [isChartReady, showOrderLines]); + + /** + * @description Hook to handle drawing order lines + */ + useEffect(() => { + if (tvWidget && isChartReady) { + tvWidget.onChartReady(() => { + tvWidget.chart().dataReady(() => { + if (showOrderLines) { + drawOrderLines(); + } else { + deleteOrderLines(); + } + }); + }); + } + }, [isChartReady, showOrderLines, currentMarketOrders, currentMarketId]); + + const drawOrderLines = () => { + if (!currentMarketOrders) return; + currentMarketOrders.forEach( + ({ + id, + type, + status, + side, + cancelReason, + remainingSize, + size, + triggerPrice, + price, + trailingPercent, + }) => { + const key = `${side.rawValue}-${id}`; + const quantity = (remainingSize ?? size).toString(); + + const orderType = type.rawValue as OrderType; + const orderLabel = stringGetter({ + key: ORDER_TYPE_STRINGS[orderType].orderTypeKey, + }); + const orderString = trailingPercent ? `${orderLabel} ${trailingPercent}%` : orderLabel; + + const shouldShow = + !cancelReason && + (status === AbacusOrderStatus.open || status === AbacusOrderStatus.untriggered); + + const maybeOrderLine = key in orderLines ? orderLines[key] : null; + if (maybeOrderLine) { + if (!shouldShow) { + maybeOrderLine.remove(); + delete orderLines[key]; + return; + } else if (maybeOrderLine.getQuantity() !== quantity) { + maybeOrderLine.setQuantity(quantity); + return; + } + } else if (shouldShow) { + const { orderColor, borderColor, backgroundColor, textColor, textButtonColor } = + getOrderLineColors({ side: side.rawValue, appTheme, appColorMode }); + + const orderLine = tvWidget + ?.chart() + .createOrderLine({ disableUndo: false }) + .setPrice(MustBigNumber(triggerPrice ?? price).toNumber()) + .setQuantity(quantity) + .setText(orderString) + .setLineColor(orderColor) + .setQuantityBackgroundColor(orderColor) + .setQuantityBorderColor(borderColor) + .setBodyBackgroundColor(backgroundColor) + .setBodyBorderColor(borderColor) + .setBodyTextColor(textColor) + .setQuantityTextColor(textButtonColor); + + if (orderLine) { + orderLines[key] = orderLine; + } + } + } + ); + }; + + const deleteOrderLines = () => { + Object.values(orderLines).forEach((line) => { + line.remove(); + }); + orderLines = {}; + }; + return ( {!isChartReady && } diff --git a/src/views/dialogs/TradeDialog.tsx b/src/views/dialogs/TradeDialog.tsx index 081bdf2..2eff8c0 100644 --- a/src/views/dialogs/TradeDialog.tsx +++ b/src/views/dialogs/TradeDialog.tsx @@ -4,7 +4,7 @@ import styled, { AnyStyledComponent, css } from 'styled-components'; import { TradeInputField } from '@/constants/abacus'; import { STRING_KEYS, StringKey } from '@/constants/localization'; -import { TradeTypes, TRADE_TYPE_STRINGS, MobilePlaceOrderSteps } from '@/constants/trade'; +import { TradeTypes, ORDER_TYPE_STRINGS, MobilePlaceOrderSteps } from '@/constants/trade'; import { useBreakpoints, useStringGetter } from '@/hooks'; import { layoutMixins } from '@/styles/layoutMixins'; diff --git a/src/views/forms/TradeForm/PlaceOrderButtonAndReceipt.tsx b/src/views/forms/TradeForm/PlaceOrderButtonAndReceipt.tsx index 6b44ef4..3770ad5 100644 --- a/src/views/forms/TradeForm/PlaceOrderButtonAndReceipt.tsx +++ b/src/views/forms/TradeForm/PlaceOrderButtonAndReceipt.tsx @@ -5,7 +5,7 @@ import type { TradeInputSummary } from '@/constants/abacus'; import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons'; import { DialogTypes } from '@/constants/dialogs'; import { STRING_KEYS } from '@/constants/localization'; -import { TRADE_TYPE_STRINGS, MobilePlaceOrderSteps } from '@/constants/trade'; +import { ORDER_TYPE_STRINGS, MobilePlaceOrderSteps } from '@/constants/trade'; import { useStringGetter, useTokenConfigs } from '@/hooks'; @@ -184,7 +184,7 @@ export const PlaceOrderButtonAndReceipt = ({ ORDER: stringGetter({ key: isClosePosition ? STRING_KEYS.CLOSE_ORDER - : TRADE_TYPE_STRINGS[selectedTradeType].tradeTypeKey, + : ORDER_TYPE_STRINGS[selectedTradeType].orderTypeKey, }), }, })} diff --git a/src/views/notifications/TradeNotification/index.tsx b/src/views/notifications/TradeNotification/index.tsx index d628b2d..b723f13 100644 --- a/src/views/notifications/TradeNotification/index.tsx +++ b/src/views/notifications/TradeNotification/index.tsx @@ -11,7 +11,7 @@ import { } from '@/constants/abacus'; import { STRING_KEYS } from '@/constants/localization'; -import { TRADE_TYPE_STRINGS, TradeTypes } from '@/constants/trade'; +import { ORDER_TYPE_STRINGS, TradeTypes } from '@/constants/trade'; import { useStringGetter } from '@/hooks'; import { layoutMixins } from '@/styles/layoutMixins'; @@ -48,7 +48,7 @@ export const TradeNotification = ({ isToast, data, notification }: TradeNotifica const { assetId } = marketData ?? {}; const orderType = ORDER_TYPE as KotlinIrEnumValues; const tradeType = TRADE_TYPES[orderType]; - const titleKey = tradeType && TRADE_TYPE_STRINGS[tradeType]?.tradeTypeKey; + const titleKey = tradeType && ORDER_TYPE_STRINGS[tradeType]?.orderTypeKey; const orderStatus = ORDER_STATUS as KotlinIrEnumValues; return ( diff --git a/tradingview/tradingview.tgz b/tradingview/tradingview.tgz index ebc537f..e845da8 100644 Binary files a/tradingview/tradingview.tgz and b/tradingview/tradingview.tgz differ