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

# Cara Menggunakan getProgramAccounts

> Pelajari kasus penggunaan getProgramAccounts, contoh kode, parameter permintaan, struktur respons, dan tips.

Metode RPC [`getProgramAccounts`](https://www.helius.dev/docs/api-reference/rpc/http/getprogramaccounts) adalah alat canggih untuk melakukan kueri pada blockchain Solana. Metode ini memungkinkan Anda mengambil semua akun yang dimiliki oleh program on-chain tertentu. Ini sangat penting untuk berbagai macam aplikasi, mulai dari menemukan semua akun token yang terkait dengan pengguna untuk mint token tertentu hingga menemukan semua akun data khusus pengguna untuk aplikasi terdesentralisasi.

Karena sebuah program mungkin memiliki akun dalam jumlah yang sangat besar, `getProgramAccounts` menyediakan kemampuan pemfilteran yang andal untuk membantu Anda mempersempit pencarian dan mengambil hanya data yang diperlukan secara efisien.

Untuk aplikasi yang perlu melakukan kueri terhadap kumpulan akun program yang sangat besar, pertimbangkan untuk menggunakan [`getProgramAccountsV2`](/docs/id/api-reference/rpc/http/getprogramaccountsv2), yang menyediakan dukungan paginasi berbasis kursor dengan ukuran halaman yang dapat dikonfigurasi hingga 10.000 akun per permintaan.

## Kasus Penggunaan Umum

* **Menemukan Semua Akun Token untuk Sebuah Mint:** Temukan semua pemilik token SPL tertentu.
* **Mengambil Data Khusus Pengguna:** Ambil semua akun yang dibuat oleh program untuk pengguna tertentu (misalnya, posisi pengguna dalam protokol DeFi atau status permainan mereka dalam game Play-to-Earn).
* **Mencantumkan Semua Instans dari Jenis Akun Khusus:** Jika program Anda menentukan struktur akun tertentu, `getProgramAccounts` dapat menemukan semua instans struktur tersebut.
* **Memantau Status Program:** Amati semua akun yang terkait dengan program untuk melacak keseluruhan status atau aktivitasnya.
* **Membangun Penjelajah dan Alat Analitik:** Agregasikan data tentang program dan akun yang terkait dengannya.

## Parameter Permintaan

1. **`programId`** (`string`, wajib):
   * Kunci publik program yang dienkode dengan base-58 dan akunnya ingin Anda ambil.
   * Contoh: `"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"` (untuk Program Token SPL).

2. **`options`** (`object`, opsional): Objek konfigurasi dengan bidang berikut:
   * **`commitment`** (`string`): Menentukan [tingkat komitmen](https://www.helius.dev/blog/solana-commitment-levels) (misalnya, `"finalized"`, `"confirmed"`).
   * **`encoding`** (`string`): Enkode untuk bidang `data` dalam setiap akun yang dikembalikan. Nilai bawaannya adalah `"base64"`.
     * `"base58"`: Alternatif yang lebih lambat untuk data biner.
     * `"base64"`: Enkode base64 standar untuk data biner.
     * `"base64+zstd"`: Data biner yang dienkode dengan base64 dan dikompresi dengan zstd.
     * `"jsonParsed"`: Jika node RPC memiliki pengurai untuk jenis akun program (misalnya, Token SPL, Stake), bidang `data` akan berupa objek JSON terstruktur. Opsi ini sangat direkomendasikan agar mudah dibaca dan digunakan.
   * **`filters`** (`array`): Larik objek filter yang akan diterapkan pada akun. Ini sangat penting untuk performa dan relevansi. Anda dapat menggunakan hingga 4 filter. Filter umum mencakup:
     * **`dataSize`** (`object`):
       * `dataSize` (`u64`): Memfilter akun berdasarkan panjang datanya dalam byte. Contoh: `{ "dataSize": 165 }` (untuk akun Token SPL).
     * **`memcmp`** (`object`): Perbandingan memori. Membandingkan sebagian data akun dengan byte yang diberikan.
       * `offset` (`usize`): Offset byte dalam data akun tempat perbandingan dimulai.
       * `bytes` (`string`): String byte yang akan dicocokkan dan dienkode dengan base-58. String byte harus berukuran kurang dari 129 byte.
       * Contoh: Untuk menemukan akun token bagi mint tertentu, Anda akan menggunakan `memcmp` dengan `offset: 0` (tempat alamat mint disimpan dalam akun token) dan mengatur `bytes` ke kunci publik mint.
   * **`dataSlice`** (`object`): Hanya mengembalikan bagian tertentu dari data setiap akun. Berguna untuk akun besar jika Anda hanya memerlukan sebagian data.
     * `offset` (`usize`): Offset byte tempat pemotongan dimulai.
     * `length` (`usize`): Jumlah byte yang akan dikembalikan.
     * *Catatan: `dataSlice` terutama digunakan untuk enkode biner, bukan `jsonParsed`.*
   * **`withContext`** (`boolean`): Jika `true`, respons akan berupa objek `RpcResponse` yang berisi `context` (dengan `slot`) dan `value` (larik akun). Jika `false` atau dihilangkan, biasanya hanya larik akun yang dikembalikan. Perilakunya dapat sedikit berbeda berdasarkan penyedia RPC.
   * **`minContextSlot`** (`u64`): Slot minimum tempat permintaan dapat dievaluasi.

## Struktur Respons

Respons berupa larik objek, dengan setiap objek mewakili akun yang ditemukan dan mencakup:

* **`pubkey`** (`string`): Kunci publik akun yang dienkode dengan base-58.
* **`account`** (`object`):
  * `lamports` (`u64`): Saldo akun dalam lamport.
  * `owner` (`string`): Kunci publik program yang memiliki akun ini dan dienkode dengan base-58 (ini adalah `programId` yang Anda gunakan dalam kueri).
  * `data` (`string`, `array`, atau `object`): Data akun yang diformat berdasarkan parameter `encoding`.
    * Untuk `jsonParsed`: Objek JSON yang mewakili status akun yang dideserialisasi.
    * Untuk `base64`: Larik `["encoded_string", "base64"]`.
  * `executable` (`boolean`): Menunjukkan apakah akun dapat dieksekusi (yaitu, merupakan program itu sendiri).
  * `rentEpoch` (`u64`): Epoch saat akun ini selanjutnya harus membayar sewa.
  * `space` (`u64`, opsional): Panjang data akun dalam byte. Terkadang disebut `data.length` jika data berupa buffer, atau menjadi bagian dari struktur yang diurai.

Jika `withContext: true` digunakan, larik ini akan ditempatkan di bawah bidang `value` pada objek `RpcResponse`.

## Contoh

### 1. Menemukan Semua Akun Token untuk Mint Tertentu (USDC)

Contoh ini menemukan semua akun Token SPL yang menyimpan USDC. Contoh ini menggunakan `dataSize` untuk memfilter akun token (165 byte) dan `memcmp` untuk mencocokkan alamat mint USDC pada offset 0.

<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. Menemukan Semua Akun Token yang Dimiliki Dompet Tertentu

Contoh ini menemukan semua akun Token SPL yang dimiliki oleh alamat dompet tertentu. Contoh ini menggunakan `dataSize` (165 byte) dan `memcmp` pada offset 32 (tempat kunci publik pemilik disimpan dalam akun token).

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

## Pemfilteran Lanjutan

Optimalkan kueri Anda dengan filter untuk mengurangi ukuran respons dan meningkatkan performa:

```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="/docs/id/api-reference/rpc/http/getprogramaccounts">
  getProgramAccounts
</Card>

### Jenis Filter

* `memcmp`: Filter akun yang cocok dengan pola tertentu pada offset yang diberikan
* `dataSize`: Filter akun berdasarkan ukuran datanya secara tepat
* Beberapa filter: Semua kondisi harus terpenuhi (AND logis)

## Tips untuk Developer

* **Performa:** `getProgramAccounts` dapat menghabiskan banyak sumber daya pada node RPC, khususnya tanpa filter atau untuk program dengan banyak akun. Selalu gunakan filter (`dataSize`, `memcmp`) dan `dataSlice` jika memungkinkan untuk mempersempit cakupan kueri dan mengurangi ukuran respons.
* **Kumpulan Hasil Besar:** Untuk kueri yang mengembalikan banyak hasil, respons mungkin terpotong atau mengalami timeout. Gunakan pemfilteran untuk mempersempit cakupan, atau pertimbangkan [`getProgramAccountsV2`](/docs/id/api-reference/rpc/http/getprogramaccountsv2) untuk dukungan paginasi.
* **Batas Laju:** Perhatikan batas laju penyedia RPC karena panggilan `getProgramAccounts` yang sering atau berat dapat mencapai batas tersebut.
* **Pengetahuan tentang Tata Letak Data:** Penggunaan `memcmp` secara efektif memerlukan pemahaman tentang tata letak byte dari data akun yang Anda kueri.
* **Ketersediaan `jsonParsed`:** Enkode `jsonParsed` bergantung pada ketersediaan pengurai untuk jenis akun program tertentu pada node RPC. Enkode ini didukung secara luas untuk program umum seperti Token SPL.

`getProgramAccounts` adalah metode penting bagi developer yang perlu melakukan kueri dan berinteraksi dengan kumpulan akun milik suatu program. Menguasai opsi pemfilterannya merupakan kunci untuk membangun aplikasi Solana yang efisien dan andal.

## Paginasi untuk Kumpulan Data Besar

Untuk aplikasi yang menangani program dengan akun dalam jumlah besar (10.000+), gunakan [`getProgramAccountsV2`](/docs/id/api-reference/rpc/http/getprogramaccountsv2), yang menyediakan:

* **Paginasi berbasis kursor**: Atur `limit` (1–10.000) dan gunakan `paginationKey` untuk menavigasi hasil
* **Pembaruan inkremental**: Gunakan `changedSinceSlot` untuk mengambil hanya akun yang diubah sejak slot tertentu
* **Performa lebih baik**: Mencegah timeout dan mengurangi penggunaan memori
* **Perilaku paginasi**: Akhir paginasi hanya ditunjukkan ketika tidak ada akun yang dikembalikan. Jumlah akun yang dikembalikan mungkin kurang dari batas karena pemfilteran—lanjutkan paginasi hingga `paginationKey` bernilai 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");
}
```

## Metode Terkait

<CardGroup cols={2}>
  <Card title="getProgramAccountsV2" href="/docs/id/api-reference/rpc/http/getprogramaccountsv2">
    Versi dengan paginasi dan navigasi berbasis kursor untuk kumpulan data besar
  </Card>
</CardGroup>
