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

> 프로그램, 계정, 명령어 이름으로 필터링된 디코딩된 Solana 트랜잭션 구독. 이름이 지정된 인수와 계정으로 전체 트랜잭션 수신.

구독을 시작합니다. 필터에 맞는 모든 확인된 트랜잭션은 이미 디코딩된 상태로 `parsedTransactionNotification`로 도착합니다. 이름이 지정된 인수와 계정이 있는 모든 명령어, 수수료, 전체 계정 키 목록, 트랜잭션 수준의 `summary`, 그리고 SOL 및 토큰 전송이 포함됩니다.

## Endpoints

Parsed Streams는 클로즈드 베타에 있습니다. Helius 팀이 프로젝트 ID를 허용 목록에 추가하고 접속 엔드포인트를 공유합니다:

* `wss://<ENDPOINT>/?api-key=<API_KEY>`

## Authorizations

<ParamField query="api-key" type="string" required>
  Helius API 키, `api-key` 쿼리 매개변수 또는 `x-api-key` 헤더로 전달됩니다. 누락되거나 잘못된 키 또는 허용 목록에 없는 키는 HTTP 401로 거부됩니다.
</ParamField>

## Body

<ParamField body="params" type="array" required>
  <Expandable title="Filter" defaultOpen>
    `programs` 또는 `accounts.include` 둘 중 하나는 필수입니다. 설정한 필드는 **AND**로 결합됩니다: 명령어는 모두 충족해야 매치됩니다.

    <ParamField body="programs" type="string[]">
      프로그램 ID 매칭(기본 58 주소, 이름 아님). 명령어의 프로그램이 이 목록에 있으면 매칭됩니다. 목록 내에서 OR 됩니다.
    </ParamField>

    <ParamField body="instructionNames" type="string[]">
      디코딩된 명령어 이름, 예: `route`. 처음에는 정확히, 그런 다음 케이스 및 구분자에 민감하지 않게 매칭됩니다. 따라서 `sharedAccountsRoute`도 와이어 이름 `shared_accounts_route`에 매칭됩니다. 목록 내에서 OR 됩니다. 카탈로그가 식별할 수 있는 이름의 명령어만 일치하므로 [describeProgram](/docs/ko/api-reference/parsed-streams/describeprogram)에서 이름을 가져오십시오.
    </ParamField>

    <ParamField body="accounts.include" type="string[]">
      계정 주소. 이들 중 하나가 해당 명령어의 계정 목록에 나타나면 명령어가 매칭됩니다. 목록 내에서 OR 됩니다. 디코딩 여부에 관계없이 모든 명령어에 작동합니다. 프로그램 ID 자체는 여기서 계정으로 간주되지 않습니다.
    </ParamField>

    <ParamField body="accounts.roles" type="object">
      디코딩된 계정 역할 이름에 대한 주소 맵, 예: `{ "user_transfer_authority": "<pubkey>" }`. 각 항목은 유지되어야 하며(항목 간 AND), 명령어가 이에 적용되려면 디코딩되어야 합니다. 역할 이름은 케이스 폴딩 없이 **정확히** 매칭되므로 추측하지 말고 [describeProgram](/docs/ko/api-reference/parsed-streams/describeprogram)에서 복사하십시오.
    </ParamField>

    <ParamField body="includeFailed" type="boolean" default="false">
      실패한 트랜잭션의 명령어 포함.
    </ParamField>

    <ParamField body="includeCpi" type="boolean" default="true">
      내부 (CPI) 명령어가 매칭될 수 있습니다. 상위 수준의 명령어만 매칭하려면 `false`을 설정하십시오.
    </ParamField>
  </Expandable>

  <Expandable title="Options">
    두 번째 매개변수는 선택 사항입니다.

    <ParamField body="commitment" type="string" default="confirmed">
      `confirmed`만 지원됩니다.
    </ParamField>

    <ParamField body="details" type="string" default="full">
      각 알림에 포함되는 내용. `full`: 전체 트랜잭션, 모든 명령어, 필터 히트를 가리키는 `matchedIndexes` 포함. `matched`: 매칭된 명령어만, 인덱스 목록 없음. `raw`: 매칭된 명령어만, 위치, `programId`, 기본 58 `data` 블랍으로 축소, 디코딩된 필드와 `accountKeys` 배열 없음. 대역폭이 컨텍스트보다 중요할 때 `matched` 사용 (전체 페이로드는 평균적으로 3배 크기), 명령 데이터만 필요할 때 `raw` 사용.
    </ParamField>
  </Expandable>
</ParamField>

필터 또는 옵션에서 알 수 없는 필드는 무시되지 않고 `-32602`로 거부되므로, 오타는 아무 것도 매칭되지 않기보다는 명확하게 실패합니다.

## Response

<ResponseField name="result" type="integer">
  구독 ID (구독 해지를 위해 필요)
</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://<ENDPOINT>/?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://<ENDPOINT>/?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": [
            {
              "topIndex": 4,
              "innerIndex": 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>

## Notifications

구독당 일치하는 트랜잭션당 하나의 알림. `params.result.value` 내부:

* **`transaction`** — 전체 컨텍스트: 서명, 슬롯, 수수료(lamports), 전체 `accountKeys` 목록, `status`/`error`, 트랜잭션 수준의 `summary` 및 추출된 `nativeTransfers` 및 `tokenTransfers`.
* **`instructions`** — 실행 순서대로 각 명령어, `topIndex`, `innerIndex`, `stackHeight`에 의해 위치 지정됨. 디코딩된 명령어는 이름이 지정된 `decoded.args` 및 `decoded.accounts` 포함 (스네이크 케이스, u64 값은 문자열로); 디코딩되지 않은 것은 `rawData` 및 `rawAccounts` 포함.
* **`matchedIndexes`** — 필터에 실제로 일치한 명령어를 알려주는 `instructions`로의 색인. `details: "matched"`와 함께 배열에는 히트만 포함되며 `matchedIndexes`는 없습니다; `details: "raw"`와 함께 각각의 매칭된 명령어는 위치, `programId` 및 기본 58 `data` 블랍으로 축소됩니다.

알림 페이로드에 대한 필드별 읽기는 [빠른 시작 프로토콜 참조](/docs/ko/parsed-streams/quickstart#알림)를 참조하십시오.

## Managing Subscriptions

구독 응답의 `result`는 해당 구독에서 모든 알림에 나타나는 `params.subscription`와 동일한 숫자입니다. 저장하십시오 — [구독 해지](/docs/ko/api-reference/parsed-streams/parsedtransactionunsubscribe)에 필요합니다.

프로젝트는 최대 **100개의 동시 연결**을 보유할 수 있으며, 이는 모든 API 키에 걸쳐 공유되며, 연결당 최대 **25개의 구독**을 가집니다. 모든 제한 사항은 [개요](/docs/ko/api-reference/parsed-streams/overview#제한)를 참조하십시오.
