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

# Suivez les créations de jetons Pump.fun avec des flux analysés

> Abonnez-vous aux instructions de création Pump.fun avec Helius Parsed Streams et construisez un écouteur Solana sécurisé contre les reconnexions qui enregistre chaque nouvelle création de jeton et créateur.

Ce guide construit un écouteur de longue durée pour **chaque nouveau jeton Pump.fun**. Il filtre les deux instructions que Pump.fun utilise pour lancer un jeton, et reste connecté malgré les délais d'inactivité et les déploiements.

<Steps>
  <Step title="Recherchez le programme">
    Pump.fun lance des jetons via deux instructions selon la version : `create` et `create_v2`. Confirmez les noms exacts et les rôles des comptes avec [`describeProgram`](/docs/fr/parsed-streams/quickstart#découverte) avant de les filtrer :

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

    Vérifiez la liste `instructions` de la réponse pour `create` et `create_v2`, et sa liste `roles` pour le compte souhaité — généralement la nouvelle adresse **mint**, et soit un rôle de compte `creator` ou un champ `creator` dans `args`. Les deux versions d'instruction ne partagent pas nécessairement une même structure, c'est pourquoi le code ci-dessous vérifie à la fois un argument et quelques noms de rôles au lieu de supposer une seule structure.
  </Step>

  <Step title="Construire le filtre">
    Filtrez sur le programme et les deux noms d'instruction. Laissez `includeCpi` activé — les `create`/`create_v2` de Pump.fun sont généralement de haut niveau, mais c'est une protection bon marché — et excluez les transactions échouées puisqu'un déploiement échoué ne produit jamais une création en direct :

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

  <Step title="Connectez-vous avec un client sécurisé contre les reconnexions">
    Un traqueur de déploiement est un processus de longue durée, alors traitez les déconnexions comme routinières plutôt qu'exceptionnelles : surveillez la poignée de main initiale, maintenez la connexion en vie sur un filtre silencieux et reconnectez-vous automatiquement à la fermeture.

    ```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>
      Ceci utilise un délai de reconnexion fixe de 3 secondes pour simplifier. Pour un écouteur en production, reculez exponentiellement — voir [Handling Reconnects](/docs/fr/parsed-streams/guides/handling-reconnects).
    </Tip>
  </Step>

  <Step title="Gérer les notifications et enregistrer chaque déploiement">
    Acheminer les messages entrants par `id` (vos propres demandes) ou `method` (notifications poussées par le serveur), puis extraire le mint, le créateur et les métadonnées de l'instruction décodée :

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

    Parce que `includeFailed` est `false`, chaque notification que vous enregistrez est un jeton qui a effectivement été déployé. Vérifiez que `ix.decoded` est présent avant de faire confiance à `args` et `accounts` — une version non reconnue du programme Pump.fun arrive avec `decoded: null` et apparaîtrait autrement comme `mint: null`.
  </Step>
</Steps>

## Prochaines étapes

<CardGroup cols={2}>
  <Card title="Suivre les échanges Jupiter" icon="arrow-right-arrow-left" href="/docs/fr/parsed-streams/guides/track-jupiter-swaps">
    Le flux décrireProgramme → construire le filtre → s'abonner en détail.
  </Card>

  <Card title="Gérer les reconnexions" icon="rotate" href="/docs/fr/parsed-streams/guides/handling-reconnects">
    Recul exponentiel et remplissage des écarts de slots pour les écouteurs de longue durée.
  </Card>

  <Card title="Récupérer les créations Pump.fun" icon="clock-rotate-left" href="/docs/fr/parsed-events/guides/fetch-pumpfun-mints">
    La version historique : parcourez les déploiements passés d'un créateur avec Parsed Events.
  </Card>
</CardGroup>
