> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbitflare.com/llms.txt
> Use this file to discover all available pages before exploring further.

# getProgramAccounts

> 返回程序拥有的所有账户

## 参数

<ResponseField name="programId" type="string" required>
  程序公钥（base-58 编码）
</ResponseField>

<ResponseField name="config" type="object" optional>
  <Expandable title="config fields">
    <ResponseField name="commitment" type="string" optional>
      Commitment 级别（processed、confirmed、finalized）
    </ResponseField>

    <ResponseField name="encoding" type="string" optional>
      账户数据的编码格式（base58、base64、jsonParsed）
    </ResponseField>

    <ResponseField name="dataSlice" type="object" optional>
      <ResponseField name="offset" type="number">
        开始读取账户数据的偏移量
      </ResponseField>

      <ResponseField name="length" type="number">
        要读取的数据长度
      </ResponseField>
    </ResponseField>

    <ResponseField name="filters" type="array" optional>
      要应用于账户的过滤器对象数组

      <ResponseField name="memcmp" type="object" optional>
        <ResponseField name="offset" type="number">
          要比较的账户数据偏移量
        </ResponseField>

        <ResponseField name="bytes" type="string">
          要匹配的 base-58 编码字节
        </ResponseField>
      </ResponseField>

      <ResponseField name="dataSize" type="number" optional>
        要匹配的账户数据大小
      </ResponseField>
    </ResponseField>
  </Expandable>
</ResponseField>

## 响应

<ResponseField name="result" type="array">
  账户信息对象数组

  <ResponseField name="pubkey" type="string">
    账户公钥（base-58 编码）
  </ResponseField>

  <ResponseField name="account" type="object">
    <ResponseField name="data" type="array">
      指定编码格式的账户数据
    </ResponseField>

    <ResponseField name="executable" type="boolean">
      账户是否可执行
    </ResponseField>

    <ResponseField name="lamports" type="number">
      账户余额（以 lamports 为单位）
    </ResponseField>

    <ResponseField name="owner" type="string">
      账户所有者（base-58 编码）
    </ResponseField>

    <ResponseField name="rentEpoch" type="number">
      账户下次需要支付租金的 epoch
    </ResponseField>
  </ResponseField>
</ResponseField>

## 代码示例

### 基本请求

```bash theme={null}
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "getProgramAccounts",
  "params": [
    "PROGRAM_ID"
  ]
}'
```

### 带过滤器的请求

```bash theme={null}
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "getProgramAccounts",
  "params": [
    "PROGRAM_ID",
    {
      "filters": [
        {
          "dataSize": 165
        },
        {
          "memcmp": {
            "offset": 0,
            "bytes": "BASE58_ENCODED_BYTES"
          }
        }
      ]
    }
  ]
}'
```

### 使用 web3.js

```typescript theme={null}
import { Connection, PublicKey } from '@solana/web3.js';

const connection = new Connection('https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY');

// Get all program accounts
const accounts = await connection.getProgramAccounts(
  new PublicKey('PROGRAM_ID')
);
console.log('Accounts:', accounts);

// Get filtered program accounts
async function getFilteredProgramAccounts(
  programId: PublicKey,
  filters: any[]
) {
  const accounts = await connection.getProgramAccounts(programId, {
    filters
  });
  
  return accounts.map(({ pubkey, account }) => ({
    pubkey: pubkey.toBase58(),
    data: account.data,
    lamports: account.lamports,
    owner: account.owner.toBase58(),
    executable: account.executable
  }));
}
```

## 注意事项

1. 返回特定程序拥有的所有账户
2. 可以应用过滤器缩小结果范围
3. 可以对账户数据进行切片以减少响应大小
4. 响应是即时的，因为它从当前状态读取
5. 可以为账户数据指定不同的编码格式

## 最佳实践

1. 使用过滤器高效查询特定账户
2. 考虑使用 dataSlice 减少响应大小
3. 在适当时缓存结果以减少 RPC 负载
4. 使用分页处理大型结果集
5. 根据需求使用适当的编码格式

## 常见错误

| 错误码    | 消息                              | 解决方案                  |
| ------ | ------------------------------- | --------------------- |
| -32601 | Method not found                | 验证是否连接到 Solana RPC 节点 |
| -32602 | Invalid params                  | 检查 programId 和配置参数    |
| -32007 | Account information unavailable | 节点可能正在启动或同步中          |

## 用例

1. **程序账户分析**
   ```typescript theme={null}
   interface ProgramAccountAnalysis {
     pubkey: string;
     dataSize: number;
     dataHash: string;
     lamports: number;
     metadata: {
       timestamp: number;
     };
   }

   async function analyzeProgramAccounts(
     programId: PublicKey,
     filters?: any[]
   ): Promise<ProgramAccountAnalysis[]> {
     const accounts = await connection.getProgramAccounts(programId, {
       filters,
       encoding: 'base64'
     });
     
     return accounts.map(({ pubkey, account }) => {
       const data = account.data[0];
       const dataSize = Buffer.from(data, 'base64').length;
       
       return {
         pubkey: pubkey.toBase58(),
         dataSize,
         dataHash: require('crypto')
           .createHash('sha256')
           .update(data)
           .digest('hex'),
         lamports: account.lamports,
         metadata: {
           timestamp: Date.now()
         }
       };
     });
   }
   ```

2. **程序账户监控**
   ```typescript theme={null}
   interface ProgramAccountChange {
     pubkey: string;
     type: 'created' | 'deleted' | 'modified';
     previous: any;
     current: any;
     difference: number;
   }

   class ProgramAccountMonitor {
     private previousAccounts: Map<string, any> = new Map();
     
     async monitorProgramAccounts(
       programId: PublicKey,
       filters?: any[],
       interval: number = 5000
     ): Promise<ProgramAccountChange[]> {
       const accounts = await connection.getProgramAccounts(programId, {
         filters
       });
       const changes: ProgramAccountChange[] = [];
       
       accounts.forEach(({ pubkey, account }) => {
         const address = pubkey.toBase58();
         const current = account;
         const previous = this.previousAccounts.get(address);
         
         if (!previous && current) {
           changes.push({
             pubkey: address,
             type: 'created',
             previous: null,
             current,
             difference: current.lamports
           });
         } else if (previous && !current) {
           changes.push({
             pubkey: address,
             type: 'deleted',
             previous,
             current: null,
             difference: -previous.lamports
           });
         } else if (previous && current) {
           const difference = current.lamports - previous.lamports;
           if (difference !== 0 || current.data[0] !== previous.data[0]) {
             changes.push({
               pubkey: address,
               type: 'modified',
               previous,
               current,
               difference
             });
           }
         }
         
         this.previousAccounts.set(address, current);
       });
       
       return changes;
     }
   }
   ```

3. **程序账户分页**
   ```typescript theme={null}
   interface ProgramAccountPage {
     accounts: Array<{
       pubkey: string;
       data: any;
       lamports: number;
     }>;
     total: number;
     page: number;
     pageSize: number;
     metadata: {
       timestamp: number;
     };
   }

   async function getProgramAccountPage(
     programId: PublicKey,
     page: number = 1,
     pageSize: number = 100,
     filters?: any[]
   ): Promise<ProgramAccountPage> {
     const accounts = await connection.getProgramAccounts(programId, {
       filters,
       encoding: 'base64'
     });
     
     const start = (page - 1) * pageSize;
     const end = start + pageSize;
     const pageAccounts = accounts.slice(start, end);
     
     return {
       accounts: pageAccounts.map(({ pubkey, account }) => ({
         pubkey: pubkey.toBase58(),
         data: account.data[0],
         lamports: account.lamports
       })),
       total: accounts.length,
       page,
       pageSize,
       metadata: {
         timestamp: Date.now()
       }
     };
   }
   ```
