diff --git a/README.md b/README.md index 6a11737..3128758 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ import TradeViewChart from 'react-crypto-chart'; No Object
Candlestick Config type -
 
+    
     {
         upColor: "#00c176",
         downColor: "#cf304a",
@@ -153,6 +153,22 @@ import TradeViewChart from 'react-crypto-chart';
     }
   
+ + useFuturesTestnet + No + Boolean + +
false
+ + + + useSpotTestnet + No + Boolean + +
false
+ + diff --git a/package.json b/package.json index 9d8eda2..2020a5f 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,13 @@ "module": "./lib/esm/index.js", "types": "./lib/esm/index.d.ts", "author": "Justin K Xavier", + "contributors": [ + { + "name": "Rakibul Yeasin", + "email": "ryeasin03@gmail.com", + "url": "https://dreygur.js.org/" + } + ], "repository": { "url": "https://github.com/justinkx/react-crypto-chart.git" }, @@ -19,17 +26,15 @@ "/lib" ], "devDependencies": { - "@types/react": "^17.0.11", - "@types/react-dom": "^17.0.7", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", "typescript": "^4.3.2" }, - "peerDependencies": { - "react": "^16.8.0", - "react-dom": "^16.8.0" - }, "dependencies": { "lightweight-charts": "^3.8.0" + }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" } } diff --git a/src/TradeView.tsx b/src/TradeView.tsx index 8eb2de0..fbe7bd2 100644 --- a/src/TradeView.tsx +++ b/src/TradeView.tsx @@ -23,8 +23,7 @@ const TradeView: React.FC = ({ const volumeSeries = useRef(); const setInitialData = useCallback(() => { - candleSeries.current = - chart?.current?.addCandlestickSeries(candleStickConfig); + candleSeries.current = chart?.current?.addCandlestickSeries(candleStickConfig); candleSeries?.current.setData(initialChartData); volumeSeries.current = chart.current.addHistogramSeries(histogramConfig); volumeSeries?.current?.setData(initialChartData); @@ -72,6 +71,7 @@ const TradeView: React.FC = ({ return () => resizeObserver.current.disconnect(); }, []); + return (
= ({ pair = 'BTCBUSD', interval = '1m', + useFuturesTestnet = false, + useSpotTestnet = false, candleStickConfig = condleStickDefaultConfig, histogramConfig = histogramDefaultConfig, chartLayout = defaultChartLayout, containerStyle, }) => { - const [candleStickData, setCandleData] = useState<[] | null>(null); - const [updatedata, setUpdateData] = useState( - null - ); - - const fetchCandleData = useCallback(async () => { - const candleData = await fetchCandleStickData(pair); - setCandleData(candleData); - }, [pair]); + const [candleStickData, setCandleData] = useState(null); + const [updatedata, setUpdateData] = useState(null); useEffect(() => { - fetchCandleData(); - }, [fetchCandleData]); + fetchCandleStickData(pair, interval, useFuturesTestnet, useSpotTestnet) + .then(res => setCandleData(res)) + .catch(err => console.log(err)); - useEffect(() => { const ws = new WebSocket( - `${WS_URL}/${pair.toLocaleLowerCase()}@kline_${interval}` + `${getWebsocketUrl({ useFuturesTestnet, useSpotTestnet })}/${pair.toLocaleLowerCase()}@kline_${interval}` ); - // ws.onopen = () => console.log("open"); + ws.onmessage = (e) => { const message = JSON.parse(e.data); const parsedMessage = candleSocketAdaptor(message); @@ -46,11 +41,12 @@ const TradeViewChart: React.FC = ({ return () => { ws.close(); }; - }, [pair, interval]); + }, [pair, interval, useFuturesTestnet, useSpotTestnet]); if (!candleStickData) { return
; } + return ( { +import { CandleStickAdaptorResult } from "./types"; + +export const candleStickAdaptor = (data: any): CandleStickAdaptorResult => { const [ openTime, open, high, low, close, - volume, - closeTime, - quoteAssetVolume, - numberOfTrades, - takerBuyBaseAssetVolume, - takerBuyQuotessetVolume, - ignore, + volume ] = data; return { time: openTime / 1000, @@ -21,17 +17,10 @@ export const candleStickAdaptor = (data) => { close: parseFloat(close), value: parseFloat(volume), color: open < close ? "#005a40" : "#82112b", - - // closeTime, - // quoteAssetVolume, - // numberOfTrades, - // takerBuyBaseAssetVolume, - // takerBuyQuotessetVolume, - // ignore, }; }; -export const candleSocketAdaptor = (data) => { +export const candleSocketAdaptor = (data: any) => { const { k: { T, o, c, h, l, v, V }, } = data; diff --git a/src/utils/candleStickService.js b/src/utils/candleStickService.ts similarity index 61% rename from src/utils/candleStickService.js rename to src/utils/candleStickService.ts index ae6a976..08e8bfe 100644 --- a/src/utils/candleStickService.js +++ b/src/utils/candleStickService.ts @@ -1,7 +1,8 @@ import { candleStickAdaptor } from "./adaptor"; +import { CandleStickAdaptorResult } from "./types"; export const parseCandleStickData = (candleArray = []) => { - const transformedData = candleArray.reduce((accu, curr) => { + const transformedData = candleArray.reduce((accu: CandleStickAdaptorResult[], curr) => { const candle = candleStickAdaptor(curr); accu.push(candle); return accu; diff --git a/src/utils/constants.js b/src/utils/constants.ts similarity index 100% rename from src/utils/constants.js rename to src/utils/constants.ts diff --git a/src/utils/fetchService.js b/src/utils/fetchService.ts similarity index 53% rename from src/utils/fetchService.js rename to src/utils/fetchService.ts index 2ae791a..a035bd2 100644 --- a/src/utils/fetchService.js +++ b/src/utils/fetchService.ts @@ -1,11 +1,13 @@ -import { BASE_URL } from "./constants"; +import { getBaseUrl } from "./urls"; import { parseCandleStickData } from "./candleStickService"; export const fetchCandleStickData = async ( symbol = "BTCBUSD", - interval = "1m" + interval = "1m", + useFuturesTestnet = false, + useSpotTestnet = false, ) => { - const url = `${BASE_URL}symbol=${symbol}&interval=${interval}`; + const url = `${getBaseUrl({ useFuturesTestnet, useSpotTestnet })}symbol=${symbol}&interval=${interval}`; const result = await fetch(url); const data = await result.json(); return parseCandleStickData(data); diff --git a/src/utils/types.ts b/src/utils/types.ts index 18a6860..7a58ace 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1,5 +1,15 @@ import { CrosshairMode, LineStyle } from 'lightweight-charts'; +export interface CandleStickAdaptorResult { + time: number; + open: number; + high: number; + low: number; + close: number; + value: number; + color: string; +} + export interface CandleStickSocketData { open: number; high: number; @@ -10,7 +20,7 @@ export interface CandleStickSocketData { color: string; } export interface TradeViewProps { - initialChartData: []; + initialChartData: CandleStickAdaptorResult[]; updatedata: CandleStickSocketData | null; candleStickConfig: CandleStickConfig; histogramConfig: HistogramConfig; @@ -52,10 +62,12 @@ export interface TradeViewChart { } export interface Props { pair: string; - interval: string; - candleStickConfig: CandleStickConfig; - histogramConfig: HistogramConfig; - chartLayout: DeffaultChartLayout; + interval?: string; + candleStickConfig?: CandleStickConfig; + histogramConfig?: HistogramConfig; + chartLayout?: DeffaultChartLayout; + useFuturesTestnet?: boolean; + useSpotTestnet?: boolean; containerStyle?: { [x: string]: any; }; diff --git a/src/utils/urls.ts b/src/utils/urls.ts new file mode 100644 index 0000000..e13b135 --- /dev/null +++ b/src/utils/urls.ts @@ -0,0 +1,34 @@ +const url: { [key: string]: { [key: string]: string } } = { + main: { + base: "https://api.binance.com/api/v3/klines?", + ws: "wss://stream.binance.com:9443/ws" + }, + future: { + base: "https://testnet.binancefuture.com/fapi/v1/klines?", + ws: "wss://stream.binancefuture.com/ws" + }, + spot: { + base: "https://testnet.binance.vision/api/v3/klines?", + ws: "wss://testnet.binance.vision/ws" + } +}; + +export function getBaseUrl({ useFuturesTestnet, useSpotTestnet }: { useFuturesTestnet?: boolean, useSpotTestnet?:boolean }): string { + if (useFuturesTestnet && !useSpotTestnet) { + return url.future.base; + } + if (!useFuturesTestnet && useSpotTestnet) { + return url.spot.base; + } + return url.main.base; +} + +export function getWebsocketUrl({ useFuturesTestnet, useSpotTestnet }: { useFuturesTestnet?: boolean, useSpotTestnet?: boolean }): string { + if (useFuturesTestnet && !useSpotTestnet) { + return url.future.ws; + } + if (!useFuturesTestnet && useSpotTestnet) { + return url.spot.ws; + } + return url.main.ws; +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 7d2ffa6..c04e3cb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,33 +1,33 @@ { - "compilerOptions": { - "outDir": "lib/esm", - "module": "esnext", - "target": "es5", - "lib": [ - "es6", - "dom", - "es2016", - "es2017" - ], - "jsx": "react", - "declaration": true, - "moduleResolution": "node", - "noUnusedLocals": true, - "noUnusedParameters": true, - "esModuleInterop": true, - "noImplicitReturns": true, - "noImplicitThis": true, - "noImplicitAny": true, - "strictNullChecks": true, - "suppressImplicitAnyIndexErrors": true, - "allowSyntheticDefaultImports": true, - "allowJs": true - }, - "include": [ - "src" + "compilerOptions": { + "outDir": "lib/esm", + "module": "esnext", + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" ], - "exclude": [ - "node_modules", - "lib" - ] -} \ No newline at end of file + "jsx": "react-jsx", + "declaration": true, + "moduleResolution": "node", + "noUnusedLocals": true, + "noUnusedParameters": true, + "esModuleInterop": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": true, + "strictNullChecks": true, + "suppressImplicitAnyIndexErrors": true, + "allowSyntheticDefaultImports": true, + "allowJs": true, + "strict": true + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules", + "lib" + ] +}