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

# Lacak Mint Token Pump.fun dengan Parsed Streams

> Berlangganan instruksi create Pump.fun dengan Helius Parsed Streams dan buat listener Solana yang aman saat tersambung kembali untuk mencatat setiap mint token baru dan kreatornya.

Panduan ini membuat listener jangka panjang untuk **setiap token Pump.fun baru**. Listener ini memfilter dua instruksi yang digunakan Pump.fun untuk meluncurkan token dan tetap terhubung saat terjadi batas waktu karena tidak aktif maupun deployment.

<Steps>
  <Step title="Look Up the Program">
    Pump.fun meluncurkan token melalui dua instruksi, tergantung versinya: `create` dan `create_v2`. Konfirmasikan nama persis dan peran akun dengan [`describeProgram`](/docs/id/parsed-streams/quickstart#penemuan) sebelum memfilternya. Saat ini, fitur tersebut hanya tersedia di `wss://fs-beta.helius-rpc.com/?api-key=<API_KEY>`:

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

    Periksa daftar `instructions` dalam respons untuk menemukan `create` dan `create_v2`, serta daftar `roles` untuk akun yang Anda inginkan — biasanya alamat **mint** baru, serta peran akun `creator` atau bidang `creator` di `args`. Kedua versi instruksi tidak selalu memiliki struktur yang sama. Karena itu, kode di bawah memeriksa argumen dan beberapa nama peran, bukan mengasumsikan satu struktur tertentu.
  </Step>

  <Step title="Build the Filter">
    Filter berdasarkan program dan kedua nama instruksi. Biarkan `includeCpi` tetap aktif — `create`/`create_v2` milik Pump.fun biasanya berada di tingkat teratas, tetapi langkah ini merupakan perlindungan tambahan yang ringan — dan kecualikan transaksi yang gagal karena deployment yang gagal tidak pernah menghasilkan mint aktif:

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

  <Step title="Connect with a Reconnect-Safe Client">
    Pelacak deployment adalah proses jangka panjang. Karena itu, perlakukan pemutusan koneksi sebagai kejadian rutin, bukan pengecualian: pantau handshake awal dengan watchdog, pertahankan koneksi saat filter tidak menerima aktivitas, dan sambungkan kembali secara otomatis ketika koneksi ditutup.

    ```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>
      Contoh ini menggunakan jeda penyambungan kembali tetap selama 3 detik agar sederhana. Untuk listener produksi, gunakan backoff eksponensial — lihat [Menangani Penyambungan Kembali](/docs/id/parsed-streams/guides/handling-reconnects).
    </Tip>
  </Step>

  <Step title="Handle Notifications and Log Each Deploy">
    Arahkan pesan masuk berdasarkan `id` (permintaan Anda sendiri) atau `method` (notifikasi yang dikirim server), lalu ambil mint, kreator, dan metadata dari instruksi yang telah didekode:

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

    Karena `includeFailed` adalah `false`, setiap notifikasi yang Anda catat merupakan token yang benar-benar berhasil diluncurkan. Pastikan `ix.decoded` tersedia sebelum mempercayai `args` dan `accounts` — build program Pump.fun yang tidak dikenali akan diterima dengan `decoded: null` dan jika tidak diperiksa akan muncul sebagai `mint: null`.
  </Step>
</Steps>

## Langkah Berikutnya

<CardGroup cols={2}>
  <Card title="Track Jupiter Swaps" icon="arrow-right-arrow-left" href="/docs/id/parsed-streams/guides/track-jupiter-swaps">
    Alur describeProgram → buat filter → berlangganan secara lebih mendetail.
  </Card>

  <Card title="Handling Reconnects" icon="rotate" href="/docs/id/parsed-streams/guides/handling-reconnects">
    Backoff eksponensial dan pengisian ulang celah slot untuk listener jangka panjang.
  </Card>

  <Card title="Fetch Pump.fun Mints" icon="clock-rotate-left" href="/docs/id/parsed-events/guides/fetch-pumpfun-mints">
    Versi historis: telusuri deployment lama milik seorang kreator per halaman dengan Parsed Events.
  </Card>
</CardGroup>
