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

# 如何使用 getTokenAccountsByDelegate

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

[`getTokenAccountsByDelegate`](https://www.helius.dev/docs/api-reference/rpc/http/gettokenaccountsbydelegate) RPC 方法检索所有已批准特定公钥作为委托的 SPL Token 账户。委托有权对代币账户执行某些操作，例如转移或销毁代币，直至委托金额。

此方法对于管理代理权限的服务或需要发现特定密钥可以代表哪些代币账户执行操作的服务非常有用。

## 常见用例

* **列出代理资产：** 显示已授予特定钱包或程序代理权限的所有代币账户。
* **自动化代币管理：** 代表用户执行操作的服务（例如，自动做市商、管理代币化奖励的质押协议）可以使用此方法查找他们有权与之交互的账户。
* **审计代理：** 审查哪些账户已将代理权限授予特定地址。
* **撤销代理：** 确定需要撤销代理权限的代币账户（尽管撤销本身是一个单独的交易）。

## 请求参数

1. **`delegatePubkey`** (字符串，必填)：要查找其关联代币账户的委托账户的 base-58 编码公钥。

2. **`filter`** (对象，必填)：一个 JSON 对象，**必须**指定 `mint` 或 `programId` 以过滤账户：
   * **`mint`** (字符串)：特定代币铸造的 base-58 编码公钥。如果提供，查询将仅返回此特定代币类型的委托于 `delegatePubkey` 的代币账户。
   * **`programId`** (字符串)：拥有账户的代币程序的 base-58 编码公钥。通常是标准 SPL Token Program (`TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) 或 Token-2022 Program (`TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`)。

3. **`options`** (对象，可选)：一个可选的配置对象，包含以下常见字段：
   * **`commitment`** (字符串，可选)：指定[承诺级别](https://www.helius.dev/blog/solana-commitment-levels)。
   * **`encoding`** (字符串，可选)：账户数据的编码。强烈建议使用 `"jsonParsed"`，因为它返回人类可读的账户信息。其他选项包括 `"base64"`, `"base64+zstd"`。如果未指定，默认为 `"base64"`。
   * **`dataSlice`** (对象，可选)：允许您仅检索账户数据的特定部分。包含 `offset` (usize) 和 `length` (usize) 字段。仅适用于 `base58`, `base64`, or `base64+zstd` 编码。
   * **`minContextSlot`** (u64, 可选)：请求可以评估的最小插槽。

## 响应结构

JSON-RPC 响应中的 `result.value` 字段是一个对象数组。每个对象表示一个具有 `delegatePubkey` 作为其委托并匹配 `filter` 标准的代币账户。数组中的每个对象都有两个字段：

* **`pubkey`** (字符串)：代币账户本身的 base-58 编码公钥。
* **`account`** (对象)：包含代币账户详细信息的对象：
  * **`lamports`** (u64)：代币账户的 lamport 余额（用于租金豁免）。
  * **`owner`** (字符串)：拥有此账户的程序的公钥（例如，Token Program）。
  * **`data`**：账户数据。如果使用 `"jsonParsed"` 编码，这将是一个具有 `program` 字段（例如，`"spl-token"`）和一个包含结构化信息的 `parsed` 字段的对象：
    * **`parsed.info`**：包含详细信息的对象，如：
      * **`mint`** (字符串)：代币的铸币地址。
      * **`owner`** (字符串)：代币账户的所有者（不是委托人）。
      * **`tokenAmount`** (对象)：此账户中的代币总余额（`amount`，`decimals`，`uiAmount`，`uiAmountString`）。
      * **`delegate`** (字符串)：委托人的公钥（应与请求中的 `delegatePubkey` 匹配）。
      * **`delegatedAmount`** (对象)：委托人被授权管理的代币数量（`amount`，`decimals`，`uiAmount`，`uiAmountString`）。
      * **`isNative`** (布尔值)：指示账户是否持有包裹的 SOL。
      * **`state`** (字符串)：代币账户的状态（例如，`"initialized"`）。
    * **`parsed.type`** (字符串)：账户的类型（例如，`"account"`）。
  * **`executable`** (布尔值)：账户是否可执行。
  * **`rentEpoch`** (u64)：此账户将在何时需要支付租金。
  * **`space`** (u64, 如果未使用 `jsonParsed`)：原始账户数据的字节长度。

**示例响应（使用 `jsonParsed` 编码）：**

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "result": {
    "context": {
      "slot": 183458000
    },
    "value": [
      {
        "pubkey": "SomeTokenAccountPubkey1...",
        "account": {
          "data": {
            "program": "spl-token",
            "parsed": {
              "info": {
                "delegate": "DelegatePubkeyProvidedInRequest...",
                "delegatedAmount": {
                  "amount": "1000000000",
                  "decimals": 9,
                  "uiAmount": 1.0,
                  "uiAmountString": "1.0"
                },
                "isNative": false,
                "mint": "TokenMintPubkey...",
                "owner": "ActualOwnerOfTheTokenAccount...",
                "state": "initialized",
                "tokenAmount": {
                  "amount": "5000000000",
                  "decimals": 9,
                  "uiAmount": 5.0,
                  "uiAmountString": "5.0"
                }
              },
              "type": "account"
            },
            "space": 165
          },
          "executable": false,
          "lamports": 2039280,
          "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // SPL Token Program
          "rentEpoch": 382
        }
      }
      // ... potentially other token accounts delegated to the same delegate
    ]
  },
  "id": 1
}
```

## 代码示例

<CodeGroup>
  ```bash cURL theme={"system"}
  # Replace <DELEGATE_PUBKEY> and <TOKEN_MINT_PUBKEY> or <TOKEN_PROGRAM_ID>
  # Example using programId (SPL Token Program)
  curl -X POST -H "Content-Type: application/json" -d \
    '{
      "jsonrpc": "2.0",
      "id": 1,
      "method": "getTokenAccountsByDelegate",
      "params": [
        "<DELEGATE_PUBKEY>",
        { "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" },
        { "encoding": "jsonParsed" }
      ]
    }' \
    <YOUR_RPC_URL>

  # Example using a specific mint
  curl -X POST -H "Content-Type: application/json" -d \
    '{
      "jsonrpc": "2.0",
      "id": 1,
      "method": "getTokenAccountsByDelegate",
      "params": [
        "<DELEGATE_PUBKEY>",
        { "mint": "<TOKEN_MINT_PUBKEY>" },
        { "encoding": "jsonParsed", "commitment": "confirmed" }
      ]
    }' \
    <YOUR_RPC_URL>
  ```

  ```javascript JavaScript (using @solana/web3.js) theme={"system"}
  const { Connection, PublicKey } = require('@solana/web3.js');

  async function findDelegatedAccounts(delegateAddress, filter, encoding = 'jsonParsed') {
    // Replace with your RPC endpoint
    const connection = new Connection('https://mainnet.helius-rpc.com/?api-key=<api-key>');
    const delegatePubKey = new PublicKey(delegateAddress);

    try {
      let actualFilter;
      if (filter.mint) {
        actualFilter = { mint: new PublicKey(filter.mint) };
      } else if (filter.programId) {
        actualFilter = { programId: new PublicKey(filter.programId) };
      } else {
        console.error("Filter must contain either 'mint' or 'programId'");
        return;
      }

      const accounts = await connection.getTokenAccountsByDelegate(
        delegatePubKey,
        actualFilter,
        { encoding }
      );

      console.log(`Found ${accounts.value.length} token accounts delegated to ${delegateAddress}:`);
      accounts.value.forEach(accInfo => {
        console.log(`  Token Account: ${accInfo.pubkey.toBase58()}`);
        if (encoding === 'jsonParsed' && accInfo.account.data.parsed) {
          console.log(`    Mint: ${accInfo.account.data.parsed.info.mint}`);
          console.log(`    Owner: ${accInfo.account.data.parsed.info.owner}`);
          console.log(`    Delegated Amount: ${accInfo.account.data.parsed.info.delegatedAmount.uiAmountString}`);
        }
        // console.log(JSON.stringify(accInfo.account.data, null, 2)); // For full data
      });

    } catch (error) {
      console.error(`Error fetching token accounts by delegate for ${delegateAddress}:`, error);
    }
  }

  // Replace with an actual delegate public key
  const exampleDelegate = '4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T'; 

  // Example 1: Find all SPL Token program accounts delegated to `exampleDelegate`
  findDelegatedAccounts(exampleDelegate, { programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' });

  // Example 2: Find accounts for a specific mint (e.g., USDC) delegated to `exampleDelegate`
  // const usdcMint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
  // findDelegatedAccounts(exampleDelegate, { mint: usdcMint });
  ```
</CodeGroup>

## 开发者提示

* **过滤器要求：** 你*必须*在过滤参数中提供 `mint` 或 `programId`。如果没有这些过滤器之一，你不能查询所有代币类型的所有委任账户。
* **编码：** 强烈建议为 `encoding` 选项使用 `"jsonParsed"`，以便更轻松地处理数据，因为它将二进制账户数据解码为结构化的 JSON 格式。
* **性能：** 使用 `programId` 查询可能比使用 `mint` 更耗费资源，特别是如果委托人对许多不同的代币类型有权限。一些 RPC 提供商可能对这种方法有更严格的速率限制。
* **委任数量：** 响应中的 `delegatedAmount` 表示委托人当前被授权使用的代币最大数量。这可能小于账户中的总 `tokenAmount`。
* **撤销委任：** 此方法仅检索信息。要撤销委任，代币账户的所有者必须向 SPL Token Program 发送 `Revoke` 指令。

本指南提供了使用 `getTokenAccountsByDelegate` 查找基于批准的委托人的 SPL 代币账户的全面概述。
