# Charts

> Candles from the tape, paging into history, live updates over the WebSocket, and trade markers.

Source: https://getchord.xyz/docs/recipes/charts/

**Goal**: a candlestick chart for any indexed token on Arc or Robinhood Chain that loads in one call, pages backwards for history, and updates live.

## Load

```ts
const A = "https://api.getchord.xyz/v1";
const { candles, tf, source } = await fetch(`${A}/tokens/chart/${addr}?tf=1h`).then((r) => r.json());
// candles: [{ t, o, h, l, c, v }] oldest first, up to 200
```

Timeframes: `1m` · `5m` · `15m` · `1h` · `4h` · `1d` · `1w`. `v` is USD volume in the bucket. `source: "db"` means Chord's own tape. A `404 UNKNOWN_TOKEN` means the address is neither on a curated list nor a side of an indexed pool.

## Page into history

Pass the oldest `t` you have as `before`; each page is 200 candles.

```ts
async function older() {
  const first = candles[0]?.t;
  const page = await fetch(`${A}/tokens/chart/${addr}?tf=1h&before=${first}`).then((r) => r.json());
  candles.unshift(...page.candles);
}
```

## Live

Subscribe to the same token and timeframe on the WebSocket. The open candle is re-sent as it changes; `closed: true` seals it.

```ts
ws.send(JSON.stringify({ op: "sub", channel: "candles", token: addr, tf: "1h" }));
ws.onmessage = (e) => {
  const m = JSON.parse(e.data);
  if (m.op !== "candle" || m.token !== addr || m.tf !== "1h") return;
  const last = candles.at(-1);
  if (last && last.t === m.candle.t) Object.assign(last, m.candle); else candles.push(m.candle);
};
```

Switching timeframes: unsubscribe the old `tf`, fetch the new, subscribe the new. Eight channels per connection is enough for a chart, a tape and the price feed.

## Trade markers

For a connected wallet, `GET /portfolio/{wallet}/trades?chain=5042` returns its buys and sells (`t`, `side`, `usd`, `tokenAmt`, `token`, `tx`); filter by token and draw markers at `t`. For the whole market, `GET /tokens/trades/{address}?min=1000` gives the large prints.

## Gaps

A bucket with no trades has no candle. Draw the gap or carry the last close forward — but do not invent a bar; the API does not.
