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

# getProgramAccounts の使用方法

> getProgramAccounts の使用例、コード例、リクエストパラメータ、応答構造、およびヒントを学びます。

[`getProgramAccounts`](https://www.helius.dev/docs/api-reference/rpc/http/getprogramaccounts) RPC メソッドは、Solana ブロックチェーンのクエリを行うための強力なツールです。特定のオンチェーンプログラムが所有するすべてのアカウントを取得できます。これは、特定のトークンミントのユーザー関連のすべてのトークンアカウントを見つけたり、分散型アプリケーションのすべてのユーザー固有データアカウントを発見したりするなど、多様なアプリケーションに不可欠です。

プログラムが所有する可能性のあるアカウントの数が非常に多いため、`getProgramAccounts` は検索を絞り込み、効率的に必要なデータのみを取得するための強力なフィルタリング機能を提供します。

非常に多くのプログラムアカウントをクエリする必要があるアプリケーションでは、[`getProgramAccountsV2`](/ja/api-reference/rpc/http/getprogramaccountsv2) の使用を検討してください。この方法はカーソルベースのページネーションをサポートし、1 リクエストあたり最大 10,000 アカウントのページサイズを構成可能です。

## 一般的な使用例

* **ミントのすべてのトークンアカウントを見つける:** 特定のSPLトークンのすべての保有者を発見します。
* **ユーザー固有データの取得:** 特定のユーザーのためにプログラムが作成したすべてのアカウントを取得します（例：DeFiプロトコルのユーザーのポジション、Play-to-Earnゲームのゲーム状態）。
* **カスタムアカウントタイプのすべてのインスタンスのリスト:** プログラムが特定のアカウント構造を定義している場合、`getProgramAccounts` はその構造のすべてのインスタンスを見つけることができます。
* **プログラムステートの監視:** プログラムに関連するすべてのアカウントを観察して、プログラムの全体的な状態や活動を追跡します。
* **エクスプローラーや分析ツールの構築:** プログラムとその関連アカウントに関するデータを集約します。

## リクエストパラメータ

1. **`programId`** (`string`, 必須):
   * 取得したいアカウントが所属するプログラムのbase-58エンコードされた公開鍵です。
   * 例: `"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"` (SPLトークンプログラムの場合)。

2. **`options`** (`object`, 任意): 次のフィールドを含む構成オブジェクト:
   * **`commitment`** (`string`): [コミットメントレベル](https://www.helius.dev/blog/solana-commitment-levels) を指定します（例： `"finalized"`, `"confirmed"`）。
   * **`encoding`** (`string`): 各返されたアカウント内の `data` フィールドのエンコーディング。デフォルトは `"base64"` です。
     * `"base58"`: バイナリデータの遅い代替。
     * `"base64"`: 標準のbase64エンコーディング。
     * `"base64+zstd"`: base64エンコードされたzstd圧縮バイナリデータ。
     * `"jsonParsed"`: RPCノードにプログラムのアカウントタイプのパーサーがある場合、`data`フィールドは構造化されたJSONオブジェクトとなります。可読性と使いやすさのためにお勧めします。
   * **`filters`** (`array`): 適用するフィルタオブジェクトの配列。パフォーマンスと関連性のために重要です。最大4つのフィルタを使用できます。一般的なフィルタには次のものがあります:
     * **`dataSize`** (`object`):
       * `dataSize` (`u64`): アカウントをそのデータのバイト長でフィルタします。例: `{ "dataSize": 165 }` (SPLトークンアカウントの場合)。
     * **`memcmp`** (`object`): メモリ比較。アカウントのデータのスライスと指定されたバイトを比較します。
       * `offset` (`usize`): アカウントデータ内の比較を開始するバイトオフセット。
       * `bytes` (`string`): 照合するバイトのbase-58エンコードされた文字列。バイト文字列は129バイト未満でなければなりません。
       * 例: 特定のミントのトークンアカウントを見つけるには、`memcmp`を使用し、`offset: 0`（トークンアカウントにミントアドレスが格納されている場所）と、ミントの公開鍵に設定された `bytes` を使用します。
   * **`dataSlice`** (`object`): 各アカウントのデータの特定のスライスのみを返します。大きなアカウントで部分データのみが必要な場合に便利です。
     * `offset` (`usize`): スライスを開始するオフセットバイト。
     * `length` (`usize`): 返すバイト数。
     * *注意: `dataSlice`は主にバイナリエンコーディング用であり、`jsonParsed`には適用されません。*
   * **`withContext`** (`boolean`): `true`である場合、応答は`RpcResponse`オブジェクトに含まれる `context` （`slot`付き）と`value` （アカウントの配列）になります。`false`または省略された場合、通常はアカウントの配列だけを返します。動作はRPCプロバイダによってわずかに異なることがあります。
   * **`minContextSlot`** (`u64`): リクエストを評価できる最低スロット。

## 応答構造

応答はオブジェクトの配列で、それぞれのオブジェクトは発見されたアカウントを表し、次の内容が含まれます:

* **`pubkey`** (`string`): アカウントのbase-58エンコードされた公開鍵。
* **`account`** (`object`):
  * `lamports` (`u64`): アカウントのラメポートでの残高。
  * `owner` (`string`): このアカウントを所有するプログラムのbase-58エンコードされた公開鍵（クエリした`programId`です）。
  * `data` (`string`, `array`, または `object`): `encoding`パラメータに従って書式設定されたアカウントのデータ。
    * `jsonParsed`の場合: デシリアライズされたアカウント状態を表すJSONオブジェクト。
    * `base64`の場合: 配列 `["encoded_string", "base64"]`。
  * `executable` (`boolean`): アカウントが実行可能かどうか（すなわちプログラムそのもの）を示します。
  * `rentEpoch` (`u64`): 次にこのアカウントが賃貸料を負うエポック。
  * `space` (`u64`, 任意): アカウントのデータ長（バイト単位）。データがバッファの場合、または解析された構造の一部である場合は`data.length`とも呼ばれます。

`withContext: true`を使用する場合、この配列は`value` フィールド内の `RpcResponse` オブジェクトにネストされます。

## 例

### 1. 特定のミント（USDC）のすべてのトークンアカウントを見つける

この例ではUSDCを保持するすべてのSPLトークンアカウントを見つけます。`dataSize` を使用してトークンアカウント（165バイト）をフィルタし、`memcmp` を使用してオフセット0のUSDCミントアドレスに一致させます。

<CodeGroup>
  ```bash cURL theme={"system"}
  # Replace <api-key> with your Helius API key
  # USDC Mint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
  # Token Program ID: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
  curl https://mainnet.helius-rpc.com/?api-key=<api-key> -X POST -H "Content-Type: application/json" -d \
    '{
      "jsonrpc": "2.0",
      "id": 1,
      "method": "getProgramAccounts",
      "params": [
        "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
        {
          "encoding": "jsonParsed",
          "filters": [
            { "dataSize": 165 },
            {
              "memcmp": {
                "offset": 0, 
                "bytes": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
              }
            }
          ]
        }
      ]
    }'
  ```

  ```javascript JavaScript (using @solana/web3.js) theme={"system"}
  // Replace <api-key> with your Helius API key
  const { Connection, PublicKey } = require('@solana/web3.js');
  const { TOKEN_PROGRAM_ID } = require('@solana/spl-token');

  const USDC_MINT_ADDRESS = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

  async function findUsdcTokenAccounts() {
    const connection = new Connection('https://mainnet.helius-rpc.com/?api-key=<api-key>');

    try {
      const accounts = await connection.getProgramAccounts(TOKEN_PROGRAM_ID, {
        encoding: 'jsonParsed',
        filters: [
          {
            dataSize: 165, // Standard token account size
          },
          {
            memcmp: {
              offset: 0, // Offset for the mint address in a token account
              bytes: USDC_MINT_ADDRESS, // Base-58 encoded mint address
            },
          },
        ],
      });

      console.log(`Found ${accounts.length} USDC token accounts.`);
      accounts.forEach((accountInfo, index) => {
        console.log(`--- Account ${index + 1} ---`);
        console.log(`  Pubkey: ${accountInfo.pubkey.toBase58()}`);
        // Accessing parsed data
        const parsedData = accountInfo.account.data.parsed.info;
        console.log(`  Owner: ${parsedData.owner}`);
        console.log(`  Amount: ${parsedData.tokenAmount.uiAmountString}`);
      });
    } catch (error) {
      console.error('Error fetching USDC token accounts:', error);
    }
  }

  findUsdcTokenAccounts();
  ```
</CodeGroup>

### 2. 特定のウォレットが所有するすべてのトークンアカウントを見つける

この例では特定のウォレットアドレスが所有するすべてのSPLトークンアカウントを見つけます。`dataSize`（165バイト）と、トークンアカウントにオーナーパブキーが格納されているオフセット32で`memcmp`を使用します。

<CodeGroup>
  ```bash cURL theme={"system"}
  # Replace <api-key> with your Helius API key
  # Example Wallet Address: Helioo21241PANoNdeG55722hgUnp2VawDgsz2g
  # Token Program ID: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
  curl https://mainnet.helius-rpc.com/?api-key=<api-key> -X POST -H "Content-Type: application/json" -d \
    '{
      "jsonrpc": "2.0",
      "id": 1,
      "method": "getProgramAccounts",
      "params": [
        "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
        {
          "encoding": "jsonParsed",
          "filters": [
            { "dataSize": 165 },
            {
              "memcmp": {
                "offset": 32, 
                "bytes": "Helioo21241PANoNdeG55722hgUnp2VawDgsz2g"
              }
            }
          ]
        }
      ]
    }'
  ```

  ```javascript JavaScript (using @solana/web3.js) theme={"system"}
  // Replace <api-key> with your Helius API key
  const { Connection, PublicKey } = require('@solana/web3.js');
  const { TOKEN_PROGRAM_ID } = require('@solana/spl-token');

  const TARGET_WALLET_ADDRESS = 'Helioo21241PANoNdeG55722hgUnp2VawDgsz2g';

  async function findWalletTokenAccounts() {
    const connection = new Connection('https://mainnet.helius-rpc.com/?api-key=<api-key>');

    try {
      const accounts = await connection.getProgramAccounts(TOKEN_PROGRAM_ID, {
        encoding: 'jsonParsed',
        filters: [
          {
            dataSize: 165, // Standard token account size
          },
          {
            memcmp: {
              offset: 32, // Offset for the owner address in a token account
              bytes: TARGET_WALLET_ADDRESS, // Base-58 encoded wallet address
            },
          },
        ],
      });

      console.log(`Found ${accounts.length} token accounts for wallet ${TARGET_WALLET_ADDRESS}.`);
      accounts.forEach((accountInfo, index) => {
        console.log(`--- Account ${index + 1} (${accountInfo.pubkey.toBase58()}) ---`);
        const parsedData = accountInfo.account.data.parsed.info;
        console.log(`  Mint: ${parsedData.mint}`);
        console.log(`  Amount: ${parsedData.tokenAmount.uiAmountString}`);
      });
    } catch (error) {
      console.error('Error fetching token accounts for wallet:', error);
    }
  }

  findWalletTokenAccounts();
  ```
</CodeGroup>

## 高度なフィルタリング

フィルタを使用してクエリを最適化し、応答サイズを削減し、パフォーマンスを向上させます。

```typescript theme={"system"}
// Example filtering by memcmp (memory comparison)
const response = await fetch(
  "https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: "1",
      method: "getProgramAccounts",
      params: [
        "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Solana Token Program
        {
          encoding: "jsonParsed",
          filters: [
            {
              dataSize: 165, // Size of token account data
            },
            {
              memcmp: {
                offset: 32, // Location of owner address in the token account
                bytes: "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri",
              },
            },
          ],
        },
      ],
    }),
  }
);
const data = await response.json();
console.log("Filtered program accounts data:", data);
```

<Card title="API Reference" horizontal icon="code" href="/ja/api-reference/rpc/http/getprogramaccounts">
  getProgramAccounts
</Card>

### フィルタータイプ

* `memcmp`: 特定のオフセットで特定のパターンに一致するアカウントをフィルタします
* `dataSize`: データサイズが正確に一致するアカウントをフィルタします
* 複数のフィルタ: すべての条件を満たさなければなりません（論理AND）

## 開発者向けのヒント

* **パフォーマンス:** `getProgramAccounts` は、特にフィルタなしまたは多くのアカウントを持つプログラムでは、RPCノードでリソースを多く消費することがあります。可能な限りフィルタ（`dataSize`, `memcmp`）および`dataSlice`を使用してクエリの範囲と応答サイズを削減してください。
* **大規模な結果セット:** 多くの結果を返すクエリの場合、応答が切り捨てられたりタイムアウトすることがあります。範囲を削減するためにフィルタリングを使用するか、ページネーションサポートのある[`getProgramAccountsV2`](/ja/api-reference/rpc/http/getprogramaccountsv2)を検討してください。
* **レート制限:** RPCプロバイダのレート制限に注意してください。頻繁または大規模な`getProgramAccounts`呼び出しはこれらの制限に達する可能性があります。
* **データレイアウトの知識:** `memcmp` の効果的な使用は、クエリしているアカウントデータのバイトレイアウトを理解することが必要です。
* **`jsonParsed` の利用可能性:** `jsonParsed` エンコーディングは、特定のプログラムのアカウントタイプのためのパーサーを持つRPCノードに依存します。SPLトークンのような一般的なプログラムには広くサポートされています。

`getProgramAccounts` は、プログラムによって所有されるアカウントのセットをクエリして対話する必要がある開発者にとって不可欠なメソッドです。そのフィルタリングオプションの習熟が効率的で堅牢なSolanaアプリケーションの構築の鍵です。

## 大規模データセットのページネーション

多数のアカウントを所有するプログラムを扱うアプリケーションでは、[`getProgramAccountsV2`](/ja/api-reference/rpc/http/getprogramaccountsv2)を使用してください。これは次のことを提供します:

* **カーソルベースのページネーション**: `limit` (1-10,000) を設定し、結果をナビゲートするために`paginationKey`を使用します
* **インクリメンタルアップデート**: 特定のスロット以降に変更されたアカウントのみを取得するために`changedSinceSlot`を使用します
* **より良いパフォーマンス**: タイムアウトを防ぎ、メモリ使用量を削減します
* **ページネーションの動作**: ページネーション終了はアカウントが返されなかった場合にのみ示されます。フィルタリングにより制限未満のアカウントが返される場合があるので、`paginationKey`がnullになるまでページネーションを続けてください。

```typescript theme={"system"}
// Example: Paginated query for all token accounts
const response = await fetch("https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: "1",
    method: "getProgramAccountsV2",
    params: [
      "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
      {
        encoding: "base64",
        filters: [{ dataSize: 165 }],
        limit: 5000
      }
    ]
  })
});

const data = await response.json();
console.log(`Found ${data.result.accounts.length} accounts`);
if (data.result.paginationKey) {
  console.log("More results available, use paginationKey for next page");
  // Continue pagination even if fewer than limit accounts were returned
} else {
  console.log("End of pagination - no more accounts available");
}
```

## 関連メソッド

<CardGroup cols={2}>
  <Card title="getProgramAccountsV2" href="/ja/api-reference/rpc/http/getprogramaccountsv2">
    大規模データセットのためのカーソルベースナビゲーションを用いたページネーション版
  </Card>
</CardGroup>
