> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cabalspy.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Live Wallet Count Badge

> Show how many tracked KOL wallets are in a token as a live badge or heat indicator, with a REST poll for a number on demand or a WebSocket for live updates.

Learn how to show a simple, powerful number next to any token, how many tracked KOL wallets are in it. It makes a great activity badge, a heat indicator, or a cheap trigger before you pull heavier data. This guide covers both ways to get it in TypeScript, with no CSS, so you can style the badge yourself.

## Two numbers, two sources

Before any code, know which number you want, because the two sources answer slightly different questions.

| Source                      | What it counts                                         | Best for                                              |
| --------------------------- | ------------------------------------------------------ | ----------------------------------------------------- |
| REST /v1/transactions/count | How many trades tracked wallets made in a time window  | Activity over the last hour, a quick on-demand number |
| WSS count stream            | How many distinct KOL wallets hold the token right now | A live holder count badge that updates as wallets buy |

If your badge says how many KOLs are in this token, you want the stream and its kol\_count. If it says how active has this token been lately, you want the REST count.

## Option A, a number on demand over REST

The REST counter is one call. You give it a chain, a wallet type and a time window built from seconds, minutes and hours, up to 24 hours back, and it returns just the count. No transactions, so it is fast and cheap.

### Step 1, the fetch

```typescript src/count-rest.ts theme={null}
const API_BASE = 'https://api.cabalspy.xyz/v1';

export async function fetchTradeCount(mint: string, hours = 1): Promise<number> {
  const params = new URLSearchParams({
    blockchain: 'solana',
    type: 'kol',
    hours: String(hours),
    mint,
    api_key: import.meta.env.VITE_CABALSPY_KEY as string,
  });
  const res = await fetch(`${API_BASE}/transactions/count?${params}`);
  const body = await res.json();
  if (!body.success) throw new Error(body.error?.message || 'count failed');
  return body.data.count as number;
}
```

### Step 2, show it, and refresh on an interval

Since REST gives you a snapshot, poll it on a timer if you want it to stay current. A 30 second interval is plenty for an activity badge.

```typescript src/badge-rest.ts theme={null}
import { fetchTradeCount } from './count-rest';

export function mountRestBadge(el: HTMLElement, mint: string): () => void {
  const update = async () => {
    try { el.textContent = `${await fetchTradeCount(mint)} trades (1h)`; }
    catch { el.textContent = '-'; }
  };
  update();
  const timer = setInterval(update, 30_000);
  return () => clearInterval(timer); // call to stop polling
}
```

That is the whole REST path. One call, one number, refreshed on a timer.

## Option B, a live badge over WebSocket

The stream is better when you want the badge to update the moment a KOL buys. You subscribe once, and every time the KOL wallet count for a token changes, you get the new number pushed to you.

### Step 1, connect and subscribe

Subscribe with the wildcard to watch every token, or pass a single mint to watch one. The stream always reports the KOL wallet count, it is not split by wallet type.

```typescript src/count-stream.ts theme={null}
export interface CountUpdate { mint: string; kol_count: number; }

export function connectCountStream(
  onUpdate: (u: CountUpdate) => void,
  token: string = '*',
): () => void {
  const key = import.meta.env.VITE_CABALSPY_KEY as string;
  const ws = new WebSocket(`wss://stream.cabalspy.xyz?apiKey=${encodeURIComponent(key)}`);

  ws.onopen = () => {
    ws.send(JSON.stringify({ op: 'subscribe', stream: 'count', blockchain: 'solana', token }));
  };
  ws.onmessage = (e) => {
    const msg = JSON.parse(e.data);
    if (msg.event === 'wallet_count') {
      onUpdate({ mint: msg.data.mint, kol_count: msg.data.kol_count });
    }
  };
  return () => { try { ws.close(); } catch { /* already closing */ } };
}
```

### Step 2, keep a count per token and render

Hold the latest count per mint in a Map, and update the matching badge whenever an event arrives. This scales to a whole list of tokens on one connection.

```typescript src/badges-live.ts theme={null}
import { connectCountStream } from './count-stream';

const counts = new Map<string, number>();

export function startLiveBadges(): () => void {
  return connectCountStream(({ mint, kol_count }) => {
    counts.set(mint, kol_count);
    // Update the badge for this token if it is on the page.
    const badge = document.querySelector(`[data-mint="${mint}"] .kol-badge`);
    if (badge) badge.textContent = `${kol_count} KOLs`;
  });
}
```

Your markup just needs the mint on each row and a badge element to fill in.

```html index.html theme={null}
<div data-mint="3Pkrq4MmLvDXyn1fa3sz5MekKRkZkc1iLDcz5AzWpump">
  invisibull <span class="kol-badge">0 KOLs</span>
</div>
```

## Which one should you use

A simple rule. If you are decorating a static list and a number that is a little stale is fine, poll the REST count, it is one call and needs no connection. If the freshness is the point, a live count that ticks up as KOLs pile in, use the stream.

You can also combine them. Seed each badge with a REST count on first paint so it is never empty, then let the stream take over for live updates.

## Billing note

The REST count is one request per call, cheap because it returns only a number. On the stream, each delivered wallet\_count event counts against your plan, so a wildcard subscription on a busy chain can add up, filter to the tokens you actually show.

## Reference

<CardGroup cols={2}>
  <Card title="GET /v1/transactions/count" href="/api-reference/transactions-count">
    The REST counter over a time window.
  </Card>

  <Card title="WSS count stream" href="/websockets/count">
    The live KOL wallet count per token.
  </Card>
</CardGroup>
