Solana Python SDK Guide — Building Solana Applications in Python

Practical guide to using Python for Solana development. solana-py, solders, common patterns, and what works (and what doesn't) compared to TypeScript.

BoltTx Team··5 min read
solanapythonsdksoldersdeveloper

If you're a Python developer wanting to build on Solana, the ecosystem is workable but less mature than TypeScript. The two main libraries (solana-py and solders) cover most of what you need; the patterns are similar to web3.js once you know them.

This piece is a practical guide to Solana development in Python: the libraries, the patterns, the gotchas, and when Python is the right choice versus when you should switch to TypeScript or Rust.

The Python Solana Ecosystem

Two main libraries:

solana-py. The longer-standing Python Solana SDK. Provides Connection-style classes, transaction building, RPC method wrappers. Mature but slower-moving than the JS ecosystem.

solders. Newer, Rust-backed Python bindings that provide low-level types (Pubkey, Keypair, Signature) with much better performance than pure-Python equivalents. Often used alongside solana-py.

Modern Python Solana code typically uses both: solders for types, solana-py for higher-level RPC interactions.

Installation

pip install solana solders

Or with poetry / uv. Both are well-supported on PyPI.

Basic RPC Connection

The Python pattern:

from solana.rpc.api import Client
from solders.keypair import Keypair
from solders.pubkey import Pubkey

# Connect to RPC
client = Client("https://your-rpc-url.example/?api-key=...")

# Generate or load a keypair
sender = Keypair()  # or Keypair.from_bytes(...)

# Query balance
balance = client.get_balance(sender.pubkey())
print(balance.value)  # Lamports

Familiar shape if you've used web3.js. The library hides JSON-RPC details.

Sending Transactions

from solders.message import Message
from solders.transaction import Transaction
from solders.system_program import TransferParams, transfer
from solana.rpc.types import TxOpts

# Build a transfer
ix = transfer(TransferParams(
    from_pubkey=sender.pubkey(),
    to_pubkey=recipient.pubkey(),
    lamports=1_000_000,
))

# Get blockhash, build transaction, sign, send
recent_blockhash = client.get_latest_blockhash().value.blockhash

# Build and sign the transaction using solders
msg = Message.new_with_blockhash([ix], sender.pubkey(), recent_blockhash)
tx = Transaction([sender], msg, recent_blockhash)

result = client.send_transaction(
    tx,
    opts=TxOpts(skip_preflight=True, max_retries=0),
)
print(result.value)  # Signature

The patterns mirror web3.js with Python idioms.

Common Python-Specific Considerations

Async vs sync. solana-py has both sync (Client) and async (AsyncClient) variants. For high-volume code, use async. For scripts, sync is fine.

Type stubs. Decent but not perfect. Some methods don't have full type hints. Be ready for # type: ignore occasionally.

Performance. Pure Python is slower than JS for some operations. Where it matters (signing, deserialisation), solders provides Rust-backed implementations that close the gap.

Library versioning. solana-py and solders move semi-independently. Watch for compatibility issues; pin versions in production.

When Python Makes Sense for Solana

Python is the right choice when:

Python is the wrong choice when:

Common Python Solana Patterns

Async batch RPC calls:

import asyncio
from solana.rpc.async_api import AsyncClient

async def fetch_many(client, pubkeys):
    tasks = [client.get_account_info(pk) for pk in pubkeys]
    return await asyncio.gather(*tasks)

async with AsyncClient("https://your-rpc.example") as client:
    results = await fetch_many(client, [key1, key2, key3])

For better performance, prefer getMultipleAccountsInfo (one round-trip) where applicable.

Transaction signing with versioned transactions:

from solders.message import MessageV0
from solders.transaction import VersionedTransaction

msg = MessageV0.try_compile(
    payer=signer.pubkey(),
    instructions=[your_instruction],
    address_lookup_table_accounts=[],
    recent_blockhash=blockhash,
)

tx = VersionedTransaction(msg, [signer])

Versioned transactions support more accounts than legacy transactions; needed for many Jupiter routes.

Subscription example:

from solana.rpc.websocket_api import connect

async with connect("wss://your-rpc.example") as websocket:
    await websocket.account_subscribe(pubkey)
    async for msg in websocket:
        # Handle account change
        pass

WebSocket support exists; quality depends on your provider.

Common Python Mistakes

Using sync client for async-natural code. If you're doing many concurrent operations, async is dramatically better.

Not pinning library versions. solana-py and solders evolve; production code should pin.

Building transactions inefficiently. Naive Python signing is slow; use solders-backed types.

Forgetting to handle RPC errors. Network errors, rate limits, transaction failures. Build defensive code.

Treating it like fully-typed code. Type hints are partial. Don't trust them blindly; test.

Trading Bots in Python

Python is reasonable for some trading bot styles:

Strategy / research bots. Pandas-driven backtest, regime detection, signal generation. Python excels.

Moderate-frequency execution bots. Sub-second is achievable. Sub-100ms is harder; consider hot-path in Rust with Python orchestration.

Backend services for trading systems. API servers, monitoring, dashboards. Python is fine.

For sub-100ms or HFT, write the hot path in Rust and orchestrate from Python.

What to Do This Week

If you're starting Solana in Python:

  1. Install solana-py and solders. Both.
  2. Set up AsyncClient for any production code. Sync for quick scripts.
  3. Use environment variables for RPC URLs. Same pattern as elsewhere.
  4. Build per-signature telemetry. Same value as in any language.
  5. For trading bots, plan the Rust escape hatch. If you need more speed later, you'll want hot path in Rust.
  6. Pin library versions. Pinning isn't optional in production.

Try BoltTx From Python

from solana.rpc.api import Client
from solana.rpc.types import TxOpts

client = Client("https://bolttx.io/?api-key=YOUR_API_KEY")

# ... build your transaction ...

result = client.send_transaction(
    tx,
    opts=TxOpts(skip_preflight=True, max_retries=0),
)

Free tier signup. Works the same from Python as from any other language.

FAQ

Is solana-py actively maintained? Yes, though slower-moving than the JS ecosystem. Watch GitHub for updates.

What about anchorpy? anchorpy provides Anchor-style client generation for Python. Useful if you're calling Anchor programs from Python.

Can I write Solana programs in Python? No. Programs are Rust. Python is for client code only.

Performance difference vs TypeScript? For RPC-bound work, similar. For CPU-bound work (signing, serialisation), Python with solders is competitive; without it, slower.

Which is better, solana-py or solders? Use both. solders for low-level types (faster); solana-py for high-level RPC interactions.

Further Reading

Back to all posts