A complete, typed Python client for Helius — the Solana developer platform.
The goal of this library is to support every function, method, endpoint, and feature that Helius exposes. If Helius ships it, this client wraps it.
- ✅ Solana JSON-RPC methods
- 🚧 Enhanced Transactions
- ✅ Webhooks API
- ✅ Laserstream (websockets)
- 🚧 Laserstream (gRPC)
- 🚧 DAS (Digital Asset Standard)
- 🚧 Priority Fee
- 🚧 Wallet API
- 🚧 ZK Compression
- ✅ Account administration APIs
Deprecated Helius APIs are not supported.
- Completeness — 1:1 coverage of the entire Helius API surface.
- Type safety — fully typed responses.
- Pythonic ergonomics —
get_account_info(...)instead ofgetAccountInfo(...), context managers. - Zero magic — thin, predictable wrappers that map directly to the documented Helius API.
pip install helius-pythonPass your Helius API key explicitly:
from helius.rpc import SolanaRpcClient
client = SolanaRpcClient(api_key="YOUR_HELIUS_API_KEY")or set HELIUS_API_KEY as an environment variable:
export HELIUS_API_KEY=your_helius_api_keyYou can also set it in a .env file at the project root and let the
client pick it up automatically:
HELIUS_API_KEY=your_helius_api_keyfrom helius.rpc import SolanaRpcClient
client = SolanaRpcClient() # reads HELIUS_API_KEY from the environment or .envfrom helius.rpc import SolanaRpcClient
with SolanaRpcClient(api_key="YOUR_HELIUS_API_KEY") as client:
_ctx, balance = client.get_balance("So11111111111111111111111111111111111111112")
_ctx, supply = client.get_supply()
nodes = client.get_cluster_nodes()
block = client.get_block(slot=250_000_000)
tx = client.get_transaction("5j7s...signature...")SolanaRpcClient implements the context-manager protocol via __enter__ /
__exit__, so the underlying httpx.Client is closed cleanly when the
with block exits.
If a with block doesn't fit your code structure (e.g. the client lives
on a long-lived object), call close() yourself when you're done:
from helius.rpc import SolanaRpcClient
client = SolanaRpcClient(api_key="YOUR_HELIUS_API_KEY")
try:
_ctx, balance = client.get_balance("So11111111111111111111111111111111111111112")
_ctx, supply = client.get_supply()
finally:
client.close()Client classes also implement __del__ as a safety net — if you forget
to close() or use with, the underlying HTTP client is still closed
when the instance is garbage-collected. Prefer with or close()
regardless.
🚧 Exception & error handling is a work in progress. Today, transport errors surface as raw
httpxexceptions and Helius/Solana RPC errors are not yet wrapped in typed exception classes. A consistent error hierarchy is being worked on.
| Argument | Default | Notes |
|---|---|---|
base_url |
"https://mainnet.helius-rpc.com" |
Override to point at devnet, staging, or a custom Helius endpoint. |
api_key |
None → falls back to HELIUS_API_KEY from the environment, then .env |
If none is provided, the constructor raises ValueError. |
Per-method RPC parameters (commitment, encoding, min_context_slot,
etc.) are left unset by default — the Helius/Solana server defaults
apply unless you pass them explicitly.
For parameters, semantics, and return shapes, see the official Helius docs: RPC guide and API reference.
If you hit a bug, a missing parameter, or surprising behavior, please open an issue.
The method names map 1:1 to the Solana JSON-RPC spec, just converted to
snake_case. If you know the RPC method name, you know the Python function.
Actively expanding toward full coverage of the Helius API. See
src/helius/rpc/client.py for the
current Solana JSON-RPC implementation; supported surfaces are listed below,
and missing endpoints are tracked as issues and added continuously.
| Solana JSON-RPC method | Python method | Helius docs |
|---|---|---|
getAccountInfo |
get_account_info(...) |
guide, reference |
getBalance |
get_balance(...) |
guide, reference |
getBlock |
get_block(...) |
guide, reference |
getBlockCommitment |
get_block_commitment(...) |
guide, reference |
getBlockHeight |
get_block_height(...) |
guide, reference |
getBlockProduction |
get_block_production(...) |
guide, reference |
getBlocks |
get_blocks(...) |
guide, reference |
getBlocksWithLimit |
get_blocks_with_limit(...) |
guide, reference |
getBlockTime |
get_block_time(...) |
guide, reference |
getClusterNodes |
get_cluster_nodes() |
guide, reference |
getEpochInfo |
get_epoch_info(...) |
guide, reference |
getEpochSchedule |
get_epoch_schedule() |
guide, reference |
getFeeForMessage |
get_fee_for_message(...) |
guide, reference |
getFirstAvailableBlock |
get_first_available_block() |
guide, reference |
getGenesisHash |
get_genesis_hash() |
guide, reference |
getHealth |
get_health() |
guide, reference |
getHighestSnapshotSlot |
get_highest_snapshot_slot() |
guide, reference |
getIdentity |
get_identity() |
guide, reference |
getInflationGovernor |
get_inflation_governor(...) |
guide, reference |
getInflationRate |
get_inflation_rate() |
guide, reference |
getInflationReward |
get_inflation_reward(...) |
guide, reference |
getLargestAccounts |
get_largest_accounts(...) |
guide, reference |
getLatestBlockhash |
get_latest_blockhash(...) |
guide, reference |
getLeaderSchedule |
client.get_leader_schedule(...) |
guide, reference |
getMaxRetransmitSlot |
client.get_max_retransmit_slot() |
guide, reference |
getMaxShredInsertSlot |
get_max_shred_insert_slot() |
guide, reference |
getMinimumBalanceForRentExemption |
get_minimum_balance_for_rent_exemption(...) |
guide, reference |
getMultipleAccounts |
get_multiple_accounts(...) |
guide, reference |
getProgramAccounts |
get_program_accounts(...) |
guide, reference |
getRecentPerformanceSamples |
get_recent_performance_samples(...) |
guide, reference |
getRecentPrioritizationFees |
get_recent_prioritization_fees(...) |
guide, reference |
getSignaturesForAddress |
get_signatures_for_address(...) |
guide, reference |
getSignatureStatuses |
get_signature_statuses(...) |
guide, reference |
getSlot |
get_slot(...) |
guide, reference |
getSlotLeader |
get_slot_leader(...) |
guide, reference |
getSlotLeaders |
get_slot_leaders(...) |
guide, reference |
getStakeMinimumDelegation |
get_stake_minimum_delegation(...) |
guide, reference |
getSupply |
get_supply(...) |
guide, reference |
getTokenAccountBalance |
get_token_account_balance(...) |
guide, reference |
getTokenAccountsByDelegate |
get_token_accounts_by_delegate(...) |
guide, reference |
getTokenAccountsByOwner |
get_token_accounts_by_owner(...) |
guide, reference |
getTokenLargestAccounts |
get_token_largest_accounts(...) |
guide, reference |
getTokenSupply |
get_token_supply(...) |
guide, reference |
getTransaction |
get_transaction(...) |
guide, reference |
getTransactionCount |
get_transaction_count(...) |
guide, reference |
getVersion |
get_version() |
guide, reference |
getVoteAccounts |
get_vote_accounts(...) |
guide, reference |
isBlockhashValid |
is_blockhash_valid(...) |
guide, reference |
minimumLedgerSlot |
minimum_ledger_slot() |
guide, reference |
requestAirdrop |
request_airdrop(...) |
guide, reference |
sendTransaction |
send_transaction(...) |
guide, reference |
getTransactionsForAddress |
get_transactions_for_address(...) |
reference |
getTransfersByAddress |
get_transfers_by_address(...) |
guide, reference |
WebSocketClient wraps the Solana/Helius WebSocket subscription surface.
It connects over wss:// on construction, exposes one *_subscribe /
*_unsubscribe pair per subscription type, and parses incoming
notifications into typed pydantic models.
from helius.laserstream.websockets import WebSocketClient
with WebSocketClient(api_key="YOUR_HELIUS_API_KEY") as ws:
subscription = ws.account_subscribe(
pubkey="So11111111111111111111111111111111111111112",
commitment="confirmed",
)
for context, notification, sub in ws.listen():
print(notification) # typed AccountNotification
ws.account_unsubscribe(subscription)Like SolanaRpcClient, it supports the context-manager protocol and a
manual close(). The constructor defaults to
wss://mainnet.helius-rpc.com and reads HELIUS_API_KEY from the
environment or .env when api_key is omitted; an optional proxy is
also accepted.
Each *_subscribe call returns the integer subscription id. Use
receive() to read a single notification or listen() to iterate over
them; both yield a (context, notification, subscription) tuple where
notification is the model below.
| Subscribe method | Unsubscribe method | Notification model | Helius docs |
|---|---|---|---|
account_subscribe(...) |
account_unsubscribe(...) |
AccountNotification |
reference |
block_subscribe(...) |
block_unsubscribe(...) |
BlockNotification |
reference |
logs_subscribe(...) |
logs_unsubscribe(...) |
LogsNotification |
reference |
program_subscribe(...) |
program_unsubscribe(...) |
ProgramNotification |
reference |
root_subscribe() |
root_unsubscribe(...) |
RootNotification |
reference |
signature_subscribe(...) |
signature_unsubscribe(...) |
SignatureNotification |
reference |
slot_subscribe() |
slot_unsubscribe(...) |
SlotNotification |
reference |
slots_updates_subscribe() |
slots_updates_unsubscribe(...) |
SlotsUpdatesNotification |
reference |
vote_subscribe() |
vote_unsubscribe(...) |
VoteNotification |
reference |
transaction_subscribe(...) |
transaction_unsubscribe(...) |
TransactionNotification |
reference |
WebhooksApiClient wraps the Helius Webhooks REST API. It can create,
fetch, list, update, enable/disable, and delete webhook subscriptions,
returning typed Webhook models where the endpoint returns a webhook.
from helius.webhooks.webhooks import WebhooksApiClient
with WebhooksApiClient(api_key="YOUR_HELIUS_API_KEY") as webhooks:
webhook = webhooks.create_webhook(
webhook_url="https://example.com/helius-webhook",
transaction_types=["TRANSFER"],
account_addresses=["So11111111111111111111111111111111111111112"],
webhook_type="enhanced",
auth_header="Bearer your-shared-secret",
encoding="jsonParsed",
txn_status="all",
)
webhooks.toggle_webhook(webhook.webhook_id, active=False)Like the other clients, it supports the context-manager protocol and a
manual close(). The constructor defaults to
https://mainnet.helius-rpc.com/v0/webhooks and reads HELIUS_API_KEY
from the environment or .env when api_key is omitted; optional
headers and proxy arguments are also accepted.
| REST operation | Python method | Helius docs |
|---|---|---|
| Create webhook | create_webhook(...) |
reference |
| Get webhook | get_webhook(...) |
reference |
| List webhooks | get_all_webhooks() |
reference |
| Update webhook | update_webhook(...) |
reference |
| Toggle webhook | toggle_webhook(...) |
reference |
| Delete webhook | delete_webhook(...) |
reference |
AdminClient wraps the Helius admin API. Today it exposes
project credit usage via get_project_usage(...), which returns a typed
ProjectUsage model.
from helius.admin.admin import AdminClient
with AdminClient(api_key="YOUR_HELIUS_API_KEY") as admin:
usage = admin.get_project_usage(project_id="YOUR_PROJECT_ID")
print(usage.credits_remaining, usage.usage.rpc)The project_id can be passed per call or set once on the constructor;
if neither is provided, get_project_usage raises ValueError. The
client defaults to https://admin-api.helius.xyz and, like the others,
supports the context-manager protocol, a manual close(), and reads
HELIUS_API_KEY from the environment or .env.
AI was used to assist in the development of this project, which was started because I needed a Helius client written in Python myself for another project. It has eliminated the need to perform repetitive tasks, such as writing functions that are similar to those written by hand before them. It has also been useful in drafting and updating the documentation (exclusively README.md at the time of writing), writing tests and examples. That said, AI-generated code is reviewed in full, line-by-line by me against the Helius API specifications.
To roughly describe my approach to using AI in this project, I generally write the code by hand, which makes it easy to structure the code well and maintain an intuitive understanding of how the code works. Then, when I got to the part where I had to implement 100+ similar Python functions, I turned to AI to write the massive part of the codebase, while I reviewed the result at the same time.
To sum up:
- I generally structure and write a good part of what I'm programming by hand, including boilerplate.
- I find it best to prompt agents to implement very limited functionality within narrow a scope, performing something closer to pair-programming.
- Even though at least half the LoC in this project are hand-typed, I find that AI is incredibly capable, can be enjoyable to use, but most importantly, using AI allows me to focus my time and energy on what matters.
By the way, this README section is completely brain-made and hand-typed.