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

# 파싱된 스트림으로 Jupiter 스왑 추적

> describeProgram을 사용하여 Jupiter 경로 지침에 대한 파싱된 스트림 필터를 구축하고 구독합니다.

이 가이드는 실제 필터를 단계별로 구축합니다: 구독을 열기 전에 필터가 올바르도록 [프로그램 검색](/docs/ko/parsed-streams/quickstart#디스커버리)를 사용하여 지갑의 Jupiter 스왑을 감시합니다.

<Steps>
  <Step title="프로그램 조회">
    추측된 지침 이름은 필터가 아무 것도 일치시키지 못하는 가장 흔한 방법입니다. 비교할 정확한 이름을 얻으려면 먼저 `describeProgram`를 호출하세요.

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

    카탈로그 이름보다 프로그램 **주소**를 선호하세요 — 하나의 이름을 공유하는 여러 카탈로그 항목이 있을 수 있으며, 이름 조회는 프로그램의 오래된 버전으로 해결될 수 있습니다. `route`와 `shared_accounts_route`는 대부분의 Jupiter v6 스왑을 포함하는 두 개의 지침이므로, 여기에 필터링할 것입니다.
  </Step>

  <Step title="필터 생성">
    프로그램 ID, 이전 단계의 지침 이름 및 감시 중인 지갑을 결합합니다. 필드는 AND로 결합되므로, 지갑의 SOL 계정을 사용하는 경로 지침과 일치합니다:

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

    `accounts.roles`는 `user_transfer_authority`를 지갑의 정확한 위치에 고정하여, `accounts.include` 단독보다 엄격합니다: 일반 주소 일치는 지침의 다른 곳에서 관련 없는 계정으로 표시되는 지갑도 잡아냅니다. 역할 이름은 정확하게 일치하므로 추측하지 않고 `describeProgram`의 `roles` 목록에서 복사됩니다. `includeCpi: true` (기본값)를 그대로 둡니다 — 스왑의 실제 토큰 이동은 내부 지침에서 발생합니다.
  </Step>

  <Step title="구독 및 알림 처리">
    필터를 사용하여 구독을 열고, 각 일치하는 지침의 디코딩된 인수를 읽습니다:

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

    const ws = new WebSocket("wss://<ENDPOINT>/?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`는 필터에 일치한 지침을 가리킵니다 — 트랜잭션에서 나머지는 모두 건너뜁니다. 읽기 전에 `decoded`가 있는지 확인하세요: 인덱싱되지 않은 프로그램 버전의 경로 지침은 `decoded: null` 및 원시 필드와 함께 도착합니다.
  </Step>
</Steps>

## 다음 단계

<CardGroup cols={2}>
  <Card title="필터 필드 참조" icon="filter" href="/docs/ko/parsed-streams/quickstart#필터-필드">
    모든 필터 필드, 옵션 및 제한입니다.
  </Card>

  <Card title="다시 연결 처리" icon="rotate" href="/docs/ko/parsed-streams/guides/handling-reconnects">
    연결 해제 및 배포 중에도 이 구독을 유지하세요.
  </Card>
</CardGroup>
