Production-grade Solana RPC client with rate limiting, circuit breaking, and provider rotation.
Project description
solana-rpc-resilient
production-grade solana rpc client that handles the real world.
rate limiting. circuit breaking. provider rotation. retry on 429. zero config.
extracted from a production solana trading system. battle-tested with millions of rpc calls.
๐ก๏ธ Why this library?
every solana dev hits the same problems:
- 429 rate limits โ your rpc provider throttles you and your app crashes
- dead providers โ your single rpc endpoint goes down and everything stops
- no failover โ you hardcode one url and pray
this library solves all three with zero config:
from solana_rpc_resilient import ResilientRPCClient
client = ResilientRPCClient([
{"name": "helius", "url": "https://mainnet.helius-rpc.com/?api-key=YOUR_KEY", "weight": 3},
{"name": "quicknode", "url": "https://your-quicknode-url.com", "weight": 2},
{"name": "public", "url": "https://api.mainnet-beta.solana.com", "weight": 1},
])
async with client:
balance = await client.get_balance("So11111111111111111111111111111111111111112")
print(balance) # Ok(489293423) โ balance in lamports
if helius returns 429 โ automatically rotates to quicknode. if quicknode is down โ circuit breaker opens, falls back to public. if all providers are down โ auto-recovers the healthiest one after 10s.
you never think about rpc reliability again.
๐ฆ Install
pip install solana-rpc-resilient
requires python 3.11+
You need your own RPC endpoints. Get a free key from Helius, QuickNode, or any Solana RPC provider. The public endpoint (
api.mainnet-beta.solana.com) works but is heavily rate-limited.
โก Features
| feature | description |
|---|---|
| adaptive rate limiter | token bucket that self-tunes. backs off on 429, climbs back after stable success. |
| circuit breaker | CLOSED โ OPEN โ HALF_OPEN state machine. stops hammering dead endpoints. |
| provider rotation | weighted random selection from healthy providers. auto-failover on 429. |
| auto-recovery | unhealthy providers are re-probed after configurable timeout. never permanently locked out. |
| request dedup | concurrent calls for the same data share one in-flight request. |
| ttl cache | configurable per-method caching to reduce unnecessary calls. |
| bypass mode | emergency calls skip circuit breaker (e.g., checking balance during a sell). |
๐ง Components
Rate Limiter
from solana_rpc_resilient import TokenBucketRateLimiter
limiter = TokenBucketRateLimiter(rate=10.0, burst=20.0)
result = await limiter.acquire(timeout=5.0)
if result.is_ok:
# make your api call
limiter.record_success()
else:
# timed out waiting for a token
pass
# on 429 response:
limiter.record_rate_limit(retry_after=2.0)
# rate automatically decreases. cooldown kicks in.
Circuit Breaker
from solana_rpc_resilient import CircuitBreaker
breaker = CircuitBreaker(
name="helius",
failure_threshold=5, # open after 5 failures
recovery_seconds=60.0, # try again after 60s
)
result = await breaker.call(
my_rpc_function,
is_retriable=lambda err: err.code == "RATE_LIMITED", # 429s don't trip the breaker
)
Full Client
from solana_rpc_resilient import ResilientRPCClient
client = ResilientRPCClient(
providers=[
{"name": "primary", "url": "https://...", "weight": 3, "tier": "paid"},
{"name": "backup", "url": "https://...", "weight": 1, "tier": "free"},
],
rate_limit=10.0, # requests/second
burst=20.0, # burst capacity
failure_threshold=5, # circuit breaker threshold
recovery_seconds=60.0, # circuit breaker recovery
)
async with client:
# all standard solana rpc methods
balance = await client.get_balance(address)
info = await client.get_account_info(address)
sig = await client.send_transaction(tx_bytes, skip_preflight=True)
statuses = await client.get_signature_statuses(signatures)
accounts = await client.get_token_accounts(owner)
slot = await client.get_slot()
# helius enhanced (falls back to standard if unavailable)
fees = await client.get_priority_fee_estimate(
account_keys=["JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB"],
priority_level="High",
)
๐ฏ Result Type
all methods return Result[T, RPCError] โ no exceptions to catch:
result = await client.get_balance(address)
if result.is_ok:
lamports = result.unwrap()
print(f"balance: {lamports / 1e9:.4f} SOL")
else:
error = result.unwrap_err()
print(f"failed: {error.code} โ {error.message}")
๐๏ธ Architecture
your code
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโ
โ ResilientRPCClient โ
โโโโโโโโโโโโโโโโโโโโโโโค
โ ResponseCache โ โ dedup + TTL
โโโโโโโโโโโโโโโโโโโโโโโค
โ TokenBucketLimiter โ โ adaptive rate control
โโโโโโโโโโโโโโโโโโโโโโโค
โ CircuitBreaker โ โ failure isolation
โโโโโโโโโโโโโโโโโโโโโโโค
โ ProviderRotator โ โ weighted failover
โ โโ provider A โ
โ
โ โโ provider B โ
โ
โ โโ provider C โ โ โ auto-recovers
โโโโโโโโโโโโโโโโโโโโโโโ
๐ Comparison
| solana-rpc-resilient | raw httpx / aiohttp |
solana-py | |
|---|---|---|---|
| Rate limiting | โ adaptive token bucket | โ manual | โ none |
| Circuit breaker | โ automatic | โ manual | โ none |
| Provider failover | โ weighted rotation | โ single endpoint | โ single endpoint |
| 429 recovery | โ backoff + rotate | โ crash | โ crash |
| Request dedup | โ built-in | โ manual | โ none |
| Result type | โ
Ok / Err |
โ exceptions | โ exceptions |
| Async | โ native | โ | โ ๏ธ sync default |
License
MIT
๐ฆ Also by JinUltimate1995
- jupiter-swap-python โ Jupiter swap client for Python. Async. Typed.
- pumpfun-python โ PumpFun bonding curve + PumpSwap AMM. Direct swaps from Python.
- dexscreener-python โ DexScreener API client for Python.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file solana_rpc_resilient-0.1.0.tar.gz.
File metadata
- Download URL: solana_rpc_resilient-0.1.0.tar.gz
- Upload date:
- Size: 18.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b393da285d6a062d7cf6185bacff3a191ca810bba8dc5993eed4d6b2bd6d6126
|
|
| MD5 |
9d22e83f6948a9be41e63ddea762642c
|
|
| BLAKE2b-256 |
e0a469c1bc73874f100ecbc8d9a76caf88d345bb872551a69a7f8e0a1caec28c
|
File details
Details for the file solana_rpc_resilient-0.1.0-py3-none-any.whl.
File metadata
- Download URL: solana_rpc_resilient-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d54f8168bc43f4199a1d6a7efb16943e690b7d982a55f409ba73a7ddd2cf3b8e
|
|
| MD5 |
f808d0efb1777a05a4d739bd05f3cf2e
|
|
| BLAKE2b-256 |
f6f5c0a8f26db4757ce09d4b8bf052d7e5443b8c4336a754e9637b173714c3a8
|