> ## 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.

# Rastrea acuñaciones de tokens de Pump.fun con Parsed Streams

> Suscríbete a las instrucciones create de Pump.fun con Helius Parsed Streams y crea un listener de Solana con reconexión segura que registre cada nueva acuñación de token y su creador.

Esta guía crea un listener de larga duración para **cada nuevo token de Pump.fun**. Filtra las dos instrucciones que Pump.fun usa para lanzar un token y mantiene la conexión durante tiempos de espera por inactividad e implementaciones.

<Steps>
  <Step title="Look Up the Program">
    Pump.fun lanza tokens mediante dos instrucciones, según la versión: `create` e `create_v2`. Confirma los nombres exactos y las funciones de las cuentas con [`describeProgram`](/docs/es/parsed-streams/quickstart#descubrimiento) antes de filtrarlas:

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

    Revisa la lista `instructions` de la respuesta para encontrar `create` e `create_v2`, y su lista `roles` para encontrar la cuenta que buscas. Por lo general, será la nueva dirección de **mint** y una función de cuenta `creator` o un campo `creator` en `args`. Las dos versiones de la instrucción no necesariamente tienen la misma estructura. Por eso, el siguiente código comprueba tanto un argumento como un par de nombres de funciones, en lugar de asumir una sola estructura.
  </Step>

  <Step title="Build the Filter">
    Filtra por el programa y por ambos nombres de instrucciones. Mantén activado `includeCpi`. Las instrucciones `create`/`create_v2` de Pump.fun suelen estar en el nivel superior, pero esta es una precaución de bajo costo. Excluye también las transacciones fallidas, ya que una implementación fallida nunca produce un mint activo:

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

  <Step title="Connect with a Reconnect-Safe Client">
    Un rastreador de implementaciones es un proceso de larga duración. Por eso, trata las desconexiones como algo habitual, no excepcional: supervisa la conexión inicial, mantén activa la conexión cuando el filtro no genere actividad y vuelve a conectarte automáticamente cuando se cierre.

    ```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://fs-beta.helius-rpc.com/?api-key=${API_KEY}`;
    const PUMP_PROGRAM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";

    const SUBSCRIBE_ID = 1;
    const PING_ID = 99;
    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 PING_INTERVAL_MS = 30_000; // server closes idle connections after 10 min

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

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

      // 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));
        pingTimer = setInterval(() => {
          if (ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify({ jsonrpc: "2.0", id: PING_ID, method: "ping" }));
          }
        }, PING_INTERVAL_MS);
      });

      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);
        if (pingTimer) clearInterval(pingTimer);
        console.log(`[${ts()}] closed (code=${event.code}, reason="${event.reason}"). reconnecting in 3s…`);
        setTimeout(connect, 3000);
      });
    }

    connect();
    ```

    <Tip>
      Para simplificar, esto usa un retraso fijo de 3 segundos antes de volver a conectarse. Para un listener de producción, usa una espera exponencial; consulta [Manejo de reconexiones](/docs/es/parsed-streams/guides/handling-reconnects).
    </Tip>
  </Step>

  <Step title="Handle Notifications and Log Each Deploy">
    Enruta los mensajes entrantes mediante `id` (tus propias solicitudes) o `method` (notificaciones enviadas por el servidor). Luego, extrae el mint, el creador y los metadatos de la instrucción decodificada:

    ```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.id === PING_ID) return; // keepalive pong, ignore quietly

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

    Como `includeFailed` es `false`, cada notificación que registras corresponde a un token que realmente se implementó. Comprueba que `ix.decoded` esté presente antes de confiar en `args` e `accounts`. Una compilación no reconocida del programa Pump.fun llega con `decoded: null` y, de lo contrario, aparecería como `mint: null`.
  </Step>
</Steps>

## Próximos pasos

<CardGroup cols={2}>
  <Card title="Track Jupiter Swaps" icon="arrow-right-arrow-left" href="/docs/es/parsed-streams/guides/track-jupiter-swaps">
    El flujo describeProgram → crear filtro → suscribirse con más detalle.
  </Card>

  <Card title="Handling Reconnects" icon="rotate" href="/docs/es/parsed-streams/guides/handling-reconnects">
    Espera exponencial y relleno de intervalos de slots para listeners de larga duración.
  </Card>

  <Card title="Fetch Pump.fun Mints" icon="clock-rotate-left" href="/docs/es/parsed-events/guides/fetch-pumpfun-mints">
    La versión histórica: recorre por páginas las implementaciones anteriores de un creador con Parsed Events.
  </Card>
</CardGroup>
