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

# Parsed Streamsを使用してPump.funトークンミントを追跡する

> Parsed Streamsを使用してPump.funのcreateおよびcreate_v2命令を購読し、すべての新しいトークンミント、クリエイター、名前、シンボル、URIをログに記録する再接続安全なリスナーを構築します。

このガイドでは、**すべての新しいPump.funトークン**のための長期実行リスナーを構築します。これはトークンを起動するためにPump.funが使用する2つの命令をフィルタリングし、アイドルタイムアウトやデプロイを越えて接続を維持します。

<Steps>
  <Step title="プログラムを調べる">
    Pump.funはバージョンに応じて2つの命令を通じてトークンを起動します: `create` と `create_v2`。これらをフィルタリングする前に、正確な名前とアカウントの役割を[`describeProgram`](/docs/ja/parsed-streams/quickstart#discovery)で確認してください:

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

    レスポンスの`instructions`リストで`create`と`create_v2`、および必要なアカウント—通常は新しい**ミント**アドレス、または`creator`アカウント役または`creator`フィールドを`args`で確認します。2つの命令バージョンは必ずしも形状を共有しているわけではないため、以下のコードは1つを仮定するのではなく、引数やいくつかの役割名をチェックしています。
  </Step>

  <Step title="フィルタの構築">
    プログラムと両方の命令名でフィルタリングします。`includeCpi`をオンにしておきます—Pump.funの`create`/`create_v2`は通常トップレベルですが、これは安価な保険です—失敗したトランザクションはライブミントを生成しないため失敗したデプロイを除外します。

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

  <Step title="再接続安全なクライアントで接続する">
    デプロイトラッカーは長期実行プロセスですので、切断を例外ではなくルーチンとして扱いましょう: 初期ハンドシェイクを監視し、静かなフィルタで接続を維持し、終了時には自動で再接続します。

    ```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://<ENDPOINT>/?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>
      これは単純化のために固定3秒の再接続遅延を使用しています。プロダクションリスナーには指数的バックオフを使用してください—[再接続の処理](/docs/ja/parsed-streams/guides/handling-reconnects)を参照してください。
    </Tip>
  </Step>

  <Step title="通知を処理し各デプロイをログする">
    受信メッセージを`id`（自身のリクエスト）または`method`（サーバープッシュ通知）でルーティングし、デコードされた命令からミント、クリエイター、メタデータを取得します:

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

    `includeFailed` が `false` であるため、ログに記録されるすべての通知は実際にデプロイされたトークンです。`ix.decoded` が存在することを確認してから、`args` と `accounts` を信頼してください。Pump.fun プログラムの未認識のビルドが `decoded: null` で到着すると、`mint: null` として表示されます。
  </Step>
</Steps>

## 次のステップ

<CardGroup cols={2}>
  <Card title="Jupiter スワップを追跡" icon="arrow-right-arrow-left" href="/docs/ja/parsed-streams/guides/track-jupiter-swaps">
    describeProgram → build フィルター → 詳細なフローに subscribe。
  </Card>

  <Card title="再接続の処理" icon="rotate" href="/docs/ja/parsed-streams/guides/handling-reconnects">
    長時間稼働するリスナーのための指数バックオフとスロットギャップバックフィル。
  </Card>

  <Card title="Pump.fun ミントを取得" icon="clock-rotate-left" href="/docs/ja/parsed-events/guides/fetch-pumpfun-mints">
    履歴バージョン: クリエイターの過去のデプロイを Parsed Events でページング。
  </Card>
</CardGroup>
