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

> Empfohlene Solana-Muster für KI-Agenten mit dem Helius TypeScript SDK — Transaktionshistorie, Senden, Batching, Paginierung und Fehlerbehandlung.

Best Practices und empfohlene Muster für Agenten, die das [Helius TypeScript SDK](https://github.com/helius-labs/helius-sdk) verwenden. Für Installation und Einstieg siehe die [Übersicht](/docs/de/agents/typescript-sdk).

## Empfehlungen für Agenten

### Verwenden Sie `getTransactionsForAddress` anstelle einer zweistufigen Abfrage

`getTransactionsForAddress` kombiniert Signaturabfrage und Transaktionsabruf in einem einzigen Aufruf mit serverseitiger Filterung. Es unterstützt Zeit-/Slot-Bereiche, Token-Konto-Filterung und Paginierung.

```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()));
```

### Verwenden Sie `sendSmartTransaction` für Standard-Sendungen

Es simuliert automatisch, schätzt Recheneinheiten, ruft Priority Fees ab und bestätigt. Bauen Sie keine ComputeBudget-Anweisungen manuell — das SDK fügt sie automatisch hinzu.

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

### Verwenden Sie Helius Sender für ultra-niedrige Latenz

Für zeitkritische Transaktionen (Arbitrage, Sniping, Liquidationen) verwenden Sie `sendTransactionWithSender`. Es leitet über Helius' Multi-Region-Infrastruktur und 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,
});
```

### Verwenden Sie `getAssetBatch` für mehrere Assets

Beim Abrufen von mehr als einem Asset bündeln Sie diese. Rufen Sie `getAsset` nicht in einer Schleife auf.

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

### Verwenden Sie Webhooks oder WebSockets anstelle von Polling

Führen Sie kein Polling von `getTransactionsForAddress` in einer Schleife durch. Verwenden Sie Webhooks für Server-zu-Server-Benachrichtigungen oder WebSockets für Echtzeit-Client-Streaming.

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

## Paginierung

Das SDK verwendet je nach Methode unterschiedliche Paginierungsstrategien.

### Token-/Cursor-basiert (RPC V2 Methoden)

```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);
```

### Seitenbasiert (DAS API)

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

## `tokenAccounts` Filter

Beim Abfragen von `getTransactionsForAddress` steuert der `tokenAccounts`-Filter, ob Aktivität von Token-Konten einbezogen wird:

| Wert                   | Verhalten                                                         | Verwenden Sie, wenn                                                                   |
| ---------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| weggelassen / `"none"` | Nur Transaktionen, die die Adresse direkt betreffen               | Sie sich nur für SOL-Transfers und Programmaufrufe interessieren                      |
| `"balanceChanged"`     | Beinhaltet auch Token-Transaktionen, die den Saldo geändert haben | **Empfohlen für die meisten Agenten** — zeigt Token-Sendungen/-Empfänge ohne Rauschen |
| `"all"`                | Beinhaltet alle Token-Konto-Transaktionen                         | Sie vollständige Token-Aktivität benötigen (kann viele Ergebnisse liefern)            |

## `changedSinceSlot` — Inkrementelles Kontoabrufen

`changedSinceSlot` gibt nur Konten zurück, die nach einem bestimmten Slot geändert wurden. Nützlich für Synchronisierungs- oder Indizierungs-Workflows. Unterstützt von `getProgramAccountsV2`, `getTokenAccountsByOwnerV2`, `getAccountInfo`, `getMultipleAccounts`, `getProgramAccounts`, und `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 },
]);
```

## Häufige Fehler

1. **`transactionDetails: "full"` ist nicht der Standard** — Standardmäßig gibt `getTransactionsForAddress` nur Signaturen zurück. Setzen Sie `transactionDetails: "full"`, um vollständige Transaktionsdaten zu erhalten.

2. **Fügen Sie keine ComputeBudget-Anweisungen mit `sendSmartTransaction` hinzu** — Das SDK fügt sie automatisch hinzu. Eigene hinzufügen verursacht doppelte Anweisungen und Transaktionsfehler.

3. **Prioritätsgebühren sind in Mikro-Lamports pro Recheneinheit** — Nicht in Lamports. Werte aus `getPriorityFeeEstimate` sind bereits in der korrekten Einheit für `SetComputeUnitPrice`.

4. **DAS-Paginierung ist 1-indiziert** — `page: 1` ist die erste Seite, nicht `page: 0`.

5. **`blockTime` ist in Unix-Sekunden, nicht Millisekunden** — Verwenden Sie `Math.floor(Date.now() / 1000)`, wenn Sie nach `blockTime` filtern.

6. **`getAsset` verbirgt fungible Token standardmäßig** — Geben Sie `options: { showFungible: true }` an, um sie einzuschließen.

7. **WebSocket-Streams benötigen Bereinigung** — Verwenden Sie immer ein AbortController-Signal und rufen Sie `helius.ws.close()` auf, wenn Sie fertig sind, um Verbindungslecks zu vermeiden.

8. **Setzen Sie `maxSupportedTransactionVersion: 1`, wenn Sie Transaktionen abrufen.** `getTransaction`, `getBlock`, und `getTransactionsForAddress` mit `transactionDetails: "full"` schlagen mit Fehler `-32015` bei Transaktion v1 sonst fehl. Bei v1-Transaktionen ist die Prioritätsgebühr `message.transactionConfig.priorityFee`, eine Summe in Lamports; es gibt keine ComputeBudget-Anweisungen, die gescannt werden können. Siehe [Transaktion v1 Unterstützung](/docs/de/rpc/transaction-v1).

## Fehlerbehandlung und Wiederholungen

Das SDK wirft native `Error`-Objekte mit dem HTTP-Statuscode eingebettet in die Nachrichtenzeichenkette (z. B. `"API error (429): ..."`). Es gibt keine `.status`-Eigenschaft im Fehlerobjekt, daher erfordert die Statuserkennung die Nachrichtenanalyse.

```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");
}
```

| Status | Bedeutung                               | Maßnahme                                    |
| ------ | --------------------------------------- | ------------------------------------------- |
| 401    | Ungültiger oder fehlender API-Schlüssel | API-Schlüssel überprüfen                    |
| 429    | Ratenbegrenzung oder keine Credits mehr | Zurücksetzen und erneut versuchen           |
| 5xx    | Serverfehler                            | Mit exponentiellem Backoff erneut versuchen |
