mango-v4-ui/components/trade/TradingViewChart.tsx

233 lines
7.9 KiB
TypeScript
Raw Normal View History

2022-09-13 23:24:26 -07:00
import { useEffect, useRef, useMemo, useState } from 'react'
import { useTheme } from 'next-themes'
import {
widget,
ChartingLibraryWidgetOptions,
IChartingLibraryWidget,
ResolutionString,
} from '@public/charting_library'
import mangoStore from '@store/mangoStore'
import { useViewport } from 'hooks/useViewport'
import { CHART_DATA_FEED, DEFAULT_MARKET_NAME } from 'utils/constants'
import { breakpoints } from 'utils/theme'
import { COLORS } from 'styles/colors'
2022-12-15 15:33:31 -08:00
import Datafeed from 'apis/birdeye/datafeed'
2022-09-13 23:24:26 -07:00
export interface ChartContainerProps {
container: ChartingLibraryWidgetOptions['container']
symbol: ChartingLibraryWidgetOptions['symbol']
interval: ChartingLibraryWidgetOptions['interval']
datafeedUrl: string
libraryPath: ChartingLibraryWidgetOptions['library_path']
chartsStorageUrl: ChartingLibraryWidgetOptions['charts_storage_url']
chartsStorageApiVersion: ChartingLibraryWidgetOptions['charts_storage_api_version']
clientId: ChartingLibraryWidgetOptions['client_id']
userId: ChartingLibraryWidgetOptions['user_id']
fullscreen: ChartingLibraryWidgetOptions['fullscreen']
autosize: ChartingLibraryWidgetOptions['autosize']
studiesOverrides: ChartingLibraryWidgetOptions['studies_overrides']
theme: string
}
const TradingViewChart = () => {
const { theme } = useTheme()
const { width } = useViewport()
2022-09-13 23:24:26 -07:00
const [chartReady, setChartReady] = useState(false)
2023-01-22 21:25:28 -08:00
const [spotOrPerp, setSpotOrPerp] = useState('spot')
2022-09-13 23:24:26 -07:00
const selectedMarketName = mangoStore((s) => s.selectedMarket.current?.name)
const isMobile = width ? width < breakpoints.sm : false
2022-11-19 11:20:36 -08:00
const defaultProps = useMemo(
2022-09-13 23:24:26 -07:00
() => ({
symbol: DEFAULT_MARKET_NAME,
interval: '60' as ResolutionString,
theme: 'Dark',
container: 'tv_chart_container',
datafeedUrl: CHART_DATA_FEED,
libraryPath: '/charting_library/',
fullscreen: false,
autosize: true,
studiesOverrides: {
2022-11-30 19:32:32 -08:00
'volume.volume.color.0': COLORS.DOWN[theme],
'volume.volume.color.1': COLORS.UP[theme],
2022-09-13 23:24:26 -07:00
'volume.precision': 4,
},
}),
[theme]
)
const tvWidgetRef = useRef<IChartingLibraryWidget | null>(null)
let chartStyleOverrides = {
'paneProperties.background': 'rgba(0,0,0,0)',
'paneProperties.backgroundType': 'solid',
'paneProperties.legendProperties.showBackground': false,
'paneProperties.vertGridProperties.color': 'rgba(0,0,0,0)',
'paneProperties.horzGridProperties.color': 'rgba(0,0,0,0)',
'paneProperties.legendProperties.showStudyTitles': false,
'scalesProperties.showStudyLastValue': false,
2022-09-15 20:40:30 -07:00
'scalesProperties.fontSize': 11,
2022-09-13 23:24:26 -07:00
}
const mainSeriesProperties = [
'candleStyle',
'hollowCandleStyle',
'haStyle',
'barStyle',
]
2022-09-25 23:13:25 -07:00
2022-09-13 23:24:26 -07:00
mainSeriesProperties.forEach((prop) => {
chartStyleOverrides = {
...chartStyleOverrides,
[`mainSeriesProperties.${prop}.barColorsOnPrevClose`]: true,
[`mainSeriesProperties.${prop}.drawWick`]: true,
[`mainSeriesProperties.${prop}.drawBorder`]: true,
2022-11-30 19:32:32 -08:00
[`mainSeriesProperties.${prop}.upColor`]: COLORS.UP[theme],
[`mainSeriesProperties.${prop}.downColor`]: COLORS.DOWN[theme],
[`mainSeriesProperties.${prop}.borderColor`]: COLORS.UP[theme],
[`mainSeriesProperties.${prop}.borderUpColor`]: COLORS.UP[theme],
[`mainSeriesProperties.${prop}.borderDownColor`]: COLORS.DOWN[theme],
[`mainSeriesProperties.${prop}.wickUpColor`]: COLORS.UP[theme],
[`mainSeriesProperties.${prop}.wickDownColor`]: COLORS.DOWN[theme],
2022-09-13 23:24:26 -07:00
}
})
useEffect(() => {
2022-12-24 08:38:25 -08:00
const group = mangoStore.getState().group
if (tvWidgetRef.current && chartReady && selectedMarketName && group) {
try {
2023-01-22 21:25:28 -08:00
let symbolName
if (!selectedMarketName.toLowerCase().includes('PERP')) {
symbolName = group
.getSerum3MarketByName(selectedMarketName)
.serumMarketExternal.toString()
} else {
symbolName = selectedMarketName
}
tvWidgetRef.current.setSymbol(
2023-01-22 21:25:28 -08:00
symbolName,
tvWidgetRef.current.activeChart().resolution(),
() => {
return
}
)
} catch (e) {
console.warn('Trading View change symbol error: ', e)
}
2022-12-24 08:38:25 -08:00
}
2022-09-13 23:24:26 -07:00
}, [selectedMarketName, chartReady])
2023-01-22 21:25:28 -08:00
useEffect(() => {
if (
selectedMarketName?.toLowerCase().includes('perp') &&
spotOrPerp !== 'perp'
) {
setSpotOrPerp('perp')
} else if (
!selectedMarketName?.toLowerCase().includes('perp') &&
spotOrPerp !== 'spot'
) {
setSpotOrPerp('spot')
}
}, [selectedMarketName, spotOrPerp])
2022-09-13 23:24:26 -07:00
useEffect(() => {
if (window) {
2023-01-22 21:25:28 -08:00
// const tempBtcDatafeedUrl = 'https://dex-pyth-price-mainnet.zeta.markets/tv/history?symbol=BTC-USDC&resolution=5&from=1674427748&to=1674430748&countback=2'
const tempBtcDatafeedUrl =
2023-01-23 09:47:28 -08:00
'https://redirect-origin.mangomarkets.workers.dev'
2023-01-22 21:25:28 -08:00
const btcDatafeed = new (window as any).Datafeeds.UDFCompatibleDatafeed(
tempBtcDatafeedUrl
)
2022-09-13 23:24:26 -07:00
const widgetOptions: ChartingLibraryWidgetOptions = {
// debug: true,
2023-01-22 21:25:28 -08:00
symbol:
spotOrPerp === 'spot'
? '8BnEgHoWFysVcuFFX7QztDmzuH8r5ZFvyP3sYwn1XTh6'
: 'BTC-USDC',
2022-09-13 23:24:26 -07:00
// BEWARE: no trailing slash is expected in feed URL
// tslint:disable-next-line:no-any
2023-01-22 21:25:28 -08:00
datafeed: spotOrPerp === 'spot' ? Datafeed : btcDatafeed,
2022-09-13 23:24:26 -07:00
interval:
defaultProps.interval as ChartingLibraryWidgetOptions['interval'],
container:
defaultProps.container as ChartingLibraryWidgetOptions['container'],
library_path: defaultProps.libraryPath as string,
locale: 'en',
enabled_features: ['hide_left_toolbar_by_default'],
2022-09-13 23:24:26 -07:00
disabled_features: [
'use_localstorage_for_settings',
'timeframes_toolbar',
isMobile ? 'left_toolbar' : '',
'show_logo_on_all_charts',
'caption_buttons_text_if_possible',
'header_settings',
// 'header_chart_type',
'header_compare',
'compare_symbol',
'header_screenshot',
// 'header_widget_dom_node',
// 'header_widget',
'header_saveload',
2022-09-13 23:24:26 -07:00
'header_undo_redo',
'header_interval_dialog_button',
'show_interval_dialog_on_key_press',
'header_symbol_search',
2022-09-29 21:21:23 -07:00
'popup_hints',
2022-09-13 23:24:26 -07:00
],
fullscreen: defaultProps.fullscreen,
autosize: defaultProps.autosize,
studies_overrides: defaultProps.studiesOverrides,
2022-12-04 15:06:06 -08:00
theme:
theme === 'Light' || theme === 'Banana' || theme === 'Lychee'
? 'Light'
: 'Dark',
2022-09-13 23:24:26 -07:00
custom_css_url: '/styles/tradingview.css',
loading_screen: {
backgroundColor:
theme === 'Dark'
? COLORS.BKG1.Dark
: theme === 'Light'
? COLORS.BKG1.Light
: theme === 'Mango Classic'
? COLORS.BKG1['Mango Classic']
: theme === 'Medium'
? COLORS.BKG1.Medium
: theme === 'Avocado'
? COLORS.BKG1.Avocado
: theme === 'Blueberry'
? COLORS.BKG1.Blueberry
2022-12-04 15:06:06 -08:00
: theme === 'Banana'
? COLORS.BKG1.Banana
2022-12-05 02:59:10 -08:00
: theme === 'Lychee'
? COLORS.BKG1.Lychee
: theme === 'Olive'
? COLORS.BKG1.Olive
: COLORS.BKG1['High Contrast'],
2022-09-13 23:24:26 -07:00
},
overrides: {
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
...chartStyleOverrides,
},
}
const tvWidget = new widget(widgetOptions)
tvWidgetRef.current = tvWidget
tvWidgetRef.current.onChartReady(function () {
setChartReady(true)
})
//eslint-disable-next-line
}
2023-01-22 21:25:28 -08:00
}, [theme, isMobile, defaultProps, spotOrPerp])
2022-09-13 23:24:26 -07:00
return (
<div id={defaultProps.container as string} className="tradingview-chart" />
)
}
export default TradingViewChart