> ## 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 Swap Jupiter dengan Parsed Streams

> Buat dan berlangganan ke filter Parsed Streams untuk instruksi rute Jupiter menggunakan describeProgram.

Panduan ini membuat filter nyata langkah demi langkah: memantau swap Jupiter milik sebuah dompet, menggunakan [penemuan program](/docs/id/parsed-streams/quickstart#penemuan) agar filter sudah benar sebelum Anda membuka langganan.

<Steps>
  <Step title="Look Up the Program">
    Nama instruksi yang ditebak adalah penyebab paling umum filter tidak menemukan kecocokan tanpa memberikan indikasi apa pun. Panggil `describeProgram` terlebih dahulu untuk mendapatkan nama persis yang dibandingkan oleh pencocok. Saat ini, metode tersebut hanya tersedia di `wss://fs-beta.helius-rpc.com/?api-key=<API_KEY>`, jadi kirimkan ke sana, bukan melalui koneksi langganan Anda.

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

    ```json Response theme={"system"}
    {
      "jsonrpc": "2.0", "id": 1,
      "result": {
        "id": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
        "name": "jupiter",
        "instructions": ["route", "shared_accounts_route", "exact_out_route"],
        "events": ["SwapEvent"],
        "roles": ["user_transfer_authority", "destination_token_account"]
      }
    }
    ```

    Utamakan **alamat** program daripada nama katalog — lebih dari satu entri katalog dapat memiliki nama yang sama, dan pencarian berdasarkan nama dapat mengarah ke versi program yang lebih lama. `route` dan `shared_accounts_route` adalah dua instruksi yang mencakup sebagian besar swap Jupiter v6, jadi gunakan keduanya dalam filter.
  </Step>

  <Step title="Build the Filter">
    Gabungkan ID program, nama instruksi dari langkah sebelumnya, dan dompet yang Anda pantau. Bidang digabungkan dengan AND, sehingga filter ini mencocokkan instruksi rute yang menyentuh akun SOL milik dompet tersebut:

    ```json theme={"system"}
    {
      "programs": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
      "instructionNames": ["route", "shared_accounts_route"],
      "accounts": {
        "include": ["So11111111111111111111111111111111111111112"],
        "roles": { "user_transfer_authority": "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin" }
      },
      "includeFailed": false,
      "includeCpi": true
    }
    ```

    `accounts.roles` menetapkan `user_transfer_authority` ke posisi persis dompet dalam instruksi, sehingga lebih ketat daripada hanya menggunakan `accounts.include`: pencocokan alamat biasa juga akan menangkap dompet yang muncul sebagai akun tidak terkait di bagian lain instruksi. Nama peran harus cocok persis, jadi nama tersebut disalin dari daftar `roles` milik `describeProgram`, bukan ditebak. Biarkan `includeCpi: true` (nilai default) — perpindahan token aktual dalam swap terjadi di instruksi bagian dalam.
  </Step>

  <Step title="Subscribe and Handle Notifications">
    Buka langganan dengan filter tersebut, lalu baca argumen terdekode dari setiap instruksi yang cocok:

    ```typescript theme={"system"}
    import WebSocket from "ws";

    const ws = new WebSocket("wss://beta.helius-rpc.com/?api-key=<API_KEY>");

    const filter = {
      programs: ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
      instructionNames: ["route", "shared_accounts_route"],
      accounts: {
        include: ["So11111111111111111111111111111111111111112"],
        roles: { user_transfer_authority: "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin" },
      },
      includeFailed: false,
      includeCpi: true,
    };

    ws.on("open", () => {
      ws.send(JSON.stringify({
        jsonrpc: "2.0",
        id: 1,
        method: "parsedTransactionSubscribe",
        params: [filter, { commitment: "confirmed", details: "full" }],
      }));
    });

    ws.on("message", (data) => {
      const msg = JSON.parse(data.toString());
      if (msg.method === "parsedTransactionNotification") {
        const { transaction, instructions, matchedIndexes } = msg.params.result.value;
        for (const i of matchedIndexes) {
          const ix = instructions[i];
          if (!ix.decoded) continue;
          console.log(transaction.signature, ix.decoded.args.in_amount, ix.decoded.args.slippage_bps);
        }
      }
    });
    ```

    `matchedIndexes` hanya menunjuk ke instruksi yang cocok dengan filter Anda — abaikan semua instruksi lain dalam transaksi. Pastikan `decoded` tersedia sebelum membacanya: instruksi rute dari versi program yang belum diindeks akan diterima dengan `decoded: null` dan bidang mentah sebagai gantinya.
  </Step>
</Steps>

## Langkah Berikutnya

<CardGroup cols={2}>
  <Card title="Filter Fields Reference" icon="filter" href="/docs/id/parsed-streams/quickstart#kolom-filter">
    Semua bidang filter, opsi, dan batasan.
  </Card>

  <Card title="Handling Reconnects" icon="rotate" href="/docs/id/parsed-streams/guides/handling-reconnects">
    Pertahankan langganan ini agar tetap aktif saat koneksi terputus dan selama penerapan.
  </Card>
</CardGroup>
