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

# Track Pump.fun Token Mints with Parsed Streams

> Subscribe to Pump.fun create instructions with Helius Parsed Streams and build a reconnect-safe Solana listener that logs every new token mint and creator.

This guide builds a long-running listener for **every new Pump.fun token**. It filters on the two instructions Pump.fun uses to launch a token, and stays connected across idle timeouts and deploys.

**1. Look Up the Program**

Pump.fun launches tokens through two instructions depending on version: `create` and `create_v2`. Confirm the exact names and account roles with [`describeProgram`](https://www.helius.dev/docs/parsed-streams/quickstart#discovery) before filtering on them. It is currently only available on `wss://fs-beta.helius-rpc.com/?api-key=<API_KEY>`:

```json Request theme={"system"}
{ "jsonrpc": "2.0", "id": 1, "method": "describeProgram", "params": [{ "program": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" }] }
```

Check the response's `instructions` list for `create` and `create_v2`, and its `roles` list for the account you want — typically the new **mint** address, and either a `creator` account role or a `creator` field in `args`. The two instruction versions don't necessarily share a shape, which is why the code below checks both an arg and a couple of role names rather than assuming one.

**2. Build the Filter**

Filter on the program and both instruction names. Leave `includeCpi` on — Pump.fun's `create`/`create_v2` are usually top-level, but this is cheap insurance — and exclude failed transactions since a failed deploy never produces a live mint:

```json theme={"system"}
{
  "programs": ["6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"],
  "instructionNames": ["create", "create_v2"],
  "includeFailed": false,
  "includeCpi": true
}
```

**3. Connect with a Reconnect-Safe Client**

A deploy tracker is a long-running process, so treat disconnects as routine rather than exceptional: watchdog the initial handshake, keep the connection alive on a quiet filter, and reconnect automatically on close.

```javascript pumpfun-deploys.js theme={"system"}
const API_KEY = process.env.HELIUS_API_KEY;

if (!API_KEY) {
  console.error("Missing HELIUS_API_KEY.");
  process.exit(1);
}

const URL = `wss://beta.helius-rpc.com/?api-key=${API_KEY}`;
const PUMP_PROGRAM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";

const SUBSCRIBE_ID = 1;
const SUBSCRIBE_REQUEST = {
  jsonrpc: "2.0",
  id: SUBSCRIBE_ID,
  method: "parsedTransactionSubscribe",
  params: [
    {
      programs: [PUMP_PROGRAM],
      instructionNames: ["create", "create_v2"],
      includeFailed: false,
      includeCpi: true,
    },
  ],
};

const CONNECT_TIMEOUT_MS = 10_000;

const ts = () => new Date().toISOString();

function connect() {
  console.log(`[${ts()}] connecting…`);
  const ws = new WebSocket(URL);

  // Watchdog: if the handshake never completes, force-close so we retry
  // instead of hanging silently in CONNECTING.
  const connectTimer = setTimeout(() => {
    if (ws.readyState === WebSocket.CONNECTING) {
      console.error(`[${ts()}] handshake stalled after ${CONNECT_TIMEOUT_MS}ms — closing`);
      ws.close();
    }
  }, CONNECT_TIMEOUT_MS);

  ws.addEventListener("open", () => {
    clearTimeout(connectTimer);
    console.log(`[${ts()}] connected, subscribing to pump create/create_v2`);
    ws.send(JSON.stringify(SUBSCRIBE_REQUEST));
  });

  ws.addEventListener("message", (event) => handleMessage(event.data));

  ws.addEventListener("error", (err) => {
    console.error(`[${ts()}] socket error:`, err.message || err);
  });

  ws.addEventListener("close", (event) => {
    clearTimeout(connectTimer);
    console.log(`[${ts()}] closed (code=${event.code}, reason="${event.reason}"). reconnecting in 3s…`);
    setTimeout(connect, 3000);
  });
}

connect();
```

> [!TIP]
>
> This uses a fixed 3-second reconnect delay for simplicity. For a production listener, back off exponentially instead — see [Handling Reconnects](https://www.helius.dev/docs/parsed-streams/guides/handling-reconnects.md).

**4. Handle Notifications and Log Each Deploy**

Route incoming messages by `id` (your own requests) or `method` (server-pushed notifications), then pull the mint, creator, and metadata out of the decoded instruction:

```javascript theme={"system"}
// Pull an account pubkey out of a decoded instruction by its role name.
function accountByRole(decoded, role) {
  return decoded?.accounts?.find((a) => a.name === role)?.pubkey ?? null;
}

let deployCount = 0;

function handleDeploy(tx, ix) {
  deployCount += 1;
  const args = ix.decoded?.args ?? {};
  const mint = accountByRole(ix.decoded, "mint");
  const creator =
    args.creator ??
    accountByRole(ix.decoded, "creator") ??
    accountByRole(ix.decoded, "user");

  console.log(`[${ts()}] pump deploy #${deployCount} (${ix.instructionName})`);
  console.log(`    mint:    ${mint}`);
  console.log(`    creator: ${creator}`);
  console.log(`    name:    ${args.name ?? "?"}`);
  console.log(`    symbol:  ${args.symbol ?? "?"}`);
  console.log(`    uri:     ${args.uri ?? "?"}`);
  console.log(`    slot=${tx.slot} sig=${tx.signature}`);
}

function handleMessage(raw) {
  let msg;
  try {
    msg = JSON.parse(raw);
  } catch {
    console.log(`[${ts()}] non-JSON message:`, raw);
    return;
  }

  if (msg.error) {
    console.error(`[${ts()}] error (code=${msg.error.code}): ${msg.error.message}`);
    return;
  }
  if (msg.id === SUBSCRIBE_ID && typeof msg.result === "number") {
    console.log(`[${ts()}] subscribed (subscription id=${msg.result})`);
    return;
  }

  if (msg.method === "parsedTransactionNotification") {
    const { value } = msg.params.result;
    // Default details is "full", so value.instructions is the whole
    // transaction; matchedIndexes points at just the create/create_v2
    // instructions this filter hit.
    for (const i of value.matchedIndexes) handleDeploy(value.transaction, value.instructions[i]);
    return;
  }

  console.log(`[${ts()}] message:`, JSON.stringify(msg, null, 2));
}
```

Because `includeFailed` is `false`, every notification you log is a token that actually deployed. Check `ix.decoded` is present before trusting `args` and `accounts` — an unrecognized build of the Pump.fun program arrives with `decoded: null` and would otherwise show up as `mint: null`.

## Next Steps

> [card] [Track Jupiter Swaps](https://www.helius.dev/docs/parsed-streams/guides/track-jupiter-swaps.md)
>
> The describeProgram → build filter → subscribe flow in more detail.

> [card] [Handling Reconnects](https://www.helius.dev/docs/parsed-streams/guides/handling-reconnects.md)
>
> Exponential backoff and slot-gap backfill for long-running listeners.

> [card] [Fetch Pump.fun Mints](https://www.helius.dev/docs/parsed-events/guides/fetch-pumpfun-mints.md)
>
> The historical version: page through a creator's past deploys with Parsed Events.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.