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

# 如何使用 getMultipleAccounts

> 了解 getMultipleAccounts 的使用案例、代码示例、请求参数、响应结构和提示。

[RPC方法](https://www.helius.dev/docs/api-reference/rpc/http/getmultipleaccounts)是一种同时获取多个Solana账户信息的高效方式。与其对每个账户进行单独请求，不如通过允许批量这些请求，减少网络开销，提高应用的响应速度。

## 常见用例

* **批量加载账户数据：** 当您的应用程序需要显示或处理多个已知账户的数据时（例如，用户的代币账户，一组链上程序配置）。
* **投资组合追踪器：** 获取用户拥有的多个代币账户的余额和状态。
* **市场界面：** 通过一次性获取账户数据来显示多个 NFT 或上市项目的详细信息。
* **提高 dApp 性能：** 显著减少 RPC 调用次数，从而加快加载时间并改善用户体验，特别是在处理大量账户时。

## 请求参数

1. **账户公钥数组** (必需):

* 你要查询的账户的base-58编码公钥字符串数组。
* 每次请求最多可包含100个公钥。
* 示例: 公钥示例

2. **配置对象** (可选): 包含一个或多个以下字段：

* **承诺级别**: 指定查询的[承诺水平](https://www.helius.dev/blog/solana-commitment-levels) (例如，等级示例)。
* **编码**: 账户数据的编码方式。选项包括：
* 标准base64编码（默认）。
* 较慢，但在某些上下文中可能有用。
* base64编码的zstd压缩数据。
* 如果账户由RPC节点有解析器的程序（例如，SPL Token Program，Stake Program）拥有，字段将是一个JSON对象。这对于结构化数据非常有用。
* **数据分段**: 允许你只获取账户数据的特定部分。这对于大型账户而你只需要一小部分信息时很有用。
* 偏移量: 从账户数据开始处的字节偏移量。
* 返回的字节数从偏移量开始。
* 注意: 仅可用于指定编码。
* **最低槽位**: 请求可以被评估的最低槽位。

## 响应结构

JSON-RPC 响应对象将包含一个 `result` 字段，其中包含：

* **`context`** (`object`):
  * `slot` (`u64`): 获取信息的插槽。
  * `apiVersion` (`string`, 可选): 节点的 API 版本。
* **`value`** (`array`):
  * 一个数组，其中每个元素对应请求的 `pubkeys` 数组中相同索引的公钥。
  * 每个元素将是：
    * `null`: 如果特定公钥的账户不存在或者该账户发生错误。
    * 一个具有以下字段的 **账户对象**：
      * `lamports` (`u64`): 账户拥有的 lamports 数量。
      * `owner` (`string`): 拥有账户的程序的 base-58 编码公钥。
      * `data` (`array` 或 `object`): 账户数据。如果 `encoding` 是 `jsonParsed` 并且存在解析器，则这将是一个 JSON 对象。否则，它通常是一个数组 `["encoded_string", "encoding_format"]`（例如，`["SGVsbG8=", "base64"]`）。
      * `executable` (`boolean`): 账户是否包含程序（是否可执行）。
      * `rentEpoch` (`u64`): 该账户在下一纪元需要支付租金的时刻。
      * `space` (`u64`): 账户的数据长度（字节）。

## 示例

### 1. 获取两个账户的基本信息

此示例获取两个账户的数据：SOL Llama（一个 NFT）和 Serum Dex Program v3。

<CodeGroup>
  ```bash cURL theme={"system"}
  # Replace <api-key> with your Helius API key
  # SOL Llama Mint: Abug4qgG1x23AEdjS2h9CEJ1m6ha2Z22LdK2kL2pys3F
  # Serum Dex Program v3: 9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin
  curl https://mainnet.helius-rpc.com/?api-key=<api-key> -X POST -H "Content-Type: application/json" -d \
    '{
      "jsonrpc": "2.0",
      "id": 1,
      "method": "getMultipleAccounts",
      "params": [
        [
          "Abug4qgG1x23AEdjS2h9CEJ1m6ha2Z22LdK2kL2pys3F",
          "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin"
        ]
      ]
    }'
  ```

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

  async function fetchMultipleAccountInfo() {
    const connection = new Connection('https://mainnet.helius-rpc.com/?api-key=<api-key>');
    const accountPubkeys = [
      new PublicKey('Abug4qgG1x23AEdjS2h9CEJ1m6ha2Z22LdK2kL2pys3F'), // SOL Llama
      new PublicKey('9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin')  // Serum Dex Program v3
    ];

    try {
      const accountsInfo = await connection.getMultipleAccountsInfo(accountPubkeys);
      
      accountsInfo.forEach((account, index) => {
        console.log(`--- Account ${index + 1} (${accountPubkeys[index].toBase58()}) ---`);
        if (account) {
          console.log(`  Owner: ${account.owner.toBase58()}`);
          console.log(`  Lamports: ${account.lamports}`);
          console.log(`  Executable: ${account.executable}`);
          console.log(`  Data length: ${account.data.length}`);
          // For brevity, not logging full data buffer
        } else {
          console.log("  Account not found or error fetching.");
        }
      });
    } catch (error) {
      console.error('Error fetching multiple accounts:', error);
    }
  }

  fetchMultipleAccountInfo();
  ```
</CodeGroup>

### 2. 获取解析的代币账户数据

此示例获取两个 SPL Token 账户的数据，并请求通过 `jsonParsed` 编码以获取结构化数据。

<CodeGroup>
  ```bash cURL theme={"system"}
  # Replace <api-key> with your Helius API key
  # Example USDC Token Account 1: GqoZ2MCrdTtygoX1F2b8X7F2tDXxNxyvMvykR9RzQW8p
  # Example USDT Token Account 2: HYnLMbkaPMh9W2aPNy2yP4LzLSWWw9zSCYEZdX2g2E7m
  curl https://mainnet.helius-rpc.com/?api-key=<api-key> -X POST -H "Content-Type: application/json" -d \
    '{
      "jsonrpc": "2.0",
      "id": 1,
      "method": "getMultipleAccounts",
      "params": [
        [
          "GqoZ2MCrdTtygoX1F2b8X7F2tDXxNxyvMvykR9RzQW8p",
          "HYnLMbkaPMh9W2aPNy2yP4LzLSWWw9zSCYEZdX2g2E7m"
        ],
        {
          "encoding": "jsonParsed"
        }
      ]
    }'
  ```

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

  async function fetchParsedTokenAccounts() {
    const connection = new Connection('https://mainnet.helius-rpc.com/?api-key=<api-key>');
    const tokenAccountPubkeys = [
      new PublicKey('GqoZ2MCrdTtygoX1F2b8X7F2tDXxNxyvMvykR9RzQW8p'), // Example USDC account
      new PublicKey('HYnLMbkaPMh9W2aPNy2yP4LzLSWWw9zSCYEZdX2g2E7m')  // Example USDT account
    ];

    try {
      const accountsInfo = await connection.getMultipleAccountsInfo(tokenAccountPubkeys, 'confirmed'); // Can also pass commitment here
      // Note: @solana/web3.js's getMultipleAccountsInfo automatically requests jsonParsed if the node supports it for token accounts.
      // For explicit control with raw RPC, you use the options object as in the cURL example.

      accountsInfo.forEach((account, index) => {
        console.log(`--- Token Account ${index + 1} (${tokenAccountPubkeys[index].toBase58()}) ---`);
        if (account && account.data && typeof account.data !== 'string') { // Check if data is parsed
          // The actual structure of account.data depends on the program (e.g., SPL Token)
          // For SPL Token accounts, you'd typically find parsed data in account.data.parsed.info
          const parsedInfo = (account.data as any).parsed?.info;
          if (parsedInfo) {
              console.log(`  Mint: ${parsedInfo.mint}`);
              console.log(`  Owner: ${parsedInfo.owner}`);
              console.log(`  Amount: ${parsedInfo.tokenAmount.uiAmountString} (decimals: ${parsedInfo.tokenAmount.decimals})`);
          } else {
              console.log("  Account data is not in the expected parsed format or is not a token account.");
              // console.log("Raw data:", account.data.toString('base64')); // if buffer
          }
        } else if (account) {
          console.log("  Account found, but data is not parsed or is a string (binary data).");
          // console.log("  Raw data:", account.data.toString()); // if string
        } else {
          console.log("  Account not found or error fetching.");
        }
      });
    } catch (error) {
      console.error('Error fetching parsed token accounts:', error);
    }
  }

  fetchParsedTokenAccounts();
  ```
</CodeGroup>

## 开发者提示

* **最多100个账户：** 每次请求最多可以查询100个账户。
* **原子性：** 请求不是原子的，这意味着如果一个账户查询失败，其他账户仍可能成功。检查`value`数组中的每个元素以获取`null`。
* **`jsonParsed`便利性：** 当处理诸如SPL Token账户等常见账户类型时，强烈建议使用`jsonParsed`编码，因为它使您免于手动反序列化。
* **大型账户的`dataSlice`：** 对于非常大的账户（例如某些程序状态账户），使用`dataSlice`来仅获取必要的字节，以避免过多的数据传输。
* **错误处理：** 准备处理响应`value`数组中的`null`条目，这表示某个账户未找到或无法获取。

通过利用`getMultipleAccounts`，您可以构建更高效和可扩展的Solana应用程序。

## 相关方法

<CardGroup cols={2}>
  <Card title="getAccountInfo" href="/docs/zh/api-reference/rpc/http/getaccountinfo">
    获取单个账户的详细信息
  </Card>

  <Card title="getProgramAccounts" href="/docs/zh/api-reference/rpc/http/getprogramaccounts">
    获取由特定程序拥有的所有账户
  </Card>
</CardGroup>
