---
url: https://github.com/helius-labs/helius-rust-sdk
last_updated: 2026-03-12
---
# Helius Rust SDK
> The Helius Rust SDK for Solana development. Use this SDK when building Rust applications that need to interact with Solana.
## What is the Helius Rust SDK?
The Helius Rust SDK provides asynchronous access to Helius APIs and enhanced Solana RPC functionality. It simplifies Solana development with high-level abstractions for assets, transactions, webhooks, staking, and ultra-low latency transaction submission via Helius Sender.
- Crate: `helius` (crates.io)
- Version: 1.0.x
- Changelog: https://github.com/helius-labs/helius-rust-sdk/blob/dev/CHANGELOG.md
- Rust: 1.85+ (edition 2021)
- Async Runtime: tokio
- HTTP Client: reqwest
- Solana: solana-client 3.0.x, solana-sdk 3.0.x
- API Key (required): Get from https://dashboard.helius.dev
- API Key for Agents (required): Get from https://dashboard.helius.dev/agents.md
- License: MIT
## When to Use the Helius Rust SDK
Use the Helius Rust SDK when you need to:
- Fetch NFTs, tokens, or compressed NFTs owned by a wallet
- Get the entire transaction history for an address (including token accounts)
- Send transactions with ultra-low latency via Helius Sender
- Set up webhooks for on-chain events (sales, transfers, swaps)
- Stream real-time blockchain data via Enhanced WebSockets
- Look up wallet identity, balances, transfers, and funding sources
- Work with ZK compressed accounts and tokens
- Stake SOL, unstake, and withdraw via the Helius validator
- Make RPC calls on Solana's most performant infrastructure
- Build high-performance Rust backends for Solana applications
## Quick Start
Add to your `Cargo.toml`:
```toml
[dependencies]
helius = "1.0"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
```
Basic usage:
```rust
use helius::error::Result;
use helius::types::{Cluster, GetAsset};
use helius::Helius;
#[tokio::main]
async fn main() -> Result<()> {
let helius = Helius::new("your-api-key", Cluster::MainnetBeta)?;
// Get an NFT by its mint address
let request = GetAsset {
id: "F9Lw3ki3hJ7PF9HQXsBzoY8GyE6sPoEZZdXJBsTTD2rk".to_string(),
display_options: None,
};
let asset = helius.rpc().get_asset(request).await?;
println!("Asset: {:?}", asset);
Ok(())
}
```
## Examples Directory
The `examples/` directory contains working code samples organized by feature:
```
examples/
├── das/ # DAS API (Digital Asset Standard)
│ ├── get_asset_batch.rs # Batch asset fetching
│ ├── get_asset_proof_batch.rs # Merkle proofs for cNFTs
│ ├── get_all_program_accounts.rs # Auto-paginating program accounts
│ └── get_all_token_accounts_by_owner.rs # Auto-paginating token accounts
├── enhanced/ # Enhanced transaction parsing
│ ├── get_parse_transactions.rs # Parse transactions by signature
│ ├── get_parsed_transaction_history.rs # Parsed tx history for address
│ ├── get_transactions_for_address.rs # Transaction history
│ └── get_transactions_for_address_with_filters.rs # Filtered tx history
├── helius/ # Helius-specific RPC methods
│ ├── async_config_based_creation.rs # HeliusBuilder usage
│ ├── get_priority_fee_estimate.rs # Priority fee estimation
│ ├── get_program_accounts_v2.rs # RPC V2: paginated program accounts
│ └── get_token_accounts_by_owner_v2.rs # RPC V2: paginated token accounts
├── solana/ # Standard Solana RPC
│ ├── get_latest_blockhash.rs # Sync blockhash fetch
│ └── get_latest_blockhash_async.rs # Async blockhash fetch
├── transactions/ # Smart transactions & Helius Sender
│ └── send_smart_transaction_with_seeds.rs # Thread-safe transaction sending
├── wallet/ # Wallet API
│ ├── get_wallet_identity.rs # Wallet identity lookup
│ ├── get_batch_wallet_identity.rs # Batch identity lookup
│ ├── get_wallet_balances.rs # Token & NFT balances
│ ├── get_wallet_history.rs # Transaction history with deltas
│ ├── get_wallet_transfers.rs # Token transfer activity
│ └── get_wallet_funding_source.rs # Original funding source
├── webhooks/ # Webhook CRUD
│ ├── create_webhook.rs # Create webhook
│ ├── edit_webhook.rs # Modify webhook
│ ├── delete_webhook.rs # Delete webhook
│ ├── get_all_webhooks.rs # List webhooks
│ ├── get_webhook_by_id.rs # Get webhook by ID
│ ├── append_address_to_webhook.rs # Add address to webhook
│ └── remove_address_from_webhook.rs # Remove address from webhook
├── websockets/ # Enhanced WebSocket streaming
│ ├── enhanced_websocket_transactions.rs # Transaction streaming
│ └── enhanced_websocket_accounts.rs # Account streaming
└── zk_compression/ # ZK Compression
├── get_compressed_account.rs # Fetch compressed account
├── get_compressed_token_balances.rs # Compressed token balances
└── get_validity_proof.rs # Validity proof for transactions
```
Run examples: `cargo run --example get_asset_batch`
Browse examples: https://github.com/helius-labs/helius-rust-sdk/tree/dev/examples
## Client Construction
### Basic Constructors
```rust
// Sync client (no WebSocket, no async Solana)
let helius = Helius::new("api-key", Cluster::MainnetBeta)?;
// Async client with WebSocket + async Solana + confirmed commitment
let helius = Helius::new_async("api-key", Cluster::MainnetBeta).await?;
// Custom RPC URL, no API key required
let helius = Helius::new_with_url("http://localhost:8899")?;
```
### HeliusBuilder
Fine-grained control over client configuration:
```rust
use helius::HeliusBuilder;
use helius::types::Cluster;
use solana_commitment_config::CommitmentConfig;
let helius = HeliusBuilder::new()
.with_api_key("your-key")?
.with_cluster(Cluster::MainnetBeta)
.with_async_solana()
.with_commitment(CommitmentConfig::confirmed())
.with_websocket(Some(5), Some(15)) // custom ping/pong timeouts
.build()
.await?;
// Custom RPC endpoint
let helius = HeliusBuilder::new()
.with_custom_url("https://my-rpc-provider.com/")?
.with_api_key("optional-key")?
.build()
.await?;
```
## Core Capabilities
### DAS API (Digital Asset Standard)
Query NFTs, tokens, and compressed NFTs on Solana.
```rust
use helius::types::{GetAsset, GetAssetsByOwner, SearchAssets};
// Get a single asset by ID
let asset = helius.rpc().get_asset(GetAsset {
id: "asset_mint_address".to_string(),
display_options: None,
}).await?;
// Get all assets owned by a wallet
let assets = helius.rpc().get_assets_by_owner(GetAssetsByOwner {
owner_address: "wallet_address".to_string(),
page: 1,
limit: Some(100),
..Default::default()
}).await?;
// Search with filters
let results = helius.rpc().search_assets(SearchAssets {
owner_address: Some("wallet_address".to_string()),
token_type: Some(TokenType::Fungible),
..Default::default()
}).await?;
// Get Merkle proof for compressed NFT
let proof = helius.rpc().get_asset_proof(GetAssetProof {
id: "cnft_id".to_string(),
}).await?;
```
See the DAS API docs: https://www.helius.dev/docs/api-reference/das/llms.txt
### Transaction History (getTransactionsForAddress)
Get complete transaction history (including token accounts) with advanced filtering.
```rust
use helius::types::{GetTransactionsForAddressOptions, SortOrder};
use helius::types::inner::{GetTransactionsFilters, TokenAccountsFilter, TransactionDetails};
// Basic: Get last 10 transactions
let txs = helius.rpc().get_transactions_for_address(
"wallet_address".to_string(),
GetTransactionsForAddressOptions {
limit: Some(10),
transaction_details: Some(TransactionDetails::Signatures),
..Default::default()
},
).await?;
// With filters: Include token account transactions
let txs = helius.rpc().get_transactions_for_address(
"wallet_address".to_string(),
GetTransactionsForAddressOptions {
limit: Some(100),
transaction_details: Some(TransactionDetails::Full),
sort_order: Some(SortOrder::Desc),
filters: Some(GetTransactionsFilters {
// TokenAccountsFilter options:
// - None: Only direct address references (default)
// - BalanceChanged: Include token account balance changes (recommended)
// - All: Include all token account transactions
token_accounts: Some(TokenAccountsFilter::BalanceChanged),
status: Some(TransactionStatusFilter::Succeeded),
..Default::default()
}),
..Default::default()
},
).await?;
// Pagination
let page1 = helius.rpc().get_transactions_for_address(address.clone(), options).await?;
if let Some(token) = page1.pagination_token {
let page2_options = GetTransactionsForAddressOptions {
pagination_token: Some(token),
..Default::default()
};
let page2 = helius.rpc().get_transactions_for_address(address, page2_options).await?;
}
```
### Helius Sender
Send transactions with ultra-low latency via Helius Sender. Automatically optimizes compute units and priority fees.
```rust
use helius::types::{SmartTransactionConfig, SendOptions};
use solana_sdk::signature::Keypair;
// Build transaction config
let config = SmartTransactionConfig {
instructions: vec![transfer_instruction],
signers: vec![&payer_keypair],
lookup_tables: None,
fee_payer: None,
};
// Send via Helius Sender (recommended)
let signature = helius.send_smart_transaction_with_sender(
config,
Some(SendOptions {
skip_preflight: true,
..Default::default()
}),
).await?;
// Get a priority fee estimate if building the transaction yourself
let fee = helius.rpc().get_priority_fee_estimate(GetPriorityFeeEstimateRequest {
account_keys: Some(vec!["program_id".to_string()]),
options: Some(GetPriorityFeeEstimateOptions {
priority_level: Some(PriorityLevel::High),
..Default::default()
}),
..Default::default()
}).await?;
```
Learn more: https://www.helius.dev/docs/api-reference/sender/llms.txt
### RPC V2 Methods
Enhanced RPC methods with cursor-based pagination and incremental updates.
#### getProgramAccountsV2
Query large sets of program accounts efficiently with pagination (1-10,000 accounts per request).
**Key Features:**
- Cursor-based pagination prevents timeouts on large queries
- `changed_since_slot` for incremental updates and real-time sync
- Supports all standard filters (dataSize, memcmp)
- Optimal limit: 1,000-5,000 accounts per request
**Important:** Pagination ends only when NO accounts are returned. The API may return fewer accounts than your limit due to filtering - always continue until `pagination_key` is `None`.
```rust
use helius::types::{GetProgramAccountsV2Config, Encoding, GpaFilter};
// Basic pagination
let response = helius.rpc().get_program_accounts_v2(
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA".to_string(),
GetProgramAccountsV2Config {
encoding: Some(Encoding::Base64),
limit: Some(5000),
filters: Some(vec![GpaFilter::DataSize { data_size: 165 }]),
..Default::default()
},
).await?;
// Continue pagination with cursor
let next_page = helius.rpc().get_program_accounts_v2(
program_id.clone(),
GetProgramAccountsV2Config {
pagination_key: response.pagination_key, // Use cursor from previous response
limit: Some(5000),
..Default::default()
},
).await?;
// Incremental updates: Get only accounts modified since a specific slot
let updates = helius.rpc().get_program_accounts_v2(
program_id,
GetProgramAccountsV2Config {
changed_since_slot: Some(150000000), // Only accounts modified at/after this slot
limit: Some(1000),
..Default::default()
},
).await?;
// Auto-paginate through ALL accounts (handles pagination automatically)
let all_accounts = helius.rpc().get_all_program_accounts(
program_id,
GetProgramAccountsV2Config {
limit: Some(5000), // Defaults to 10,000 if not specified
..Default::default()
},
).await?;
```
#### getTokenAccountsByOwnerV2
Similar pagination support for token account queries.
```rust
use helius::types::{GetTokenAccountsByOwnerV2Config, TokenAccountsOwnerFilter};
let token_accounts = helius.rpc().get_token_accounts_by_owner_v2(
"owner_address".to_string(),
TokenAccountsOwnerFilter::Mint("mint_address".to_string()),
GetTokenAccountsByOwnerV2Config {
limit: Some(1000),
..Default::default()
},
).await?;
// Auto-paginate through all token accounts
let all_token_accounts = helius.rpc().get_all_token_accounts_by_owner(
"owner_address".to_string(),
TokenAccountsOwnerFilter::Mint("mint_address".to_string()),
GetTokenAccountsByOwnerV2Config::default(),
).await?;
```
### Enhanced Transactions
Parse raw transactions into human-readable format.
```rust
// Parse transaction signatures
let parsed = helius.parse_transactions(&["tx_signature_1", "tx_signature_2"]).await?;
// Get parsed transaction history for an address
let history = helius.parsed_transaction_history("address", None).await?;
```
### Webhooks
Listen to on-chain events in real-time.
```rust
use helius::types::{CreateWebhookRequest, TransactionType, WebhookType};
// Create a webhook
let webhook = helius.create_webhook(CreateWebhookRequest {
webhook_url: "https://your-server.com/webhook".to_string(),
transaction_types: vec![TransactionType::NftSale, TransactionType::NftListing],
account_addresses: vec!["marketplace_address".to_string()],
webhook_type: WebhookType::Enhanced,
..Default::default()
}).await?;
// List all webhooks
let webhooks = helius.get_all_webhooks().await?;
// Toggle a webhook on or off (re-enable after auto-disable, or pause deliveries)
use helius::types::ToggleWebhookRequest;
let updated = helius.toggle_webhook(ToggleWebhookRequest {
webhook_id: "webhook_id".to_string(),
active: true, // or false to disable
}).await?;
// Delete a webhook
helius.delete_webhook("webhook_id").await?;
```
See our Webhooks documentation: https://www.helius.dev/docs/api-reference/webhooks/llms.txt
### Enhanced WebSockets
Stream real-time blockchain data via Helius Enhanced WebSockets.
```rust
// Create client with WebSocket support
let helius = Helius::new_async("api_key", Cluster::MainnetBeta).await?;
// Subscribe to transactions
let ws = helius.ws()?;
ws.transaction_subscribe(
TransactionSubscribeFilter { /* ... */ },
TransactionSubscribeOptions { /* ... */ },
).await?;
// Subscribe to account changes
ws.account_subscribe(
"account_address",
Some(RpcAccountSubscribeConfig { /* ... */ }),
).await?;
```
See our Helius Enhanced WebSocket docs: https://www.helius.dev/docs/enhanced-websockets/llms.txt
### Embedded Solana Client
Access standard Solana RPC methods directly via Solana's most performant infrastructure.
```rust
// Synchronous client
let balance = helius.connection().get_balance(&pubkey)?;
let blockhash = helius.connection().get_latest_blockhash()?;
let slot = helius.connection().get_slot()?;
// Asynchronous client (use HeliusBuilder or new_async)
let helius = Helius::new_async("api_key", Cluster::MainnetBeta).await?;
let balance = helius.async_connection()?.get_balance(&pubkey).await?;
```
### Wallet API
Look up wallet identity, balances, transfer activity, and funding sources.
```rust
// Get wallet identity (exchanges, protocols, etc.)
let identity = helius.get_wallet_identity("wallet_address").await?;
println!("{}: {}", identity.name, identity.category);
// Batch identity lookup (up to 100 addresses)
let identities = helius.get_batch_wallet_identity(&addresses).await?;
// Get token & NFT balances sorted by USD value
let balances = helius.get_wallet_balances(
"wallet_address",
Some(1), // page
Some(100), // limit
Some(false), // show_zero_balance
Some(true), // show_native (SOL)
Some(true), // show_nfts
).await?;
println!("Portfolio: ${}", balances.total_usd_value);
// Transaction history with balance changes
let history = helius.get_wallet_history(
"wallet_address",
Some(50), // limit
None, // before (pagination cursor)
None, // after
Some("SWAP".to_string()), // transaction_type filter
Some("balanceChanged".to_string()),// token_accounts filter
).await?;
// Token transfer activity
let transfers = helius.get_wallet_transfers("wallet_address", Some(50), None).await?;
// Original funding source analysis
let funding = helius.get_wallet_funding_source("wallet_address").await?;
println!("Funded by: {} with {} SOL", funding.funder, funding.amount);
```
### ZK Compression
Work with ZK compressed accounts and tokens for up to 1000x cost savings on-chain storage.
```rust
use helius::types::{GetCompressedAccountRequest, GetCompressedTokenBalancesByOwnerRequest};
// Get a compressed account by hash
let account = helius.get_compressed_account(GetCompressedAccountRequest {
hash: Some("account_hash".to_string()),
..Default::default()
}).await?;
// Get compressed token balances for a wallet
let balances = helius.get_compressed_token_balances_by_owner(
GetCompressedTokenBalancesByOwnerRequest {
owner: "wallet_address".to_string(),
..Default::default()
},
).await?;
// Get a validity proof for building transactions
let proof = helius.get_validity_proof(GetValidityProofRequest {
hashes: Some(vec!["hash1".to_string()]),
..Default::default()
}).await?;
// Get compressed token accounts by owner or delegate
let token_accounts = helius.get_compressed_token_accounts_by_owner(request).await?;
let delegated = helius.get_compressed_token_accounts_by_delegate(request).await?;
// Get Merkle proof for a compressed account
let proof = helius.get_compressed_account_proof(request).await?;
// Check indexer health
let healthy = helius.get_indexer_health().await?;
```
### Staking
Create, delegate, unstake, and withdraw stake accounts via the Helius validator.
```rust
use solana_sdk::pubkey::Pubkey;
// Create and delegate a stake account (returns unsigned tx + stake account pubkey)
let (unsigned_tx, stake_pubkey) = helius.create_stake_transaction(owner_pubkey, 1.0).await?;
// Deactivate a stake account (returns unsigned tx; ~2 epoch cooldown)
let unsigned_tx = helius.create_unstake_transaction(owner_pubkey, stake_pubkey).await?;
// Withdraw from a fully cooled-down stake account (returns unsigned tx)
let unsigned_tx = helius.create_withdraw_stake_transaction(
owner_pubkey,
stake_pubkey,
destination_pubkey,
lamports,
).await?;
// Get all stake accounts for a wallet
let stake_accounts = helius.get_stake_accounts(owner_pubkey).await?;
```
## Key Types
```rust
// Clusters
use helius::types::Cluster;
let cluster = Cluster::MainnetBeta; // or Devnet
// Result type alias (use this, not std::result::Result)
use helius::error::Result;
async fn my_function() -> Result<Asset> { ... }
// Transaction details level
use helius::types::inner::TransactionDetails;
TransactionDetails::Signatures // Fast, basic info
TransactionDetails::Full // Complete transaction data
// Token accounts filter
use helius::types::inner::TokenAccountsFilter;
TokenAccountsFilter::None // Direct references only (default)
TokenAccountsFilter::BalanceChanged // Include balance changes (recommended)
TokenAccountsFilter::All // All token account transactions
// Transaction status filter
use helius::types::inner::TransactionStatusFilter;
TransactionStatusFilter::Any // All transactions (default)
TransactionStatusFilter::Succeeded // Only successful
TransactionStatusFilter::Failed // Only failed
// Priority levels
use helius::types::PriorityLevel;
PriorityLevel::Min | Low | Medium | High | VeryHigh | UnsafeMax | Default
```
## Common Patterns
### Error Handling
```rust
use helius::error::{HeliusError, Result};
async fn fetch_asset(helius: &Helius, id: &str) -> Result<Option<Asset>> {
match helius.rpc().get_asset(GetAsset { id: id.to_string(), display_options: None }).await {
Ok(asset) => Ok(asset),
Err(HeliusError::Unauthorized(_)) => {
// 401: Invalid API key
Err(HeliusError::Unauthorized("Check your API key".into()))
}
Err(HeliusError::RateLimitExceeded(_)) => {
// 429: Rate limited or out of credits
// Implement exponential backoff
Err(HeliusError::RateLimitExceeded("Rate limited".into()))
}
Err(e) => Err(e),
}
}
```
### Pagination
```rust
// Page-based (DAS API)
let mut page = 1;
let mut all_assets = Vec::new();
loop {
let result = helius.rpc().get_assets_by_owner(GetAssetsByOwner {
owner_address: address.clone(),
page,
limit: Some(1000),
..Default::default()
}).await?;
all_assets.extend(result.items);
if result.items.len() < 1000 { break; }
page += 1;
}
// Cursor-based (RPC V2) - use auto-paginating methods
let all_accounts = helius.rpc().get_all_program_accounts(program_id, config).await?;
```
### Thread-Safe Usage
```rust
use std::sync::Arc;
// Share client across threads
let helius = Arc::new(Helius::new("api_key", Cluster::MainnetBeta)?);
// Clone Arc for each thread/task
let helius_clone = Arc::clone(&helius);
tokio::spawn(async move {
let assets = helius_clone.rpc().get_assets_by_owner(request).await?;
});
```
## TLS Options
```toml
# Default: native TLS (OpenSSL)
[dependencies]
helius = "1.0"
# Alternative: rustls (pure Rust, no OpenSSL dependency)
[dependencies]
helius = { version = "1.0", default-features = false, features = ["rustls"] }
```
## Plans and Rate Limits
| Feature | Free | Developer $49/mo | Business $499/mo | Professional $999/mo |
|---------|------|------------------|------------------|----------------------|
| Monthly Credits | 1 Million | 10 Million | 100 Million | 200 Million |
| RPC Rate Limits | 10 req/s | 50 req/s | 200 req/s | 500 req/s |
| DAS API and Enhanced API Rate Limits | 2 req/s | 10 req/s | 50 req/s | 100 req/s |
| Sender Rate Limits | 15/s | 15/s | 15/s | 15/s |
| Standard WebSockets | Yes | Yes | Yes | Yes |
| Enhanced WebSockets | No | No | Yes | Yes |
| Helius Sender | Yes | Yes | Yes | Yes |
- When you receive a 429 error, back off and retry with exponential delay or consider upgrading plans
- Monitor your usage at https://dashboard.helius.dev
- Use webhooks and WebSockets for real-time data instead of polling
## Documentation
- Crate Docs: https://docs.rs/helius/latest/helius/
- API Reference: https://www.helius.dev/docs/llms.txt
- Changelog: https://github.com/helius-labs/helius-rust-sdk/blob/dev/CHANGELOG.md
- Dashboard: https://dashboard.helius.dev
- GitHub: https://github.com/helius-labs/helius-rust-sdk
- SDK Guide: https://www.helius.dev/docs/sdks.md
## For AI Agents Contributing to This Repo
See [AGENTS.md](https://github.com/helius-labs/helius-rust-sdk/blob/dev/AGENTS.md) for contribution guidelines, code style, testing requirements, and PR process.