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

> Abonnez-vous aux transactions Solana décodées correspondant à un filtre par programme, compte et nom d'instruction. Recevez des transactions complètes avec des arguments nommés et des comptes.

Commencez un abonnement. Chaque transaction confirmée qui correspond à votre filtre arrive comme un `parsedTransactionNotification`, déjà décodée : chaque instruction avec des arguments nommés et des comptes nommés, plus les frais, la liste complète des clés de comptes, un niveau de transaction `summary`, et les transferts SOL et de jetons.

## Points de Terminaison

Parsed Streams est en bêta ouverte, disponible sur des plans payants. Obtenez votre point de connexion depuis le [Tableau de bord Helius](https://dashboard.helius.dev) :

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

## Autorisations

<ParamField query="api-key" type="string" required>
  Votre clé API Helius, passée en tant que paramètre de requête `api-key` ou dans l'en-tête `x-api-key`. Une clé manquante ou invalide est rejetée avec HTTP 401.
</ParamField>

## Corps

<ParamField body="params" type="array" required>
  <Expandable title="Filtre" defaultOpen>
    Au moins un des éléments `programs` ou `accounts.include` est requis. Les champs que vous définissez se combinent avec **ET** : une instruction doit les satisfaire tous pour correspondre.

    <ParamField body="programs" type="string[]">
      Identifiants de programme à correspondre (adresses base58, pas des noms). Une instruction correspond si son programme figure dans cette liste. OU dans la liste.
    </ParamField>

    <ParamField body="instructionNames" type="string[]">
      Noms d'instructions décodées, tels que `route`. Correspondance exacte d'abord, puis avec une tolérance pour les majuscules/minuscules et les séparateurs, donc `sharedAccountsRoute` correspond aussi au nom filaire `shared_accounts_route`. OU dans la liste. Seules les instructions dont le nom a pu être identifié par le catalogue peuvent correspondre, donc prenez les noms de [describeProgram](/docs/fr/api-reference/parsed-streams/describeprogram).
    </ParamField>

    <ParamField body="accounts.include" type="string[]">
      Adresses de compte. Une instruction correspond si l'une d'elles apparaît dans sa liste de comptes. OU dans la liste. Fonctionne pour chaque instruction, décodée ou non. L'identifiant du programme lui-même ne compte pas comme un compte ici.
    </ParamField>

    <ParamField body="accounts.roles" type="object">
      Une carte du nom de rôle de compte décodé à l'adresse, tel que `{ "user_transfer_authority": "<pubkey>" }`. Chaque entrée doit contenir (ET à travers les entrées), et l'instruction doit être décodée pour que cela s'applique. Les noms de rôle correspondent **exactement**, sans pliage de casse, donc copiez-les depuis [describeProgram](/docs/fr/api-reference/parsed-streams/describeprogram) plutôt que de deviner.
    </ParamField>

    <ParamField body="includeFailed" type="boolean" default="false">
      Inclure les instructions des transactions échouées.
    </ParamField>

    <ParamField body="includeCpi" type="boolean" default="true">
      Les instructions internes (CPI) sont éligibles pour correspondre. Réglez `false` pour correspondre uniquement aux instructions de niveau supérieur.
    </ParamField>
  </Expandable>

  <Expandable title="Options">
    Le second paramètre est optionnel.

    <ParamField body="commitment" type="string" default="confirmed">
      Seul `confirmed` est pris en charge.
    </ParamField>

    <ParamField body="details" type="string" default="full">
      Ce que chaque notification transporte. `full` : la transaction entière, chaque instruction, plus `matchedIndexes` indiquant les correspondances du filtre. `matched` : seulement les instructions qui ont correspondu, pas de liste d'index. `raw` : uniquement les instructions correspondantes, chacune réduite à sa position, `programId`, et un blob base58 `data`, sans champs décodés ni tableau `accountKeys`. Utilisez `matched` lorsque la bande passante compte plus que le contexte (les charges utiles complètes sont environ trois fois plus grandes en moyenne), et `raw` lorsque vous décodez vous-même les données des instructions et que vous n'avez besoin que des octets.
    </ParamField>
  </Expandable>
</ParamField>

Les champs inconnus n'importe où dans le filtre ou les options sont rejetés avec `-32602` plutôt qu'ignorés silencieusement, de sorte que les fautes de frappe échouent bruyamment au lieu de ne rien correspondre.

## Réponse

<ResponseField name="result" type="integer">
  ID d'abonnement (nécessaire pour se désabonner)
</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

Une notification par transaction correspondante par abonnement. À l'intérieur `params.result.value` :

* **`transaction`** — le contexte complet : signature, slot, frais (lamports), la liste complète `accountKeys`, `status`/`error`, un niveau de transaction `summary`, et les `nativeTransfers` et `tokenTransfers` extraits.
* **`instructions`** — chaque instruction dans l'ordre d'exécution, positionnée par `topIndex`, `innerIndex`, et `stackHeight`. Les instructions décodées portent des `decoded.args` et `decoded.accounts` nommés (snake\_case, valeurs u64 comme chaînes) ; celles non décodées portent `rawData` et `rawAccounts` à la place.
* **`matchedIndexes`** — indices dans `instructions` vous indiquant lesquels ont effectivement été touchés par votre filtre. Avec `details: "matched"`, le tableau contient uniquement les correspondances et `matchedIndexes` est absent ; avec `details: "raw"` chaque instruction correspondante se réduit à sa position, `programId`, et le blob base58 `data`.

Pour une lecture champ par champ de la charge de notification, voir la [référence du protocole de démarrage rapide](/docs/fr/parsed-streams/quickstart#notifications).

## Gestion des Abonnements

Le `result` de la réponse d'abonnement est le même numéro qui apparaît dans `params.subscription` sur chaque notification de cet abonnement. Conservez-le — vous en avez besoin pour [vous désabonner](/docs/fr/api-reference/parsed-streams/parsedtransactionunsubscribe).

Un projet peut avoir jusqu'à **100 connexions simultanées**, partagées entre toutes ses clés API, avec jusqu'à **25 abonnements par connexion**. Voir la [vue d'ensemble](/docs/fr/api-reference/parsed-streams/overview#limites) pour toutes les limites.
