Интеграция TradingView Lightweight Charts в dApp

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Интеграция TradingView Lightweight Charts в dApp
Средняя
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1058
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Интеграция TradingView Lightweight Charts в dApp

TradingView Lightweight Charts — open-source библиотека (~45 KB gzipped), которую используют большинство DEX'ов для отображения ценовых графиков. Dydx, GMX, Uniswap Info — все они либо используют её напрямую, либо fork'ают. Интеграция в dApp несложная, но есть несколько мест, где производительность ломается при работе с on-chain данными.

Базовая инициализация

import { createChart, IChartApi, CandlestickData } from 'lightweight-charts';

const chartContainer = useRef<HTMLDivElement>(null);
const chartRef = useRef<IChartApi>();

useEffect(() => {
  if (!chartContainer.current) return;

  const chart = createChart(chartContainer.current, {
    width: chartContainer.current.clientWidth,
    height: 400,
    layout: {
      background: { color: '#0d0d0d' },
      textColor: '#9ca3af',
    },
    grid: {
      vertLines: { color: '#1f2937' },
      horzLines: { color: '#1f2937' },
    },
    timeScale: {
      timeVisible: true,
      secondsVisible: false,
    },
  });

  chartRef.current = chart;
  return () => chart.remove();
}, []);

Обязательно вызывайте chart.remove() в cleanup функции useEffect, иначе при hot reload или размонтировании компонента накапливаются утечки памяти.

Подача данных из on-chain источников

Это главная проблема при интеграции с dApp. On-chain данные для OHLCV-свечей берутся из нескольких источников:

Subgraph (The Graph) — самый распространённый вариант для DEX. Uniswap v3 subgraph предоставляет poolHourDatas и poolDayDatas с OHLC по каждому пулу. Запрос:

query GetCandles($pool: String!, $startTime: Int!) {
  poolHourDatas(
    where: { pool: $pool, periodStartUnix_gte: $startTime }
    orderBy: periodStartUnix
    first: 1000
  ) {
    periodStartUnix
    open
    high
    low
    close
    volumeUSD
  }
}

Преобразование в формат LWC:

const candles: CandlestickData[] = data.poolHourDatas.map((d) => ({
  time: d.periodStartUnix as UTCTimestamp,
  open: parseFloat(d.open),
  high: parseFloat(d.high),
  low: parseFloat(d.low),
  close: parseFloat(d.close),
}));

candleSeries.setData(candles);

Real-time обновления — polling subgraph каждые 30–60 секунд или WebSocket подписка на Swap-события через RPC. При получении нового события пересчитываем текущую незакрытую свечу и обновляем через candleSeries.update(newCandle) вместо setData (полный пересет данных при каждом тике убивает производительность).

Синхронизация нескольких графиков

Если нужны два синхронных графика (цена + объём), используем chart.timeScale().subscribeVisibleTimeRangeChange() для синхронизации viewport между инстансами. Стандартная практика для торговых интерфейсов:

chart1.timeScale().subscribeVisibleTimeRangeChange((range) => {
  if (range) chart2.timeScale().setVisibleRange(range);
});

Адаптивный ресайзинг

LWC не адаптируется автоматически при изменении размера контейнера. Используем ResizeObserver:

const resizeObserver = new ResizeObserver(entries => {
  const { width, height } = entries[0].contentRect;
  chart.applyOptions({ width, height });
});
resizeObserver.observe(chartContainer.current);

Кастомные маркеры и overlay

Для отображения on-chain событий поверх графика (liquidations, large trades) используем series.setMarkers():

series.setMarkers([
  {
    time: timestamp as UTCTimestamp,
    position: 'belowBar',
    color: '#ef4444',
    shape: 'arrowUp',
    text: 'Liquidation $2.4M',
  },
]);

Маркеры отображаются прямо на свечах и не требуют кастомного рендеринга — это существенно проще, чем реализовывать overlay через canvas напрямую.