> ## 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 ベストプラクティス

> Helius TypeScript SDK を使用する AI エージェント向けの推奨パターンです。トランザクション履歴、トランザクション送信、バッチ処理、リアルタイムデータ、ページネーション、インクリメンタルフェッチング、一般的なミス、エラーハンドリングをカバーします。

[Helius TypeScript SDK](https://github.com/helius-labs/helius-sdk) を使用するエージェント向けのベストプラクティスと推奨パターン。インストールと開始については、[概要](/ja/agents/typescript-sdk)を参照してください。

## エージェント向けの推奨事項

### 2段階のルックアップの代わりに `getTransactionsForAddress` を使用

`getTransactionsForAddress` はシグネチャのルックアップとトランザクションの取得を1回の呼び出しでサーバー側フィルタリングと組み合わせています。時間/スロットの範囲、トークンアカウントのフィルタリング、ページネーションをサポートしています。

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

### 標準送信には `sendSmartTransaction` を使用

自動的にシミュレーションし、計算ユニットを推定し、優先手数料を取得して確認します。ComputeBudget 命令を手動で構築しないでください — SDK が自動的にそれらを追加します。

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

### 超低遅延には Helius Sender を使用

時間が重要なトランザクション（アービトラージ、スナイピング、清算）には、`sendTransactionWithSender` を使用してください。これは、Helius の複数地域のインフラストラクチャと 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,
});
```

### 複数の資産には `getAssetBatch` を使用

複数の資産を取得する場合は、バッチ処理を行ってください。ループで `getAsset` を呼び出さないでください。

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

### ポーリングの代わりにウェブフックまたは WebSockets を使用

ループで `getTransactionsForAddress` をポーリングしないでください。サーバー間通知にはウェブフックを、クライアントサイドのリアルタイムストリーミングには WebSockets を使用してください。

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

## ページネーション

SDK はメソッドに応じて異なるページネーション戦略を使用します。

### トークン/カーソルベース（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);
```

### ページベース（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` フィルタ

`getTransactionsForAddress` をクエリするとき、`tokenAccounts` フィルタはトークンアカウントのアクティビティを含めるかどうかを制御します:

| 値                  | 挙動                       | 使用する場合                                   |
| ------------------ | ------------------------ | ---------------------------------------- |
| 省略/`"none"`        | アドレスに直接関与するトランザクションのみ    | SOL の転送とプログラムコールのみ気にする場合                 |
| `"balanceChanged"` | バランスが変わったトークントランザクションも含む | **ほとんどのエージェントに推奨** — ノイズなくトークンの送受信を表示します |
| `"all"`            | すべてのトークンアカウントトランザクションを含む | 完全なトークンアクティビティが必要な場合（多くの結果を返すことがあります）    |

## `changedSinceSlot` — インクリメンタルアカウントフェッチング

`changedSinceSlot` は特定のスロット以降に変更されたアカウントのみを返します。同期やインデックス作成ワークフローに便利です。`getProgramAccountsV2`、`getTokenAccountsByOwnerV2`、`getAccountInfo`、`getMultipleAccounts`、`getProgramAccounts`、`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 },
]);
```

## 一般的なミス

1. **`transactionDetails: "full"` はデフォルトではありません** — デフォルトでは `getTransactionsForAddress` はシグネチャのみを返します。完全なトランザクションデータを取得するには、`transactionDetails: "full"` を設定してください。

2. **`sendSmartTransaction` には ComputeBudget 命令を追加しないでください** — SDK が自動的にそれらを追加します。独自に追加すると重複命令やトランザクションの失敗が発生します。

3. **優先手数料はマイクロラムポート単位です** — ラムポートではありません。`getPriorityFeeEstimate` の値は `SetComputeUnitPrice` に適した単位で既に提供されています。

4. **DAS のページネーションは1始まりです** — `page: 1` が最初のページであり、`page: 0` ではありません。

5. **`blockTime` は Unix 秒であり、ミリ秒ではありません** — `blockTime` でフィルタリングする場合は `Math.floor(Date.now() / 1000)` を使用してください。

6. **`getAsset` はデフォルトでファンジブルトークンを非表示にします** — それらを含めるには `options: { showFungible: true }` を渡してください。

7. **WebSocket ストリームはクリーンアップが必要です** — 常に AbortController シグナルを使用し、接続リークを避けるために完了したときに `helius.ws.close()` を呼び出してください。

## エラーハンドリングとリトライ

SDK は HTTP ステータスコードをメッセージ文字列に埋め込んだネイティブの `Error` オブジェクトをスローします（例: `"API error (429): ..."`）。エラーオブジェクトには `.status` プロパティがないため、ステータスの検出にはメッセージの解析が必要です。

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

| ステータス | 意味               | アクション          |
| ----- | ---------------- | -------------- |
| 401   | 無効または欠落した API キー | API キーを確認する    |
| 429   | レート制限またはクレジット切れ  | バックオフしてリトライする  |
| 5xx   | サーバーエラー          | 指数バックオフでリトライする |
