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

# Démarrage rapide des Flux Analysés

> Connectez-vous aux Flux Analysés, envoyez votre premier filtre et lisez une notification décodée. Plus la référence complète du protocole JSON-RPC 2.0.

<Tip>
  Nouveau dans les Flux Analysés ? Lisez d'abord [le modèle mental](/docs/fr/parsed-streams#le-modèle-mental) — il explique pourquoi les filtres sont comme ils sont.
</Tip>

## Démarrage rapide

<Steps>
  <Step title="Obtenir l'accès">
    Les Flux Analysés sont en bêta ouverte, disponibles sur les plans payants. Obtenez votre clé API depuis le [Tableau de bord Helius](https://dashboard.helius.dev) et connectez-vous au point de terminaison bêta à `wss://fs-beta.helius-rpc.com`.

    Authentifiez-vous avec la clé API de votre projet, passée en tant que paramètre de requête `api-key` (ou en tant qu'en-tête `x-api-key`).
  </Step>

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

    Une clé manquante ou invalide est rejetée avec HTTP 401. Un projet à sa limite de connexion obtient HTTP 429.
  </Step>

  <Step title="S'abonner avec un filtre">
    Envoyez `parsedTransactionSubscribe` avec un filtre et des options facultatives :

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

    La réponse `result` est un **ID d'abonnement** entier :

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

  <Step title="Lire une notification">
    Chaque transaction correspondante arrive comme un `parsedTransactionNotification`, déjà décodé, avec `matchedIndexes` pointant vers les instructions que votre filtre a trouvées. Voir [Notifications](#notifications) pour la forme complète.
  </Step>

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

    Ou fermez simplement la connexion — cela supprime tous ses abonnements.
  </Step>
</Steps>

## Guides

<CardGroup cols={2}>
  <Card title="Suivre les échanges Jupiter" icon="arrow-right-arrow-left" href="/docs/fr/parsed-streams/guides/track-jupiter-swaps">
    Utilisez `describeProgram` pour construire un filtre fiable avant de vous abonner.
  </Card>

  <Card title="Suivre les Mints Pump.fun" icon="rocket" href="/docs/fr/parsed-streams/guides/track-pumpfun-mints">
    Un écouteur sûr pour la reconnexion qui enregistre chaque nouveau déploiement de token Pump.fun.
  </Card>

  <Card title="Gérer les reconnexions" icon="rotate" href="/docs/fr/parsed-streams/guides/handling-reconnects">
    Survivez aux timeouts et déploiements inactifs, puis comblez précisément ce que vous avez manqué.
  </Card>
</CardGroup>

## Référence du protocole

Les Flux Analysés utilisent **JSON-RPC 2.0** sur une connexion WebSocket unique. Chaque requête reçoit une réponse avec le même `id`. Un abonnement pousse ensuite des messages `parsedTransactionNotification` jusqu'à ce que vous vous désabonniez ou déconnectiez.

| Méthode                        | Objectif                                                              |
| ------------------------------ | --------------------------------------------------------------------- |
| `parsedTransactionSubscribe`   | Démarrer un abonnement avec un filtre                                 |
| `parsedTransactionUnsubscribe` | Arrêter un abonnement                                                 |
| `ping`                         | Vérification de la vitalité ; retourne le slot actuel                 |
| `describeProgram`              | Lister les instructions d'un programme, événements et rôles de compte |

### S'abonner

Envoyez `parsedTransactionSubscribe` avec un filtre et des options facultatives. La réponse `result` est un **ID d'abonnement** entier.

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

#### Champs du filtre

Au moins l'un des `programs` ou `accounts.include` est requis. Les champs que vous définissez se combinent avec **ET** : une instruction doit remplir toutes les conditions pour correspondre.

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

<ParamField body="instructionNames" type="string[]">
  Noms d'instruction décodés, tels que `route`. Correspondance exacte d'abord, puis insensible à la casse et au séparateur, donc `sharedAccountsRoute` correspond également au nom sur le fil `shared_accounts_route`. OU dans la liste. Seules les instructions dont le nom a été identifié dans le catalogue peuvent correspondre, donc prenez les noms de `describeProgram`.
</ParamField>

<ParamField body="accounts.include" type="string[]">
  Adresses des comptes. 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'ID du programme lui-même ne compte pas ici comme un compte.
</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 être tenue (ET entre les entrées), et l'instruction doit être décodée pour que cela s'applique. Les noms de rôle correspondent **exactement**, sans conversion de casse, donc copiez-les de `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) peuvent correspondre. Réglez `false` pour correspondre uniquement aux instructions de premier niveau.
</ParamField>

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

#### Options

Le second paramètre est facultatif.

<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 contient. `full` : l'ensemble de la transaction, chaque instruction, plus `matchedIndexes` pointant vers les correspondances du filtre. `matched` : seulement les instructions qui ont correspondu, sans liste d'index. `raw` : instructions correspondantes uniquement, réduites à leur position, `programId`, et blob `data` en base58, sans champs décodés et sans tableau `accountKeys`. Utilisez `matched` quand la bande passante compte plus que le contexte (les charges utiles complètes sont en moyenne environ trois fois plus grandes), et `raw` lorsque vous décodez les données d'instruction vous-même et que vous avez seulement besoin des octets.
</ParamField>

Un projet peut détenir jusqu'à **100 connexions concurrentes**, partagées entre toutes ses clés API.

### Notifications

Une notification par transaction correspondante par abonnement. Avec le défaut `details: "full"` :

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

Lecture de celle-ci :

* **`transaction`** est le contexte complet. `fee` est en lamports. `accountKeys` est la liste complète des clés, y compris les clés chargées à partir de tables de recherche d'adresses, dans le même ordre que la chaîne les rapporte. `feePayer` est toujours `accountKeys[0]`. `error` transporte l'erreur de transaction en JSON structuré, par exemple `{"InstructionError": [2, {"Custom": 6001}]}`, lorsque `status` est `"error"`.
* **`summary`** a une forme unique partout où elle apparaît : un `type` (tel que `swap` ou `transfer`), un `description` lisible, et une charge `parsedData` structurée lorsque l'analyseur reconnaît l'action — pour un échange : le protocole, les montants et les mints. `transaction.summary` étiquette l'action principale de la transaction ; chaque instruction reconnue porte son propre `summary` avec la même forme. Pour collecter chaque échange dans une transaction, itérez `instructions` et lisez `summary.parsedData` lorsque `summary.type` est `"swap"`.
* **`nativeTransfers`** et **`tokenTransfers`** lister les mouvements SOL et token extraits par l'analyseur dans la transaction complète, sous la même forme que celle renvoyée par l'API d'Événements Analytiques, afin que les consommateurs de flux et d'API puissent partager le code de traitement. Les deux sont toujours présents, éventuellement vides.
* **`instructions`** est chaque instruction de la transaction dans l'ordre d'exécution : chaque instruction de premier niveau suivie de ses instructions internes. Chaque entrée porte sa propre position : `topIndex` est celle à laquelle elle appartient (commençant à 0), `innerIndex` est sa position parmi les appels internes de cette instruction (`null` signifie qu'il s'agit de l'instruction de premier niveau elle-même), et `stackHeight` est la profondeur d'appel (1 pour le niveau supérieur). Utilisez ceux-ci, pas la position dans le tableau.
* **`matchedIndexes`** sont les indices dans `instructions` vous indiquant lesquels votre filtre a effectivement trouvé. Le reste est là pour le contexte. Avec `details: "matched"` le tableau ne contient que les occurrences et `matchedIndexes` est absent.
* **Les noms `decoded` sont en snake\_case** (`in_amount`, `user_transfer_authority`), tels que publiés dans l'IDL du programme. Les arguments entiers sont souvent des chaînes (`"1000000"`) car les valeurs u64 ne rentrent pas dans les nombres JavaScript.
* **`blockTime`** est actuellement toujours `null`. Ne vous basez pas dessus.
* Attendez-vous à un **mélange d'instructions décodées et non décodées** à l'intérieur d'une même transaction : un échange entièrement décodé peut se trouver à côté d'un mémo non reconnu. Branchez-vous sur `decoded` : quand il est `null`, l'instruction transporte `rawData` (octets base58) et `rawAccounts` (liste de clés publiques simples) à la place, vous avez donc toujours quelque chose à travailler avec.

Avec `details: "raw"` le `value` se rétrécit au méta de transaction et aux blobs. `accountKeys`, `nativeTransfers`, `tokenTransfers`, `matchedIndexes`, et tous les champs décodés disparaissent (la transaction `summary` est toujours incluse); chaque instruction correspondante est sa position, son programme, et ses octets `data` en base58, exactement comme ils apparaissent sur la chaîne (présent même pour les instructions que le catalogue aurait pu décoder):

```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": [
    { "topIndex": 4, "innerIndex": null, "stackHeight": 1, "programId": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4", "data": "3Bxs4h24hBtQy9rw" }
  ]
}
```

### Se désabonner

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

Retourne `true` si l'abonnement existait et était le vôtre. Les notifications s'arrêtent immédiatement. La fermeture de la connexion supprime tous ses abonnements.

### Découverte

L'échec le plus courant avec ce type d'API est un filtre qui est valide mais ne correspond à rien, généralement un nom d'instruction ou de rôle deviné. `describeProgram` empêche cela en renvoyant les noms exacts que le comparateur utilise :

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

Vous pouvez passer une adresse de programme ou un nom de catalogue, mais **préférez l'adresse** : les noms peuvent être ambigus selon les versions de programme (plus d'une entrée de catalogue est nommée `jupiter`, et une recherche de nom peut se résoudre à celle plus ancienne). Si vous effectuez une recherche par nom, vérifiez que `result.id` est le programme auquel vous avez l'intention de vous abonner.

Flux recommandé : `describeProgram` pour obtenir les noms exacts d'instruction et de rôle, construisez le filtre avec ces noms, puis abonnez-vous. Le guide [Suivre les échanges Jupiter](/docs/fr/parsed-streams/guides/track-jupiter-swaps) explique cela de bout en bout.

### Limites

| Limite                             | Valeur                                           |
| ---------------------------------- | ------------------------------------------------ |
| Connexions concurrentes par projet | 100                                              |
| Abonnements par connexion          | 25                                               |
| Messages client                    | 10 par seconde, rafale de 20                     |
| Taille de message client           | 64 KiB                                           |
| `programs` par filtre              | 10                                               |
| `instructionNames` par filtre      | 50, chacun jusqu'à 64 caractères                 |
| `accounts.include` par filtre      | 100                                              |
| `accounts.roles` par filtre        | 20, chaque nom jusqu'à 64 caractères             |
| Tampon sortant par connexion       | 2048 notifications, puis la connexion est fermée |

### Erreurs

Les erreurs suivent JSON-RPC 2.0 : `{ "error": { "code": <int>, "message": "<text>" }, "id": <id> }`. Les messages indiquent exactement ce qui était incorrect et où.

| Code     | Signification                                                                                                  |
| -------- | -------------------------------------------------------------------------------------------------------------- |
| `-32700` | Erreur d'analyse (JSON invalide)                                                                               |
| `-32600` | Requête invalide                                                                                               |
| `-32601` | Méthode non trouvée                                                                                            |
| `-32602` | Paramètres invalides : mauvais clé publique, champ inconnu, engagement ou valeur de détails non pris en charge |
| `-32000` | Limite de filtre dépassée                                                                                      |
| `-32001` | Serveur non prêt; réessayez avec une temporisation croissante                                                  |
| `-32002` | Limité par débit (10 messages par seconde)                                                                     |
| `-32006` | Trop d'abonnements (25 par connexion)                                                                          |

Les connexions peuvent également se fermer avec un code de fermeture WebSocket — voir [Gestion des reconnexions](/docs/fr/parsed-streams/guides/handling-reconnects) pour savoir ce que chacun signifie et comment récupérer.

## Exemples de Client

<CodeGroup>
  ```bash wscat theme={"system"}
  wscat -c "wss://fs-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://fs-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://fs-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>
