Skip to content

Instantly share code, notes, and snippets.

@Swoorup
Last active March 1, 2023 16:27
Show Gist options
  • Save Swoorup/e02874cd5a034b3f8b17bb71bca2056e to your computer and use it in GitHub Desktop.
Save Swoorup/e02874cd5a034b3f8b17bb71bca2056e to your computer and use it in GitHub Desktop.
Viper charts demo
import { useEffect, useRef } from 'react';
import './App.css';
import { DataUpdates, HistoricalDataRequest, Price, UTCTimestamp, Viper as ViperCharts } from "@viper-charts/viper-charts";
// import "@viper-charts/viper-charts/dist/style.css";
import { ViperDatabase } from "./ViperDatabase";
const db = createDB();
function onSaveViperSettings(settings: any) {
localStorage.setItem("settings", JSON.stringify(settings));
}
async function onRequestTemplates() {
return await db.templates.where("id").above(0).toArray();
}
async function onSaveTemplate(id: number, { name, config }: any) {
// Check if template exists at id
const rows = await db.templates.where("id").equals(id).toArray();
const row = rows[0];
if (row) {
// If so, update it
await db.templates.update(id, { name, config });
} else {
// If not, create it
await db.templates.add({ name, config });
}
return await db.templates.orderBy("id").last();
}
async function onDeleteTemplate(id: number) {
await db.templates.delete(id);
}
function createDB() {
const db = new ViperDatabase();
return db;
}
async function getSourcesFromBinance() {
const res = await fetch(
"https://www.binance.com/api/v3/exchangeInfo"
);
const json = await res.json();
const sources: any = {};
for (const item of json.symbols) {
sources[item.symbol] = {
source: "BINANCE",
name: item.symbol,
maxItemsPerRequest: 500,
models: {
candle: {
model_id: "candle",
name: "Candle",
label: `Binance:${item.symbol}`,
},
},
};
}
return sources;
}
const onRequestHistoricalData = async (requests: HistoricalDataRequest[], api: ViperCharts) => {
for (const {
source,
name,
timeframe,
dataModels,
start,
end,
} of requests) {
if (source === "BINANCE") {
const tf = {
1000: "1s",
60000: "1m",
[60000 * 5]: "5m",
[60000 * 15]: "15m",
[60000 * 60]: "1h",
[60000 * 60 * 4]: "4h",
[60000 * 60 * 24]: "1d",
}[timeframe];
const res = await fetch(`https://www.binance.com/api/v3/klines?symbol=${name}&interval=${tf}&startTime=${start}&endTime=${end}`);
const json = await res.json();
for (const dataModel of dataModels) {
if (dataModel === "candle") {
const data = new Map() as DataUpdates;
for (const item of json) {
const [timestamp, open, high, low, close, volume] = item;
const time = new Date(timestamp).getTime();
data.set(time as UTCTimestamp, {
open: +open as Price,
high: +high as Price,
low: +low as Price,
close: +close as Price,
volume: +volume
});
}
api.addData({ source, name, timeframe, dataModel }, data);
}
}
}
}
}
function App() {
const viperChartRef = useRef<ViperCharts | null>(null);
const htmlRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
console.log("Initializing...");
async function initializeViper() {
// The sources available to ViperCharts
const sources = {
BINANCE: await getSourcesFromBinance(),
};
if (!htmlRef.current) return;
if (viperChartRef.current) {
// destroy if already initializing. In some instances useEffect is called twice.
viperChartRef.current.destroy();
};
// document.getElementById("chart")!,
viperChartRef.current = new ViperCharts({
element: htmlRef.current,
sources,
settings: JSON.parse(localStorage.getItem("settings")!) || {},
onRequestHistoricalData,
onSaveViperSettings,
onRequestTemplates,
onSaveTemplate,
onDeleteTemplate,
});
}
initializeViper();
return () => {
viperChartRef.current?.destroy();
viperChartRef.current = null;
}
}, [htmlRef])
return (
<div className="App">
<div ref={htmlRef} id="chart" style={{ width: "100%", height: "100vh" }}></div>
</div>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment