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