cURL
curl --request POST \
--url 'https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner' \
--header 'Content-Type: application/json' \
--data '
{
"id": "test-account",
"jsonrpc": "2.0",
"method": "getCompressedTokenAccountsByOwner",
"params": {
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"cursor": "3J98t1WpEZ73CNm",
"limit": 1,
"mint": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj"
}
}
'import requests
url = "https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner"
payload = {
"id": "test-account",
"jsonrpc": "2.0",
"method": "getCompressedTokenAccountsByOwner",
"params": {
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"cursor": "3J98t1WpEZ73CNm",
"limit": 1,
"mint": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj"
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: 'test-account',
jsonrpc: '2.0',
method: 'getCompressedTokenAccountsByOwner',
params: {
owner: '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj',
cursor: '3J98t1WpEZ73CNm',
limit: 1,
mint: '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj'
}
})
};
fetch('https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'id' => 'test-account',
'jsonrpc' => '2.0',
'method' => 'getCompressedTokenAccountsByOwner',
'params' => [
'owner' => '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj',
'cursor' => '3J98t1WpEZ73CNm',
'limit' => 1,
'mint' => '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner"
payload := strings.NewReader("{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedTokenAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"3J98t1WpEZ73CNm\",\n \"limit\": 1,\n \"mint\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner")
.header("Content-Type", "application/json")
.body("{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedTokenAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"3J98t1WpEZ73CNm\",\n \"limit\": 1,\n \"mint\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedTokenAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"3J98t1WpEZ73CNm\",\n \"limit\": 1,\n \"mint\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "test-account",
"jsonrpc": "2.0",
"error": {
"code": 123,
"message": "<string>"
},
"result": {
"context": {
"slot": 100
},
"value": {
"items": [
{
"account": {
"hash": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"lamports": 100,
"leafIndex": 100,
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"slotCreated": 100,
"tree": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"address": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"data": {
"data": "SGVsbG8sIFdvcmxkIQ==",
"dataHash": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"discriminator": 100
},
"seq": 100
},
"tokenData": {
"amount": 100,
"mint": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"state": "initialized",
"delegate": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"tlv": "SGVsbG8sIFdvcmxkIQ=="
}
}
],
"cursor": "3J98t1WpEZ73CNm"
}
}
}{
"error": {
"code": 123,
"message": "<string>"
},
"id": "<string>",
"jsonrpc": "<string>"
}{
"error": {
"code": 123,
"message": "<string>"
},
"id": "<string>",
"jsonrpc": "<string>"
}JSON RPC Methods
Getcompressedtokenaccountsbyowner
Retrieve compressed token accounts owned by a specific address. RPC method guide with use cases, tips and examples.
POST
/
getCompressedTokenAccountsByOwner
cURL
curl --request POST \
--url 'https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner' \
--header 'Content-Type: application/json' \
--data '
{
"id": "test-account",
"jsonrpc": "2.0",
"method": "getCompressedTokenAccountsByOwner",
"params": {
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"cursor": "3J98t1WpEZ73CNm",
"limit": 1,
"mint": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj"
}
}
'import requests
url = "https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner"
payload = {
"id": "test-account",
"jsonrpc": "2.0",
"method": "getCompressedTokenAccountsByOwner",
"params": {
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"cursor": "3J98t1WpEZ73CNm",
"limit": 1,
"mint": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj"
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: 'test-account',
jsonrpc: '2.0',
method: 'getCompressedTokenAccountsByOwner',
params: {
owner: '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj',
cursor: '3J98t1WpEZ73CNm',
limit: 1,
mint: '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj'
}
})
};
fetch('https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'id' => 'test-account',
'jsonrpc' => '2.0',
'method' => 'getCompressedTokenAccountsByOwner',
'params' => [
'owner' => '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj',
'cursor' => '3J98t1WpEZ73CNm',
'limit' => 1,
'mint' => '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner"
payload := strings.NewReader("{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedTokenAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"3J98t1WpEZ73CNm\",\n \"limit\": 1,\n \"mint\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner")
.header("Content-Type", "application/json")
.body("{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedTokenAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"3J98t1WpEZ73CNm\",\n \"limit\": 1,\n \"mint\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://devnet.helius-rpc.com/getCompressedTokenAccountsByOwner?api-key=%3Capi_key%3E/getCompressedTokenAccountsByOwner")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedTokenAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"3J98t1WpEZ73CNm\",\n \"limit\": 1,\n \"mint\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "test-account",
"jsonrpc": "2.0",
"error": {
"code": 123,
"message": "<string>"
},
"result": {
"context": {
"slot": 100
},
"value": {
"items": [
{
"account": {
"hash": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"lamports": 100,
"leafIndex": 100,
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"slotCreated": 100,
"tree": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"address": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"data": {
"data": "SGVsbG8sIFdvcmxkIQ==",
"dataHash": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"discriminator": 100
},
"seq": 100
},
"tokenData": {
"amount": 100,
"mint": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"state": "initialized",
"delegate": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"tlv": "SGVsbG8sIFdvcmxkIQ=="
}
}
],
"cursor": "3J98t1WpEZ73CNm"
}
}
}{
"error": {
"code": 123,
"message": "<string>"
},
"id": "<string>",
"jsonrpc": "<string>"
}{
"error": {
"code": 123,
"message": "<string>"
},
"id": "<string>",
"jsonrpc": "<string>"
}The
Example: Get All Token Accounts
Example: Filter by Specific Token Mint
Example: Paginated Token Discovery
Example: Calculate Token Portfolio Value
getCompressedTokenAccountsByOwner RPC method retrieves all compressed token accounts owned by a specific public key. The method supports mint filtering to query specific tokens, cursor-based pagination for handling large result sets, and returns parsed token data with merkle context for verification.
You can test this method via the OpenAPI example or custom examples below.
Common Use Cases
- Token Portfolio Display: Show all compressed tokens owned by a wallet address
- Balance Aggregation: Calculate total token holdings across multiple compressed accounts
- Token Transfer Setup: Find available token accounts to use as transfer sources
- Wallet Integration: Support compressed token discovery in wallet interfaces
- DeFi Protocol Integration: Query user token holdings for lending, trading, or staking
owner(PublicKey, required): Base58-encoded public key of the account owner to query token accounts for.options(object, optional): Configuration object containing filtering and pagination parameters:mint(PublicKey, optional): Base58-encoded mint address to filter results by specific tokencursor(string, optional): Pagination cursor from previous response for fetching next pagelimit(BN, optional): Maximum number of accounts to return (usebn()helper function)
items(array): Array of compressed token account objectscompressedAccount(object): Compressed account data and merkle proof contextaddress(string): Compressed account address (if available)owner(string): Account owner public keylamports(number): Account lamportsdata(object): Account data informationhash(string): Account hash for merkle proof verification
parsed(object): Parsed token-specific informationmint(PublicKey): Token mint addressowner(PublicKey): Token account owneramount(BN): Token amount as BN object - use .toString() for exact valuedelegate(PublicKey | null): Delegate address if set, null otherwisestate(number): Account state (0=initialized, 1=frozen, etc.)tlv(Buffer | null): Type-Length-Value extension data if present
cursor(string | null): Pagination cursor for next batch, null if no more results
- BN Object Handling: The
amountfield is a BN object - use.toString()for exact values or.toNumber()for small amounts - State Values: The
statefield is a numeric enum (0=initialized, 1=frozen, etc.) not a string - Parameter Types: Use
bn()helper function for thelimitparameter, not raw numbers - Pagination: Use cursor-based pagination for large token portfolios to avoid timeouts
- Performance: Filter by mint address when querying specific tokens to reduce response size
- Empty Responses: Handle cases where owners have no compressed token accounts gracefully
Dependencies & Setup
Dependencies & Setup
npm install @lightprotocol/stateless.js
- cURL
- TypeScript
- Rust
curl -X POST https://devnet.helius-rpc.com?api-key=YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getCompressedTokenAccountsByOwner",
"params": {
"owner": "OWNER_PUBKEY_HERE"
}
}'
import { createRpc, bn, Rpc } from '@lightprotocol/stateless.js';
import { PublicKey } from '@solana/web3.js';
const rpc: Rpc = createRpc(
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY',
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY'
);
async function getAllTokenAccounts(): Promise<void> {
const owner = new PublicKey('OWNER_ADDRESS_HERE');
const result = await rpc.getCompressedTokenAccountsByOwner(owner);
console.log(\`Found ${result.items.length} compressed token accounts\`);
result.items.forEach((account, index) => {
console.log(\`Token Account ${index + 1}:\`);
console.log(\` Mint: ${account.parsed.mint.toBase58()}\`);
console.log(\` Amount: ${account.parsed.amount.toString()}\`);
console.log(\` Owner: ${account.parsed.owner.toBase58()}\`);
console.log(\` State: ${account.parsed.state}\`);
});
return result;
}
getAllTokenAccounts();
Rust Client:
light-client v0.14.0 is available on crates.io. Use LightClient for the current stable API.// Current API: light-client 0.14.0
use light_client::rpc::LightClient;
use solana_sdk::pubkey::Pubkey;
use std::str::FromStr;
use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
let client = LightClient::new("https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY".to_string()).await?;
// Query compressed token accounts by owner
let owner = Pubkey::from_str("OWNER_PUBKEY_HERE")?;
match client.get_compressed_token_accounts_by_owner(&owner, None).await? {
response => {
println!("Found {} compressed token accounts", response.value.items.len());
for (index, account) in response.value.items.iter().enumerate() {
println!("Token Account {}:", index + 1);
println!(" Mint: {}", account.parsed.mint);
println!(" Amount: {}", account.parsed.amount);
println!(" Owner: {}", account.parsed.owner);
println!(" State: {}", account.parsed.state);
}
}
}
Ok(())
}
TypeScript
import { createRpc, bn, Rpc } from '@lightprotocol/stateless.js';
import { PublicKey } from '@solana/web3.js';
const rpc: Rpc = createRpc(
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY',
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY'
);
async function getTokenAccountsByMint(): Promise<void> {
const owner = new PublicKey('OWNER_ADDRESS_HERE');
const mint = new PublicKey('TOKEN_MINT_HERE');
const result = await rpc.getCompressedTokenAccountsByOwner(owner, {
mint
});
if (result.items.length === 0) {
console.log('No compressed token accounts found for this mint');
return;
}
let totalBalance = bn(0);
result.items.forEach((account, index) => {
const amount = account.parsed.amount;
totalBalance = totalBalance.add(amount);
console.log(\`Account ${index + 1}:\`);
console.log(\` Amount: ${amount.toString()}\`);
console.log(\` Hash: ${account.compressedAccount.hash}\`);
});
console.log(\`Total Balance: ${totalBalance.toString()}\`);
return result;
}
getTokenAccountsByMint();
TypeScript
import { createRpc, bn, Rpc } from '@lightprotocol/stateless.js';
import { PublicKey } from '@solana/web3.js';
const rpc: Rpc = createRpc(
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY',
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY'
);
async function getAllTokenAccountsPaginated(owner: PublicKey) {
let allAccounts = [];
let cursor = undefined;
const batchSize = 50; // Smaller batch size for DevNet
do {
const batch = await rpc.getCompressedTokenAccountsByOwner(owner, {
cursor,
limit: bn(batchSize)
});
allAccounts.push(...batch.items);
cursor = batch.cursor;
console.log(\`Fetched ${batch.items.length} token accounts, total: ${allAccounts.length}\`);
// Rate limiting for DevNet
await new Promise(resolve => setTimeout(resolve, 100));
} while (cursor);
// Group by mint
const accountsByMint = new Map();
allAccounts.forEach(account => {
const mintKey = account.parsed.mint.toBase58();
if (!accountsByMint.has(mintKey)) {
accountsByMint.set(mintKey, []);
}
accountsByMint.get(mintKey).push(account);
});
console.log(\`Total compressed token accounts: ${allAccounts.length}\`);
console.log(\`Unique token mints: ${accountsByMint.size}\`);
return { allAccounts, accountsByMint };
}
// Usage
const owner = new PublicKey('OWNER_ADDRESS_HERE');
getAllTokenAccountsPaginated(owner);
TypeScript
import { createRpc, bn, Rpc } from '@lightprotocol/stateless.js';
import { PublicKey } from '@solana/web3.js';
const rpc: Rpc = createRpc(
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY',
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY'
);
async function calculateTokenPortfolio(): Promise<Map<string, any>> {
const owner = new PublicKey('OWNER_ADDRESS_HERE');
const tokenAccounts = await rpc.getCompressedTokenAccountsByOwner(owner);
if (tokenAccounts.items.length === 0) {
console.log('No compressed token accounts found');
return;
}
const portfolio = new Map();
tokenAccounts.items.forEach(account => {
const mintKey = account.parsed.mint.toBase58();
const amount = account.parsed.amount;
if (portfolio.has(mintKey)) {
const existing = portfolio.get(mintKey);
portfolio.set(mintKey, existing.add(amount));
} else {
portfolio.set(mintKey, amount);
}
});
console.log('Compressed Token Portfolio:');
portfolio.forEach((balance, mint) => {
console.log(\` ${mint}: ${balance.toString()}\`);
});
return portfolio;
}
calculateTokenPortfolio();
Body
application/json
An ID to identify the request.
Available options:
test-account The version of the JSON-RPC protocol.
Available options:
2.0 The name of the method to invoke.
Available options:
getCompressedTokenAccountsByOwner Show child attributes
Show child attributes