Skip to main content

API Reference

createChart

import { createChart } from 'polynode-charts'

const chart = createChart(container, options?)
ParameterTypeDescription
containerHTMLElement | stringDOM element or CSS selector
optionsChartOptionsOptional configuration

ChartOptions

interface ChartOptions {
  width?: number            // fixed width (px)
  height?: number           // fixed height (px)
  autoSize?: boolean        // auto-resize to container (default: true)
  layout?: LayoutOptions
  grid?: GridOptions
  crosshair?: CrosshairOptions
  timeScale?: TimeScaleOptions
  rightPriceScale?: PriceScaleOptions
}

LayoutOptions

interface LayoutOptions {
  background?: string    // default: '#080d16'
  textColor?: string     // default: '#556'
  fontFamily?: string    // default: '"SF Mono", "Fira Code", monospace'
  fontSize?: number      // default: 10
}

GridOptions

interface GridOptions {
  vertLines?: { color?: string; visible?: boolean }
  horzLines?: { color?: string; visible?: boolean }
}

PriceScaleOptions

interface PriceScaleOptions {
  mode?: 'normal' | 'probability'  // 'probability' clamps axis to 0-100%
  autoScale?: boolean
  scaleMargins?: { top?: number; bottom?: number }
}

Chart

Series Methods

chart.addCandleSeries(opts?: CandleSeriesOptions): CandleSeries
chart.addLineSeries(opts?: LineSeriesOptions): LineSeries
chart.addAreaSeries(opts?: AreaSeriesOptions): AreaSeries
chart.addVolumeSeries(opts?: VolumeSeriesOptions): VolumeSeries
chart.removeSeries(series): void

Scale Access

chart.timeScale(): TimeScale

Events

// Subscribe to crosshair movement — returns unsubscribe function
const unsub = chart.subscribeCrosshairMove((params) => {
  console.log(params.time, params.point)
})
unsub()  // stop listening

// Subscribe to chart clicks
const unsub2 = chart.subscribeClick((params) => {
  console.log('Clicked at time:', params.time)
})
CrosshairMoveParams:
interface CrosshairMoveParams {
  time: number | null
  point: { x: number; y: number } | null
  seriesData: Map<string, OhlcData | LineData>
}
ClickParams:
interface ClickParams {
  time: number | null
  point: { x: number; y: number }
}

Utility

chart.getContainer(): HTMLElement  // returns the chart's parent DOM element

Lifecycle

chart.resize(width, height): void  // manual resize
chart.remove(): void               // cleanup everything

Series

All series share these common methods:
series.setData(data[]): void      // replace all data
series.update(item): void          // append or update last point
series.setMaxLength(n): void       // cap buffer size (drops oldest)

CandleSeries

const series = chart.addCandleSeries({
  upColor: '#22c55e',
  downColor: '#ef4444',
  wickUpColor: '#22c55e',    // optional, defaults to upColor
  wickDownColor: '#ef4444',  // optional, defaults to downColor
  borderVisible: true,
})
Data shape:
interface OhlcData {
  time: number   // epoch milliseconds
  open: number
  high: number
  low: number
  close: number
  volume?: number
}

LineSeries

const series = chart.addLineSeries({
  color: '#f7931a',
  lineWidth: 2,
  smooth: true,        // bezier curve interpolation
  showDot: true,       // pulsing dot at last point
  dotColor: '#f7931a',
})
Data shape:
interface LineData {
  time: number   // epoch milliseconds
  value: number
}
Live mode:
series.setLive(true)   // phantom point + smooth lerp
series.isLive()        // check live state
Price line overlay:
series.setPriceLine(72822.50, {
  color: '#3b82f6',
  dash: [6, 4],
  label: 'PRICE TO BEAT',
  labelColor: '#fff',
})

series.clearPriceLine()
series.getPriceLine()  // returns PriceLineConfig | null
The price line renders as a dashed horizontal line across the chart with a label on the left and a price badge on the right axis. The Y-axis auto-expands to keep the price line visible.

AreaSeries

Extends LineSeries with a gradient fill beneath the line.
const series = chart.addAreaSeries({
  color: '#6ea8fe',          // line color
  topColor: '#6ea8fe33',     // gradient top
  bottomColor: '#6ea8fe00',  // gradient bottom (transparent)
  lineWidth: 2,
  smooth: true,
})
Uses the same LineData shape as LineSeries.

VolumeSeries

Automatically creates a separate pane at 22% of chart height.
const series = chart.addVolumeSeries({
  upColor: 'rgba(34, 197, 94, 0.4)',
  downColor: 'rgba(239, 68, 68, 0.4)',
  opacity: 0.4,
})
Data shape:
interface VolumeData {
  time: number
  value: number
  color?: string  // override per-bar color
}

TimeScale

const ts = chart.timeScale()
MethodDescription
goLive()Enable live mode. Auto-scrolls to newest data. Snaps back after 4s idle.
isLive()Returns true if in live mode
setVisibleRange(start, end)Set visible time range (epoch ms)
animateToRange(start, end)Animated zoom to range
zoomAt(factor, mouseXFrac)Zoom around a point (scroll wheel)
getVisibleStart()Left edge time (epoch ms)
getVisibleEnd()Right edge time (epoch ms)
getVisibleWindow()Duration of visible range (ms)
Live mode behavior: When live, the chart auto-scrolls to show the latest data. If the user pans or zooms away, the chart remembers and snaps back to live after 4 seconds of idle. This gives users freedom to explore history while keeping the default view current.

Orderbook

import { createOrderbook } from 'polynode-charts'

const ob = createOrderbook('#orderbook', {
  colorBid: '#22c55e',
  colorAsk: '#ef4444',
  depthFillOpacity: 0.08,
  labelCount: 8,
})

ob.update({
  bids: [{ price: 0.54, size: 1200 }, { price: 0.53, size: 800 }],
  asks: [{ price: 0.55, size: 900 }, { price: 0.56, size: 1500 }],
})

OrderbookOptions

interface OrderbookOptions {
  colorBid?: string          // default: '#22c55e'
  colorAsk?: string          // default: '#ef4444'
  depthFillOpacity?: number  // default: 0.08
  labelCount?: number        // price labels on axis
  background?: string
  textColor?: string
}

BookData

interface BookData {
  bids: PriceLevel[]
  asks: PriceLevel[]
}

interface PriceLevel {
  price: number
  size: number
}
MethodDescription
ob.update(data)Replace book data and re-render
ob.destroy()Remove DOM and stop rendering

createShortFormOverlay

One-liner to add Polymarket short-form price-to-beat overlays to any live chart. Adds interval buttons, auto-discovers markets, draws a dashed price-to-beat line, and shows live odds with a countdown timer.
import { createChart, createShortFormOverlay } from 'polynode-charts'

const chart = createChart('#btc', { layout: { background: '#0c1220' } })
const series = chart.addLineSeries({ color: '#f7931a', showDot: true })
series.setLive(true)
chart.timeScale().goLive()

// One line: buttons + discovery + price line + odds + countdown
const overlay = createShortFormOverlay(chart, series, { coin: 'btc' })

ShortFormOverlayOptions

interface ShortFormOverlayOptions {
  coin: ShortFormCoin                   // 'btc' | 'eth' | 'sol' | 'xrp' | 'doge' | 'hype'
  intervals?: ShortFormInterval[]       // default: ['5m', '15m', '1h']
  defaultInterval?: ShortFormInterval   // if set, auto-starts on creation
  onRotation?: (event: RotationEvent) => void  // callback on each poll/rotation
}

ShortFormOverlay (return type)

MethodDescription
overlay.setInterval('15m')Switch to a different interval
overlay.stop()Stop polling, remove price line, clear display
overlay.destroy()Full cleanup: stop + remove DOM
overlay.getActiveInterval()Returns current interval or null

What it renders

  • Interval buttons (5m, 15m, 1h) — click to toggle on/off
  • Price-to-beat line — horizontal dashed blue line on the chart
  • Odds display — “24% up · 77% down · 1m35s” with live countdown
  • Auto-rotation — discovers the next market window when the current one expires

PolynodeProvider — MarketInfo

The outcome field tells you which side of a binary market this token represents.
interface MarketInfo {
  token_id: string
  question: string        // the market question (e.g. "US x Iran ceasefire by April 7?")
  slug: string
  image: string
  last_price: number
  volume_24h: number
  outcomes: string[]      // e.g. ['Yes', 'No']
  outcome: string         // which outcome THIS token is ('Yes' or 'No')
  condition_id?: string
  neg_risk?: boolean      // true for multi-outcome events (elections, championships)
}
The neg_risk field indicates a multi-outcome event on Polymarket. When provider.event() searches for multi-outcome markets, it prioritizes neg_risk: true markets to find genuine events (elections, World Cup, NBA Finals) rather than binary matches.