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

# TypeScript SDK Meilleures Pratiques

> Modèles Solana recommandés pour les agents IA utilisant le Helius TypeScript SDK — historique des transactions, envoi, regroupement, pagination, et gestion des erreurs.

Meilleures pratiques et modèles recommandés pour les agents utilisant le [Helius TypeScript SDK](https://github.com/helius-labs/helius-sdk). Pour l'installation et le démarrage, voir la [vue d'ensemble](/docs/fr/agents/typescript-sdk).

## Recommandations pour les Agents

### Utiliser `getTransactionsForAddress` au lieu de la recherche en deux étapes

`getTransactionsForAddress` combine la recherche de signatures et la récupération des transactions en un seul appel avec filtrage côté serveur. Il prend en charge les plages de temps/slot, le filtrage des comptes de jetons et la pagination.

```typescript theme={"system"}
// GOOD: Single call, server-side filtering
const txs = await helius.getTransactionsForAddress([
  "address",
  {
    transactionDetails: "full",
    limit: 100,
    filters: {
      tokenAccounts: "balanceChanged",
      blockTime: { gte: Math.floor(Date.now() / 1000) - 86400 },
    },
  },
]);

// BAD: Two calls, client-side filtering, no token account support
const sigs = await helius.raw.getSignaturesForAddress(address).send();
const txs = await Promise.all(sigs.map(s => helius.raw.getTransaction(s.signature).send()));
```

### Utiliser `sendSmartTransaction` pour les envois standards

Il simule automatiquement, estime les unités de calcul, récupère les frais prioritaires, et confirme. Ne construisez pas manuellement les instructions ComputeBudget — le SDK les ajoute automatiquement.

```typescript theme={"system"}
const sig = await helius.tx.sendSmartTransaction({
  instructions: [yourInstruction],
  signers: [walletSigner],
  commitment: "confirmed",
  priorityFeeCap: 100_000,   // Optional: cap fees in microlamports/CU
  bufferPct: 0.1,            // 10% compute unit headroom (default)
});
```

### Utiliser Helius Sender pour une latence ultra-faible

Pour les transactions sensibles au temps (arbitrage, sniping, liquidations), utiliser `sendTransactionWithSender`. Il passe par l'infrastructure multi-régionale de Helius et Jito.

```typescript theme={"system"}
const sig = await helius.tx.sendTransactionWithSender({
  instructions: [yourInstruction],
  signers: [walletSigner],
  region: "US_EAST",          // Default, US_SLC, US_EAST, EU_WEST, EU_CENTRAL, EU_NORTH, AP_SINGAPORE, AP_TOKYO
  swqosOnly: true,            // Route through SWQOS only (lower tip requirement)
  pollTimeoutMs: 60_000,
  pollIntervalMs: 2_000,
});
```

### Utiliser `getAssetBatch` pour plusieurs actifs

Lors de la récupération de plusieurs actifs, regroupez-les. Ne pas appeler `getAsset` dans une boucle.

```typescript theme={"system"}
// GOOD: Single request
const assets = await helius.getAssetBatch({
  ids: ["mint1", "mint2", "mint3"],
  options: { showFungible: true, showCollectionMetadata: true },
});

// BAD: N requests
const assets = await Promise.all(mints.map(id => helius.getAsset({ id })));
```

### Utiliser les webhooks ou WebSockets au lieu du polling

Ne pas interroger `getTransactionsForAddress` dans une boucle. Utilisez les webhooks pour les notifications serveur à serveur ou les WebSockets pour le streaming client en temps réel.

```typescript theme={"system"}
// Webhook: server receives POST on matching transactions
const webhook = await helius.webhooks.create({
  webhookURL: "https://your-server.com/webhook",
  webhookType: "enhanced",
  transactionTypes: ["TRANSFER", "NFT_SALE", "SWAP"],
  accountAddresses: ["address_to_monitor"],
  authHeader: "Bearer your-secret",
});

// WebSocket: stream logs in real-time
const req = await helius.ws.logsNotifications({ mentions: ["address"] });
const stream = await req.subscribe({ abortSignal: controller.signal });
for await (const log of stream) {
  console.log(log);
}
```

## Pagination

Le SDK utilise différentes stratégies de pagination selon la méthode.

### Basé sur les jetons/cursors (Méthodes RPC V2)

```typescript theme={"system"}
// getTransactionsForAddress uses paginationToken
let paginationToken = null;
const allTxs = [];
do {
  const result = await helius.getTransactionsForAddress([
    "address",
    { limit: 100, paginationToken },
  ]);
  allTxs.push(...result.data);
  paginationToken = result.paginationToken;
} while (paginationToken);

// getProgramAccountsV2 uses paginationKey
let paginationKey = null;
do {
  const result = await helius.getProgramAccountsV2([
    programId,
    { limit: 1000, paginationKey },
  ]);
  // process result.accounts
  paginationKey = result.paginationKey;
} while (paginationKey);
```

### Basé sur les pages (API DAS)

```typescript theme={"system"}
let page = 1;
const allAssets = [];
while (true) {
  const result = await helius.getAssetsByOwner({ ownerAddress: "...", page, limit: 1000 });
  allAssets.push(...result.items);
  if (result.items.length < 1000) break;
  page++;
}
```

## Filtre `tokenAccounts`

Lors de la requête `getTransactionsForAddress`, le filtre `tokenAccounts` contrôle si l'activité du compte de jetons est incluse :

| Valeur             | Comportement                                                        | Utiliser Quand                                                                                |
| ------------------ | ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| omis / `"none"`    | Seules les transactions impliquant directement l'adresse            | Vous vous souciez uniquement des transferts SOL et des appels de programme                    |
| `"balanceChanged"` | Inclut également les transactions de jetons qui ont changé un solde | **Recommandé pour la plupart des agents** — montre les envois/réceptions de jetons sans bruit |
| `"all"`            | Inclut toutes les transactions du compte de jetons                  | Vous avez besoin de l'activité complète des jetons (peut renvoyer de nombreux résultats)      |

## `changedSinceSlot` — Récupération de Compte Incrémentielle

`changedSinceSlot` retourne uniquement les comptes modifiés après un slot donné. Utile pour les flux de synchronisation ou d'indexation. Pris en charge par `getProgramAccountsV2`, `getTokenAccountsByOwnerV2`, `getAccountInfo`, `getMultipleAccounts`, `getProgramAccounts`, et `getTokenAccountsByOwner`.

```typescript theme={"system"}
// First fetch: get all accounts
const baseline = await helius.getProgramAccountsV2([programId, { limit: 10_000 }]);
const lastSlot = currentSlot;

// Later: only get accounts that changed since your last fetch
const updates = await helius.getProgramAccountsV2([
  programId,
  { limit: 10_000, changedSinceSlot: lastSlot },
]);
```

## Erreurs Communes

1. **`transactionDetails: "full"` n'est pas par défaut** — Par défaut, `getTransactionsForAddress` retourne uniquement les signatures. Définissez `transactionDetails: "full"` pour obtenir les données complètes de transaction.

2. **Ne pas ajouter d'instructions ComputeBudget avec `sendSmartTransaction`** — Le SDK les ajoute automatiquement. Ajouter les vôtres entraîne des instructions en double et l'échec de la transaction.

3. **Les frais prioritaires sont en microlamports par unité de calcul** — Pas en lamports. Les valeurs de `getPriorityFeeEstimate` sont déjà dans l'unité correcte pour `SetComputeUnitPrice`.

4. **La pagination DAS commence à 1** — `page: 1` est la première page, pas `page: 0`.

5. **`blockTime` est en secondes Unix, pas en millisecondes** — Utilisez `Math.floor(Date.now() / 1000)` lors du filtrage par `blockTime`.

6. **`getAsset` masque par défaut les jetons fongibles** — Passez `options: { showFungible: true }` pour les inclure.

7. **Les flux WebSocket nécessitent un nettoyage** — Utilisez toujours un signal AbortController et appelez `helius.ws.close()` lorsque terminé pour éviter les fuites de connexion.

8. **Définir `maxSupportedTransactionVersion: 1` lors de la récupération des transactions.** `getTransaction`, `getBlock`, et `getTransactionsForAddress` avec `transactionDetails: "full"` échouent avec l'erreur `-32015` sur transaction v1 autrement. Sur les transactions v1, les frais prioritaires sont `message.transactionConfig.priorityFee`, un total en lamports; il n'y a pas d'instructions ComputeBudget à scanner. Voir [Support des transactions v1](/docs/fr/rpc/transaction-v1).

## Gestion des Erreurs et Réessais

Le SDK lance des objets `Error` natifs avec le code de statut HTTP intégré dans la chaîne de message (par ex., `"API error (429): ..."`). Il n'y a pas de propriété `.status` sur l'objet error, donc la détection du statut nécessite l'analyse du message.

```typescript theme={"system"}
async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      const msg = error instanceof Error ? error.message : "";
      const status = msg.match(/\b(\d{3})\b/)?.[1];
      const retryable = status === "429" || (status && status.startsWith("5"));
      if (!retryable || attempt === maxRetries) throw error;
      await new Promise(r => setTimeout(r, 1000 * 2 ** attempt));
    }
  }
  throw new Error("Unreachable");
}
```

| Statut | Signification                              | Action                            |
| ------ | ------------------------------------------ | --------------------------------- |
| 401    | Clé API invalide ou manquante              | Vérifier la clé API               |
| 429    | Limite de taux dépassée ou crédits épuisés | Réduire et réessayer              |
| 5xx    | Erreur serveur                             | Réessayer avec retour exponentiel |
