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

# Bắt đầu nhanh với Parsed Streams

> Kết nối với Parsed Streams, gửi bộ lọc đầu tiên và đọc thông báo đã giải mã. Kèm theo tài liệu tham khảo đầy đủ về giao thức JSON-RPC 2.0.

<Tip>
  Bạn mới làm quen với Parsed Streams? Hãy đọc [mô hình tư duy](/docs/vi/parsed-streams#mô-hình-tư-duy) trước — phần này giải thích lý do các bộ lọc có cấu trúc như vậy.
</Tip>

## Bắt đầu nhanh

<Steps>
  <Step title="Get Access">
    Parsed Streams có sẵn trong tất cả các gói với mức phí 1 credit cho mỗi sự kiện được phân phối. Lấy khóa API từ [Helius Dashboard](https://dashboard.helius.dev) và kết nối với điểm cuối [Gatekeeper](/docs/vi/gatekeeper/overview) tại `wss://beta.helius-rpc.com`, cùng máy chủ với lưu lượng RPC và WebSocket của Helius.

    Xác thực bằng khóa API của dự án, được truyền dưới dạng tham số truy vấn `api-key` (hoặc tiêu đề `x-api-key`).
  </Step>

  <Step title="Connect">
    ```bash wscat theme={"system"}
    wscat -c "wss://beta.helius-rpc.com/?api-key=YOUR_API_KEY"
    ```

    Khóa bị thiếu hoặc không hợp lệ sẽ bị từ chối với HTTP 401. Dự án đã đạt giới hạn kết nối sẽ nhận HTTP 429.
  </Step>

  <Step title="Subscribe with a Filter">
    Gửi `parsedTransactionSubscribe` cùng một bộ lọc và các tùy chọn không bắt buộc:

    ```json theme={"system"}
    {"jsonrpc":"2.0","id":1,"method":"parsedTransactionSubscribe","params":[{"programs":["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"]}]}
    ```

    `result` trong phản hồi là một **ID đăng ký** dạng số nguyên:

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

  <Step title="Read a Notification">
    Mỗi giao dịch khớp sẽ đến dưới dạng `parsedTransactionNotification`, đã được giải mã, với `matchedIndexes` trỏ đến các lệnh mà bộ lọc của bạn khớp. Xem [Thông báo](#thông-báo) để biết cấu trúc đầy đủ.
  </Step>

  <Step title="Unsubscribe">
    ```json theme={"system"}
    { "jsonrpc": "2.0", "id": 2, "method": "parsedTransactionUnsubscribe", "params": [23] }
    ```

    Hoặc chỉ cần đóng kết nối — thao tác này sẽ xóa tất cả đăng ký của kết nối đó.
  </Step>
</Steps>

## Hướng dẫn

<CardGroup cols={2}>
  <Card title="Track Jupiter Swaps" icon="arrow-right-arrow-left" href="/docs/vi/parsed-streams/guides/track-jupiter-swaps">
    Sử dụng `describeProgram` để tạo một bộ lọc đáng tin cậy trước khi đăng ký.
  </Card>

  <Card title="Track Pump.fun Mints" icon="rocket" href="/docs/vi/parsed-streams/guides/track-pumpfun-mints">
    Một trình lắng nghe an toàn khi kết nối lại, ghi nhật ký mọi lần triển khai token Pump.fun mới.
  </Card>

  <Card title="Handling Reconnects" icon="rotate" href="/docs/vi/parsed-streams/guides/handling-reconnects">
    Duy trì hoạt động qua các lần hết thời gian chờ khi không hoạt động và triển khai, sau đó bổ sung chính xác những gì đã bỏ lỡ.
  </Card>
</CardGroup>

## Tài liệu tham khảo giao thức

Parsed Streams sử dụng **JSON-RPC 2.0** qua một kết nối WebSocket duy nhất. Mỗi yêu cầu nhận được một phản hồi có cùng `id`. Sau đó, một đăng ký sẽ đẩy các thông báo `parsedTransactionNotification` cho đến khi bạn hủy đăng ký hoặc ngắt kết nối.

| Phương thức                    | Mục đích                                                            |
| ------------------------------ | ------------------------------------------------------------------- |
| `parsedTransactionSubscribe`   | Bắt đầu đăng ký bằng một bộ lọc                                     |
| `parsedTransactionUnsubscribe` | Dừng đăng ký                                                        |
| `describeProgram`              | Liệt kê các lệnh, sự kiện và vai trò tài khoản của một chương trình |

### Đăng ký

Gửi `parsedTransactionSubscribe` cùng một bộ lọc và các tùy chọn không bắt buộc. `result` trong phản hồi là một **ID đăng ký** dạng số nguyên.

```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" }
  ]
}
```

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

#### Các trường của bộ lọc

Bắt buộc phải có ít nhất một trong hai trường `programs` hoặc `accounts.include`. Các trường bạn đặt được kết hợp bằng phép **AND**: một lệnh phải đáp ứng tất cả các trường đó mới khớp.

<ParamField body="programs" type="string[]">
  Các ID chương trình cần khớp (địa chỉ base58, không phải tên). Một lệnh khớp nếu chương trình của lệnh nằm trong danh sách này. Các mục trong danh sách được kết hợp bằng OR.
</ParamField>

<ParamField body="instructionNames" type="string[]">
  Tên lệnh đã giải mã, chẳng hạn như `route`. Trước tiên hệ thống so khớp chính xác, sau đó dùng phương án dự phòng không phân biệt chữ hoa chữ thường và dấu phân cách, vì vậy `sharedAccountsRoute` cũng khớp với tên trên dây `shared_accounts_route`. Các mục trong danh sách được kết hợp bằng OR. Chỉ các lệnh có tên mà danh mục nhận diện được mới có thể khớp, vì vậy hãy lấy tên từ `describeProgram`.
</ParamField>

<ParamField body="accounts.include" type="string[]">
  Địa chỉ tài khoản. Một lệnh khớp nếu bất kỳ địa chỉ nào trong số này xuất hiện trong danh sách tài khoản của lệnh. Các mục trong danh sách được kết hợp bằng OR. Hoạt động với mọi lệnh, dù đã giải mã hay chưa. Bản thân ID chương trình không được tính là tài khoản ở đây.
</ParamField>

<ParamField body="accounts.roles" type="object">
  Ánh xạ từ tên vai trò tài khoản đã giải mã đến địa chỉ, chẳng hạn như `{ "user_transfer_authority": "<pubkey>" }`. Mọi mục đều phải thỏa mãn (AND giữa các mục) và lệnh phải được giải mã thì điều kiện này mới áp dụng. Tên vai trò được so khớp **chính xác**, không chuyển đổi chữ hoa chữ thường, vì vậy hãy sao chép chúng từ `describeProgram` thay vì phỏng đoán.
</ParamField>

<ParamField body="includeFailed" type="boolean" default="false">
  Bao gồm các lệnh từ giao dịch thất bại.
</ParamField>

<ParamField body="includeCpi" type="boolean" default="true">
  Các lệnh bên trong (CPI) đủ điều kiện để khớp. Đặt `false` để chỉ khớp các lệnh cấp cao nhất.
</ParamField>

Các trường không xác định ở bất kỳ đâu trong bộ lọc hoặc tùy chọn đều bị từ chối với `-32602` thay vì bị âm thầm bỏ qua, do đó lỗi chính tả sẽ gây lỗi rõ ràng thay vì không khớp với bất kỳ thứ gì.

#### Tùy chọn

Tham số thứ hai là không bắt buộc.

<ParamField body="commitment" type="string" default="confirmed">
  Chỉ hỗ trợ `confirmed`.
</ParamField>

<ParamField body="details" type="string" default="full">
  Nội dung của mỗi thông báo. `full`: toàn bộ giao dịch, mọi lệnh, cùng với `matchedIndexes` trỏ đến các kết quả khớp bộ lọc. `matched`: chỉ các lệnh đã khớp, không có danh sách chỉ mục. `raw`: chỉ các lệnh đã khớp, mỗi lệnh được rút gọn thành vị trí, `programId` và blob `data` dạng base58, không có trường đã giải mã và không có mảng `accountKeys`. Sử dụng `matched` khi băng thông quan trọng hơn ngữ cảnh (payload đầy đủ có kích thước trung bình lớn gấp khoảng ba lần) và `raw` khi bạn tự giải mã dữ liệu lệnh và chỉ cần các byte.
</ParamField>

Số kết nối đồng thời cho mỗi dự án phụ thuộc vào gói của bạn: **5** với Free, **10** với Developer và **50** với Business và Professional, dùng chung cho tất cả khóa API của dự án. Xem [Giới hạn tốc độ](/docs/vi/billing/rate-limits#luồng-đã-phân-tích-cú-pháp).

### Thông báo

Mỗi giao dịch khớp sẽ tạo một thông báo cho mỗi đăng ký. Với `details: "full"` mặc định:

```json 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]
      }
    }
  }
}
```

Cách đọc:

* **`transaction`** là ngữ cảnh đầy đủ. `fee` có đơn vị lamport. `accountKeys` là danh sách khóa đầy đủ, bao gồm các khóa được tải từ bảng tra cứu địa chỉ, theo đúng thứ tự mà chuỗi báo cáo. `feePayer` luôn là `accountKeys[0]`. `error` chứa lỗi giao dịch dưới dạng JSON có cấu trúc, ví dụ `{"InstructionError": [2, {"Custom": 6001}]}`, khi `status` là `"error"`.
* **`summary`** có cùng một cấu trúc ở mọi nơi xuất hiện: một `type` (chẳng hạn như `swap` hoặc `transfer`), một `description` dễ đọc và một payload `parsedData` có cấu trúc khi trình phân tích nhận diện được hành động — đối với một giao dịch hoán đổi: giao thức, số lượng và mint. `transaction.summary` gắn nhãn hành động chính của giao dịch; mỗi lệnh được nhận diện đều có `summary` riêng với cùng cấu trúc. Để thu thập mọi giao dịch hoán đổi trong một giao dịch, hãy lặp qua `instructions` và đọc `summary.parsedData` tại nơi `summary.type` là `"swap"`.
* **`nativeTransfers`** và **`tokenTransfers`** liệt kê các chuyển động SOL và token mà trình phân tích trích xuất từ toàn bộ giao dịch, theo cùng cấu trúc mà Parsed Events API trả về, để các trình sử dụng luồng và API có thể dùng chung mã xử lý. Cả hai luôn hiện diện nhưng có thể rỗng.
* **`instructions`** chứa mọi lệnh của giao dịch theo thứ tự thực thi: mỗi lệnh cấp cao nhất được theo sau bởi các lệnh bên trong của lệnh đó. Mỗi mục chứa vị trí riêng: `instructionIndex` cho biết mục đó thuộc lệnh cấp cao nhất nào (bắt đầu từ 0), `innerInstructionIndex` là vị trí của mục trong các lệnh gọi bên trong của lệnh đó (`null` nghĩa là chính lệnh cấp cao nhất) và `stackHeight` là độ sâu lệnh gọi (1 đối với cấp cao nhất). Hãy sử dụng các giá trị này, không dùng vị trí trong mảng.
* **`matchedIndexes`** là các chỉ mục trỏ vào `instructions`, cho biết những lệnh nào thực sự khớp với bộ lọc của bạn. Các lệnh còn lại được cung cấp làm ngữ cảnh. Với `details: "matched"`, mảng chỉ chứa các kết quả khớp và không có `matchedIndexes`.
* **Tên `decoded` sử dụng snake\_case** (`in_amount`, `user_transfer_authority`), như được công bố trong IDL của chương trình. Các đối số số nguyên thường là chuỗi (`"1000000"`) vì các giá trị u64 không vừa với kiểu số của JavaScript.
* **`blockTime`** hiện luôn là `null`. Không xây dựng logic dựa trên trường này.
* Một giao dịch có thể chứa **hỗn hợp lệnh đã giải mã và chưa giải mã**: một giao dịch hoán đổi được giải mã đầy đủ có thể nằm cạnh một memo không được nhận diện. Rẽ nhánh theo `decoded`: khi giá trị này là `null`, lệnh sẽ chứa `rawData` (các byte base58) và `rawAccounts` (danh sách pubkey thuần) thay thế, vì vậy bạn luôn có dữ liệu để xử lý.

Với `details: "raw"`, `value` được thu gọn thành siêu dữ liệu giao dịch và các blob. `accountKeys`, `nativeTransfers`, `tokenTransfers`, `matchedIndexes` và tất cả các trường đã giải mã đều bị loại bỏ (`summary` của giao dịch vẫn được bao gồm); mỗi lệnh đã khớp chỉ gồm vị trí, chương trình và các byte `data` dạng base58, chính xác như cách chúng xuất hiện trên chuỗi (có mặt ngay cả với các lệnh mà danh mục có thể giải mã):

```json theme={"system"}
"value": {
  "transaction": {
    "signature": "3riSYL4HTRxgQjLayt6L2JPaDR3oaEQg1H4v3fnjUxNU...",
    "slot": 430172053,
    "blockTime": null,
    "feePayer": "6jduWNCTQzG91JGBchfGGxd55Vi5FxJCCJEV18RkXzJX",
    "fee": 5000,
    "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"
      }
    }
  },
  "instructions": [
    { "instructionIndex": 4, "innerInstructionIndex": null, "stackHeight": 1, "programId": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4", "data": "3Bxs4h24hBtQy9rw" }
  ]
}
```

### Hủy đăng ký

```json theme={"system"}
{ "jsonrpc": "2.0", "id": 2, "method": "parsedTransactionUnsubscribe", "params": [23] }
```

Trả về `true` nếu đăng ký tồn tại và thuộc về bạn. Thông báo dừng ngay lập tức. Việc đóng kết nối sẽ xóa tất cả đăng ký của kết nối đó.

### Khám phá

Lỗi phổ biến nhất với loại API này là bộ lọc hợp lệ nhưng không khớp với bất kỳ dữ liệu nào, thường do đoán sai tên lệnh hoặc vai trò. `describeProgram` ngăn chặn điều đó bằng cách trả về chính xác các tên mà trình so khớp sử dụng để so sánh. Hiện tại phương thức này chỉ có trên `wss://fs-beta.helius-rpc.com/?api-key=<API_KEY>`, vì vậy hãy gửi qua một kết nối riêng biệt với các đăng ký của bạn:

```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"]
  }
}
```

Bạn có thể truyền địa chỉ chương trình hoặc tên danh mục, nhưng **nên ưu tiên địa chỉ**: tên có thể không rõ ràng giữa các phiên bản chương trình (nhiều mục danh mục có tên `jupiter` và thao tác tra cứu theo tên có thể phân giải thành mục cũ hơn). Nếu tra cứu theo tên, hãy kiểm tra rằng `result.id` là chương trình bạn định đăng ký.

Quy trình đề xuất: dùng `describeProgram` để lấy chính xác tên lệnh và vai trò, tạo bộ lọc bằng các tên đó, rồi đăng ký. Hướng dẫn [Theo dõi các giao dịch hoán đổi Jupiter](/docs/vi/parsed-streams/guides/track-jupiter-swaps) trình bày toàn bộ quy trình từ đầu đến cuối.

### Giới hạn

| Giới hạn                           | Giá trị                                                 |
| ---------------------------------- | ------------------------------------------------------- |
| Số kết nối đồng thời cho mỗi dự án | 5 (Free), 10 (Developer), 50 (Business và Professional) |
| Số đăng ký trên mỗi kết nối        | 25                                                      |
| Thông báo từ máy khách             | 10 mỗi giây, tối đa 20 trong một đợt                    |
| Kích thước thông báo từ máy khách  | 64 KiB                                                  |
| `programs` trên mỗi bộ lọc         | 10                                                      |
| `instructionNames` trên mỗi bộ lọc | 50, mỗi mục tối đa 64 ký tự                             |
| `accounts.include` trên mỗi bộ lọc | 100                                                     |
| `accounts.roles` trên mỗi bộ lọc   | 20, mỗi tên tối đa 64 ký tự                             |
| Bộ đệm gửi đi trên mỗi kết nối     | 2048 thông báo, sau đó kết nối sẽ bị đóng               |

### Lỗi

Các lỗi tuân theo JSON-RPC 2.0: `{ "error": { "code": <int>, "message": "<text>" }, "id": <id> }`. Thông báo cho biết chính xác lỗi là gì và nằm ở đâu.

| Mã       | Ý nghĩa                                                                                                    |
| -------- | ---------------------------------------------------------------------------------------------------------- |
| `-32700` | Lỗi phân tích cú pháp (JSON không hợp lệ)                                                                  |
| `-32600` | Yêu cầu không hợp lệ                                                                                       |
| `-32601` | Không tìm thấy phương thức                                                                                 |
| `-32602` | Tham số không hợp lệ: pubkey sai, trường không xác định, giá trị commitment hoặc details không được hỗ trợ |
| `-32000` | Vượt quá giới hạn bộ lọc                                                                                   |
| `-32001` | Máy chủ chưa sẵn sàng; thử lại với thời gian chờ tăng dần                                                  |
| `-32002` | Bị giới hạn tốc độ (10 thông báo mỗi giây)                                                                 |
| `-32006` | Quá nhiều đăng ký (25 trên mỗi kết nối)                                                                    |

Kết nối cũng có thể đóng với mã đóng WebSocket — xem [Xử lý kết nối lại](/docs/vi/parsed-streams/guides/handling-reconnects) để biết ý nghĩa của từng mã và cách khôi phục.

## Ví dụ máy khách

<CodeGroup>
  ```bash wscat theme={"system"}
  wscat -c "wss://beta.helius-rpc.com/?api-key=<API_KEY>"
  # then send:
  {"jsonrpc":"2.0","id":1,"method":"parsedTransactionSubscribe","params":[{"programs":["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"]}]}
  ```

  ```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())
  ```
</CodeGroup>
