Skip to content

Commit 2895ea0

Browse files
hetdagli234Het Dagli
andauthored
Add RPC v2 methods to the SDK (#208)
* Add RPC v2 methods to the SDK * default to 10k for auto paginating * removed package lock --------- Co-authored-by: Het Dagli <[email protected]>
1 parent 1cf13e4 commit 2895ea0

File tree

5 files changed

+595
-0
lines changed

5 files changed

+595
-0
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,15 @@ Provides methods for setting up, editing, and managing webhooks, crucial for lis
150150
- [`sendJitoBundle()`](https://github.com/helius-labs/helius-sdk/blob/main/examples/EXAMPLES_OVERVIEW.md#sendjitobundle): Sends a bundle of transactions to the Jito Block Engine
151151
- [`sendSmartTransactionWithTip()`](https://github.com/helius-labs/helius-sdk/blob/main/examples/EXAMPLES_OVERVIEW.md#sendsmarttransactionwithtip): Sends a smart transaction as a Jito bundle with a tip
152152

153+
[**Enhanced RPC Methods (V2)**](https://github.com/helius-labs/helius-sdk/blob/main/examples/EXAMPLES_OVERVIEW.md#enhanced-rpc-methods-v2)
154+
155+
New paginated RPC methods with cursor-based pagination for efficient data retrieval.
156+
157+
- [`getProgramAccountsV2()`](https://github.com/helius-labs/helius-sdk/blob/main/examples/rpc/getProgramAccountsV2.ts): Get program accounts with pagination support and changedSinceSlot for incremental updates.
158+
- [`getAllProgramAccounts()`](https://github.com/helius-labs/helius-sdk/blob/main/examples/rpc/getProgramAccountsV2.ts): Auto-paginate through all program accounts (use with caution for large programs).
159+
- [`getTokenAccountsByOwnerV2()`](https://github.com/helius-labs/helius-sdk/blob/main/examples/rpc/getTokenAccountsByOwnerV2.ts): Get token accounts by owner with pagination and filters.
160+
- [`getAllTokenAccountsByOwner()`](https://github.com/helius-labs/helius-sdk/blob/main/examples/rpc/getTokenAccountsByOwnerV2.ts): Auto-paginate through all token accounts for an owner.
161+
153162
[**Helper Methods**](https://github.com/helius-labs/helius-sdk/blob/main/examples/EXAMPLES_OVERVIEW.md#helper-methods)
154163

155164
Offers additional tools for various Solana-related tasks like analyzing blockchain throughput and tracking stake accounts and SPL token holders.
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { Helius } from "../../src"; // Replace with 'helius-sdk' in a production setting
2+
3+
async function main() {
4+
const helius = new Helius('YOUR_API_KEY');
5+
6+
// Example 1: Basic query with pagination
7+
console.log('\n=== Example 1: Basic query with pagination ===');
8+
const firstPage = await helius.rpc.getProgramAccountsV2(
9+
'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
10+
{
11+
encoding: 'jsonParsed',
12+
limit: 10
13+
}
14+
);
15+
16+
console.log(`Fetched ${firstPage.count} accounts`);
17+
console.log(`Pagination key: ${firstPage.paginationKey}`);
18+
console.log(`First account: ${firstPage.accounts[0]?.pubkey}`);
19+
20+
// Example 2: Continue pagination if more results exist
21+
if (firstPage.paginationKey) {
22+
console.log('\n=== Example 2: Fetching next page ===');
23+
const secondPage = await helius.rpc.getProgramAccountsV2(
24+
'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
25+
{
26+
encoding: 'jsonParsed',
27+
limit: 10,
28+
paginationKey: firstPage.paginationKey
29+
}
30+
);
31+
32+
console.log(`Fetched ${secondPage.count} more accounts`);
33+
console.log(`Next pagination key: ${secondPage.paginationKey}`);
34+
}
35+
36+
// Example 3: Using filters to get specific accounts
37+
console.log('\n=== Example 3: Using filters for token accounts ===');
38+
const tokenAccounts = await helius.rpc.getProgramAccountsV2(
39+
'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
40+
{
41+
encoding: 'jsonParsed',
42+
limit: 5,
43+
filters: [
44+
{ dataSize: 165 }, // Filter for token accounts (165 bytes)
45+
]
46+
}
47+
);
48+
49+
console.log(`Found ${tokenAccounts.count} token accounts`);
50+
tokenAccounts.accounts.forEach(account => {
51+
const parsed = account.account.data?.parsed;
52+
if (parsed?.info) {
53+
console.log(` Token account ${account.pubkey.substring(0, 8)}... with mint: ${parsed.info.mint?.substring(0, 8)}...`);
54+
}
55+
});
56+
57+
// Example 4: Get accounts changed since a specific slot (incremental updates)
58+
console.log('\n=== Example 4: Incremental updates with changedSinceSlot ===');
59+
const recentSlot = 363340000; // Replace with a recent slot
60+
const changedAccounts = await helius.rpc.getProgramAccountsV2(
61+
'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
62+
{
63+
encoding: 'jsonParsed',
64+
limit: 5,
65+
changedSinceSlot: recentSlot
66+
}
67+
);
68+
69+
console.log(`Found ${changedAccounts.count} accounts changed since slot ${recentSlot}`);
70+
71+
// Example 5: Auto-pagination to get all accounts (use with caution!)
72+
console.log('\n=== Example 5: Auto-pagination (limited for demo) ===');
73+
const allAccounts = await helius.rpc.getAllProgramAccounts(
74+
'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
75+
{
76+
encoding: 'jsonParsed',
77+
limit: 100, // Fetch 100 at a time
78+
filters: [
79+
{ dataSize: 82 }, // Filter for mint accounts (82 bytes) to reduce results
80+
]
81+
}
82+
);
83+
84+
console.log(`Total accounts fetched: ${allAccounts.length}`);
85+
86+
// Example 6: Using memcmp filter to find accounts with specific data
87+
console.log('\n=== Example 6: Using memcmp filter ===');
88+
const specificOwner = '86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY';
89+
const memcmpAccounts = await helius.rpc.getProgramAccountsV2(
90+
'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
91+
{
92+
encoding: 'base64',
93+
limit: 5,
94+
filters: [
95+
{ dataSize: 165 },
96+
{
97+
memcmp: {
98+
offset: 32, // Owner field in token account
99+
bytes: specificOwner
100+
}
101+
}
102+
]
103+
}
104+
);
105+
106+
console.log(`Found ${memcmpAccounts.count} accounts owned by ${specificOwner.substring(0, 8)}...`);
107+
}
108+
109+
main().catch((err) => {
110+
console.error('Example failed:', err);
111+
process.exit(1);
112+
});
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import { Helius } from "../../src"; // Replace with 'helius-sdk' in a production setting
2+
3+
async function main() {
4+
const helius = new Helius('YOUR_API_KEY');
5+
const ownerAddress = '86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY';
6+
7+
// Example 1: Get all SPL token accounts for a wallet
8+
console.log('\n=== Example 1: Get SPL token accounts ===');
9+
const splTokenAccounts = await helius.rpc.getTokenAccountsByOwnerV2(
10+
ownerAddress,
11+
{ programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' },
12+
{
13+
encoding: 'jsonParsed',
14+
limit: 10
15+
}
16+
);
17+
18+
console.log(`Found ${splTokenAccounts.value.count} token accounts`);
19+
console.log(`Context slot: ${splTokenAccounts.context.slot}`);
20+
console.log(`API version: ${splTokenAccounts.context.apiVersion}`);
21+
22+
splTokenAccounts.value.accounts.forEach(account => {
23+
const parsed = account.account.data?.parsed;
24+
if (parsed?.info) {
25+
const tokenAmount = parsed.info.tokenAmount;
26+
console.log(` Account ${account.pubkey.substring(0, 8)}...`);
27+
console.log(` Mint: ${parsed.info.mint}`);
28+
console.log(` Balance: ${tokenAmount?.uiAmountString || '0'}`);
29+
}
30+
});
31+
32+
// Example 2: Continue pagination if needed
33+
if (splTokenAccounts.value.paginationKey) {
34+
console.log('\n=== Example 2: Fetching next page ===');
35+
const nextPage = await helius.rpc.getTokenAccountsByOwnerV2(
36+
ownerAddress,
37+
{ programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' },
38+
{
39+
encoding: 'jsonParsed',
40+
limit: 10,
41+
paginationKey: splTokenAccounts.value.paginationKey
42+
}
43+
);
44+
45+
console.log(`Fetched ${nextPage.value.count} more accounts`);
46+
}
47+
48+
// Example 3: Get accounts for a specific mint (e.g., USDC)
49+
console.log('\n=== Example 3: Get accounts for specific mint ===');
50+
const usdcMint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; // USDC mint
51+
const usdcAccounts = await helius.rpc.getTokenAccountsByOwnerV2(
52+
ownerAddress,
53+
{ mint: usdcMint },
54+
{
55+
encoding: 'jsonParsed'
56+
}
57+
);
58+
59+
if (usdcAccounts.value.accounts.length > 0) {
60+
console.log(`Found ${usdcAccounts.value.accounts.length} USDC account(s)`);
61+
const account = usdcAccounts.value.accounts[0];
62+
const parsed = account.account.data?.parsed;
63+
if (parsed?.info) {
64+
console.log(` USDC Balance: ${parsed.info.tokenAmount?.uiAmountString || '0'}`);
65+
}
66+
} else {
67+
console.log('No USDC accounts found for this wallet');
68+
}
69+
70+
// Example 4: Get Token-2022 accounts
71+
console.log('\n=== Example 4: Get Token-2022 accounts ===');
72+
const token2022Accounts = await helius.rpc.getTokenAccountsByOwnerV2(
73+
ownerAddress,
74+
{ programId: 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' }, // Token-2022 program
75+
{
76+
encoding: 'jsonParsed',
77+
limit: 5
78+
}
79+
);
80+
81+
console.log(`Found ${token2022Accounts.value.count} Token-2022 accounts`);
82+
83+
// Example 5: Get recently changed token accounts (incremental updates)
84+
console.log('\n=== Example 5: Recently changed accounts ===');
85+
const recentSlot = 363340000; // Replace with a recent slot
86+
const recentlyChanged = await helius.rpc.getTokenAccountsByOwnerV2(
87+
ownerAddress,
88+
{ programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' },
89+
{
90+
encoding: 'jsonParsed',
91+
limit: 5,
92+
changedSinceSlot: recentSlot
93+
}
94+
);
95+
96+
console.log(`Found ${recentlyChanged.value.count} accounts changed since slot ${recentSlot}`);
97+
98+
// Example 6: Auto-pagination to get all token accounts
99+
console.log('\n=== Example 6: Get all token accounts (auto-pagination) ===');
100+
const allTokenAccounts = await helius.rpc.getAllTokenAccountsByOwner(
101+
ownerAddress,
102+
{ programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' },
103+
{
104+
encoding: 'jsonParsed',
105+
limit: 100 // Fetch 100 at a time
106+
}
107+
);
108+
109+
console.log(`Total token accounts: ${allTokenAccounts.length}`);
110+
111+
// Group by mint
112+
const tokensByMint = new Map<string, number>();
113+
allTokenAccounts.forEach(account => {
114+
const parsed = account.account.data?.parsed;
115+
if (parsed?.info?.mint) {
116+
const mint = parsed.info.mint;
117+
const balance = parseFloat(parsed.info.tokenAmount?.uiAmountString || '0');
118+
tokensByMint.set(mint, (tokensByMint.get(mint) || 0) + balance);
119+
}
120+
});
121+
122+
console.log('\nToken holdings summary:');
123+
tokensByMint.forEach((balance, mint) => {
124+
if (balance > 0) {
125+
console.log(` ${mint.substring(0, 8)}...: ${balance}`);
126+
}
127+
});
128+
129+
// Example 7: Using different encoding
130+
console.log('\n=== Example 7: Using base64 encoding ===');
131+
const base64Accounts = await helius.rpc.getTokenAccountsByOwnerV2(
132+
ownerAddress,
133+
{ programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' },
134+
{
135+
encoding: 'base64',
136+
limit: 2
137+
}
138+
);
139+
140+
console.log(`Fetched ${base64Accounts.value.count} accounts with base64 encoding`);
141+
base64Accounts.value.accounts.forEach(account => {
142+
console.log(` Account ${account.pubkey.substring(0, 8)}...`);
143+
console.log(` Data length: ${account.account.data[0].length} bytes`);
144+
console.log(` Encoding: ${account.account.data[1]}`);
145+
});
146+
}
147+
148+
main().catch((err) => {
149+
console.error('Example failed:', err);
150+
process.exit(1);
151+
});

0 commit comments

Comments
 (0)