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

# parsedTransactionSubscribe

> Berlangganan transaksi Solana terdekode yang cocok dengan filter berdasarkan program, akun, dan nama instruksi. Terima transaksi lengkap dengan argumen dan akun bernama.

Mulai langganan. Setiap transaksi terkonfirmasi yang cocok dengan filter Anda akan diterima sebagai `parsedTransactionNotification` dan sudah didekode: setiap instruksi dengan argumen dan akun bernama, beserta biaya, daftar lengkap kunci akun, `summary` tingkat transaksi, serta transfer SOL dan token.

## Endpoint

Parsed Streams tersedia pada semua paket dan disajikan melalui endpoint [Gatekeeper](/docs/id/gatekeeper/overview), menggunakan host yang sama dengan lalu lintas Helius RPC dan WebSocket:

* `wss://beta.helius-rpc.com/?api-key=<API_KEY>`

## Otorisasi

<ParamField query="api-key" type="string" required>
  Kunci API Helius Anda, yang diteruskan sebagai parameter kueri `api-key` atau header `x-api-key`. Kunci yang tidak ada atau tidak valid akan ditolak dengan HTTP 401.
</ParamField>

## Isi

<ParamField body="params" type="array" required>
  <Expandable title="Filter" defaultOpen>
    Setidaknya salah satu dari `programs` atau `accounts.include` wajib diisi. Bidang yang Anda tetapkan digabungkan dengan **AND**: instruksi harus memenuhi semuanya agar cocok.

    <ParamField body="programs" type="string[]">
      ID program yang akan dicocokkan (alamat base58, bukan nama). Instruksi cocok jika programnya ada dalam daftar ini. OR di dalam daftar.
    </ParamField>

    <ParamField body="instructionNames" type="string[]">
      Nama instruksi terdekode, seperti `route`. Nama akan dicocokkan secara persis terlebih dahulu, lalu menggunakan pencocokan cadangan yang tidak peka terhadap huruf besar-kecil dan pemisah. Karena itu, `sharedAccountsRoute` juga cocok dengan nama wire `shared_accounts_route`. OR di dalam daftar. Hanya instruksi yang namanya dapat diidentifikasi oleh katalog yang bisa cocok, jadi gunakan nama dari [describeProgram](/docs/id/api-reference/parsed-streams/describeprogram).
    </ParamField>

    <ParamField body="accounts.include" type="string[]">
      Alamat akun. Instruksi cocok jika salah satu alamat ini muncul dalam daftar akunnya. OR di dalam daftar. Berlaku untuk setiap instruksi, baik terdekode maupun tidak. ID program itu sendiri tidak dihitung sebagai akun di sini.
    </ParamField>

    <ParamField body="accounts.roles" type="object">
      Pemetaan nama peran akun terdekode ke alamat, seperti `{ "user_transfer_authority": "<pubkey>" }`. Setiap entri harus terpenuhi (AND antarentri), dan instruksi harus didekode agar ketentuan ini dapat diterapkan. Nama peran dicocokkan **secara persis**, tanpa penyeragaman huruf besar-kecil. Karena itu, salin nama dari [describeProgram](/docs/id/api-reference/parsed-streams/describeprogram), bukan menebaknya.
    </ParamField>

    <ParamField body="includeFailed" type="boolean" default="false">
      Sertakan instruksi dari transaksi yang gagal.
    </ParamField>

    <ParamField body="includeCpi" type="boolean" default="true">
      Instruksi internal (CPI) dapat dicocokkan. Tetapkan `false` agar hanya mencocokkan instruksi tingkat atas.
    </ParamField>
  </Expandable>

  <Expandable title="Options">
    Parameter kedua bersifat opsional.

    <ParamField body="commitment" type="string" default="confirmed">
      Hanya `confirmed` yang didukung.
    </ParamField>

    <ParamField body="details" type="string" default="full">
      Menentukan isi setiap notifikasi. `full`: seluruh transaksi, setiap instruksi, serta `matchedIndexes` yang menunjuk ke hasil yang cocok dengan filter. `matched`: hanya instruksi yang cocok, tanpa daftar indeks. `raw`: hanya instruksi yang cocok, masing-masing disederhanakan menjadi posisinya, `programId`, dan blob `data` base58, tanpa bidang terdekode dan tanpa array `accountKeys`. Gunakan `matched` jika bandwidth lebih penting daripada konteks (ukuran payload lengkap rata-rata sekitar tiga kali lebih besar), dan `raw` jika Anda mendekode sendiri data instruksi dan hanya memerlukan byte-nya.
    </ParamField>
  </Expandable>
</ParamField>

Bidang yang tidak dikenal di mana pun dalam filter atau opsi akan ditolak dengan `-32602`, bukan diabaikan secara diam-diam. Dengan demikian, kesalahan ketik akan langsung menyebabkan kegagalan, bukan tidak menghasilkan kecocokan apa pun.

## Respons

<ResponseField name="result" type="integer">
  ID langganan (diperlukan untuk berhenti berlangganan)
</ResponseField>

<RequestExample>
  ```json Request theme={"system"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "parsedTransactionSubscribe",
    "params": [
      {
        "programs": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
        "instructionNames": ["route", "shared_accounts_route"],
        "accounts": {
          "include": ["So11111111111111111111111111111111111111112"],
          "roles": { "user_transfer_authority": "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin" }
        },
        "includeFailed": false,
        "includeCpi": true
      },
      { "commitment": "confirmed", "details": "full" }
    ]
  }
  ```

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

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

  ws.on("open", () => {
    ws.send(JSON.stringify({
      jsonrpc: "2.0",
      id: 1,
      method: "parsedTransactionSubscribe",
      params: [{ programs: ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"] }],
    }));
  });

  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 ?? instructions.keys()) {
        const ix = instructions[i];
        console.log(transaction.signature, ix.programName, ix.instructionName, ix.decoded?.args);
      }
    }
  });
  ```

  ```python Python theme={"system"}
  import asyncio, json, websockets

  URL = "wss://beta.helius-rpc.com/?api-key=<API_KEY>"

  async def main():
      async with websockets.connect(URL) as ws:
          await ws.send(json.dumps({
              "jsonrpc": "2.0", "id": 1, "method": "parsedTransactionSubscribe",
              "params": [{"programs": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"]}],
          }))
          async for raw in ws:
              msg = json.loads(raw)
              if msg.get("method") == "parsedTransactionNotification":
                  value = msg["params"]["result"]["value"]
                  for i in value.get("matchedIndexes") or range(len(value["instructions"])):
                      ix = value["instructions"][i]
                      print(ix.get("programName"), ix.get("instructionName"), (ix.get("decoded") or {}).get("args"))

  asyncio.run(main())
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"system"}
  { "jsonrpc": "2.0", "id": 1, "result": 23 }
  ```

  ```json Notification theme={"system"}
  {
    "jsonrpc": "2.0",
    "method": "parsedTransactionNotification",
    "params": {
      "subscription": 23,
      "result": {
        "context": { "slot": 430172053 },
        "value": {
          "transaction": {
            "signature": "3riSYL4HTRxgQjLayt6L2JPaDR3oaEQg1H4v3fnjUxNU...",
            "slot": 430172053,
            "blockTime": null,
            "feePayer": "6jduWNCTQzG91JGBchfGGxd55Vi5FxJCCJEV18RkXzJX",
            "fee": 5000,
            "accountKeys": ["6jduWNCT...", "..."],
            "status": "ok",
            "error": null,
            "summary": {
              "type": "swap",
              "description": "6jduWNCTQzG91JGBchfGGxd55Vi5FxJCCJEV18RkXzJX swapped 0.001 SOL for 0.183985 EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v via Jupiter",
              "parsedData": {
                "type": "swap",
                "protocol": "jupiter",
                "kind": "swap",
                "in_amount": "1000000",
                "actual_out_amount": "183985",
                "input_mint": "So11111111111111111111111111111111111111112",
                "output_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
              }
            },
            "nativeTransfers": [
              { "fromUserAccount": "6jduWNCT...", "toUserAccount": "DfXygSm4...", "amount": 1000000 }
            ],
            "tokenTransfers": [
              {
                "fromUserAccount": "6jduWNCT...",
                "toUserAccount": "AeUfFU6L...",
                "fromTokenAccount": "HLaEoW1s...",
                "toTokenAccount": "G13P9kSY...",
                "rawTokenAmount": 183985,
                "decimals": 6,
                "tokenStandard": "Fungible",
                "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
              }
            ]
          },
          "instructions": [
            {
              "instructionIndex": 4,
              "innerInstructionIndex": null,
              "stackHeight": 1,
              "programId": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
              "programName": "jupiter",
              "instructionName": "route",
              "summary": {
                "type": "swap",
                "description": "6jduWNCTQzG91JGBchfGGxd55Vi5FxJCCJEV18RkXzJX swapped 0.001 SOL for 0.183985 EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v via Jupiter",
                "parsedData": {
                  "type": "swap",
                  "protocol": "jupiter",
                  "kind": "swap",
                  "in_amount": "1000000",
                  "actual_out_amount": "183985",
                  "input_mint": "So11111111111111111111111111111111111111112",
                  "output_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                }
              },
              "decoded": {
                "args": { "in_amount": "1000000", "slippage_bps": 50 },
                "accounts": [
                  { "name": "user_transfer_authority", "pubkey": "9xQe...", "isSigner": true, "isWritable": false }
                ]
              }
            }
          ],
          "matchedIndexes": [8, 13]
        }
      }
    }
  }
  ```
</ResponseExample>

## Notifikasi

Satu notifikasi untuk setiap transaksi yang cocok pada setiap langganan. Di dalam `params.result.value`:

* **`transaction`** — konteks lengkap: tanda tangan, slot, biaya (lamport), daftar lengkap `accountKeys`, `status`/`error`, `summary` tingkat transaksi, serta `nativeTransfers` dan `tokenTransfers` yang diekstrak.
* **`instructions`** — setiap instruksi dalam urutan eksekusi, yang posisinya ditentukan oleh `instructionIndex`, `innerInstructionIndex`, dan `stackHeight`. Instruksi terdekode memuat `decoded.args` dan `decoded.accounts` bernama (snake\_case, nilai u64 sebagai string); instruksi yang tidak didekode memuat `rawData` dan `rawAccounts` sebagai gantinya.
* **`matchedIndexes`** — indeks ke dalam `instructions` yang menunjukkan instruksi mana yang benar-benar cocok dengan filter Anda. Dengan `details: "matched"`, array hanya berisi hasil yang cocok dan `matchedIndexes` tidak disertakan; dengan `details: "raw"`, setiap instruksi yang cocok disederhanakan menjadi posisinya, `programId`, dan blob `data` base58.

Untuk penjelasan setiap bidang dalam payload notifikasi, lihat [referensi protokol panduan memulai](/docs/id/parsed-streams/quickstart#notifikasi).

## Mengelola Langganan

`result` dari respons langganan adalah angka yang sama dengan yang muncul dalam `params.subscription` pada setiap notifikasi dari langganan tersebut. Simpan angka ini — Anda memerlukannya untuk [berhenti berlangganan](/docs/id/api-reference/parsed-streams/parsedtransactionunsubscribe).

Satu proyek dapat memiliki hingga **5 koneksi bersamaan** pada paket Free, **10** pada Developer, serta **50** pada Business dan Professional. Batas ini digunakan bersama oleh semua kunci API proyek, dengan maksimum **25 langganan per koneksi**. Lihat [ringkasan](/docs/id/api-reference/parsed-streams/overview#batas) untuk semua batas.
