Skip to content

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.

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.

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

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);
}

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

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.

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.

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.