Skip to main content

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

Metadata

Release files for solana-rpc-resilient 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for solana-rpc-resilient 0.1.1
File Size Uploaded
solana_rpc_resilient-0.1.1.tar.gz 18.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for solana-rpc-resilient 0.1.1
File Interpreter ABI Platform
solana_rpc_resilient-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 38.3 kB

Release files / solana_rpc_resilient-0.1.1.tar.gz

Download URL solana_rpc_resilient-0.1.1.tar.gz
Size 18.9 kB
Tags Source
SHA-256 checksum
How to use checksums
5de81e86721d4e41de60e7cf7487a7b2077c8ea7ad7d50131588a2f7f50c9968
BLAKE2b-256 checksum
How to use checksums
415d0a8fbc07a8cf84a4265124308290e0455d544668069e03b9e84c1de614d4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.12

Release files / solana_rpc_resilient-0.1.1-py3-none-any.whl

Download URL solana_rpc_resilient-0.1.1-py3-none-any.whl
Size 19.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c2c480b50a35b635f34c4de0d0c01c6779ec66ee54f5c94e18876bf4d7ae8b94
BLAKE2b-256 checksum
How to use checksums
158bd90c104145eefbbd0e771bbb697f8f7274387560b21f4cc9f6cb66034513
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.12

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page