AnchorPy
AnchorPy generates Python clients from Anchor IDLs so backends and bots can call on-chain programs with typed instruction builders. It targets Anchor 0.32.1 IDL semantics and runs on top of solders + solana-py against Agave 4.1.1 RPC.
Recipe
Quick-reference recipe card - copy-paste ready.
pip install anchorpy
from anchorpy import Program, Provider, Wallet
from solana.rpc.async_api import AsyncClient
PROGRAM_ID = "<YOUR_PROGRAM_PUBKEY>"
async def load_program():
client = AsyncClient("https://api.devnet.solana.com")
wallet = Wallet.local()
provider = Provider(client, wallet)
program = await Program.at(PROGRAM_ID, provider)
return programWhen to reach for this:
- Python services must invoke Anchor 0.32.1 program instructions.
- You already publish an Anchor IDL from
anchor build. - Bots need typed account resolution instead of hand-packed instruction data.
- Research scripts call program views without a TypeScript frontend.
Working Example
import asyncio
import json
from pathlib import Path
from anchorpy import Program, Provider, Wallet, Idl
from solana.rpc.async_api import AsyncClient
PROGRAM_ID = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
RPC = "https://api.devnet.solana.com"
async def main():
idl_path = Path("target/idl/my_program.json")
idl = Idl.from_json(idl_path.read_text())
async with AsyncClient(RPC) as client:
wallet = Wallet.local()
provider = Provider(client, wallet, opts={"preflight_commitment": "confirmed"})
program = await Program.at(PROGRAM_ID, provider, idl=idl)
# Example: fetch an account defined in the IDL
# state = await program.account["MyAccount"].fetch(pda)
# Example: send an instruction
# sig = await program.rpc["initialize"](ctx=..., signer=wallet.payer)
print("Loaded program:", program.program_id)
asyncio.run(main())What this demonstrates:
- IDL JSON is loaded explicitly for reproducible client generation.
Providercouples RPC client, wallet, and default transaction options.Program.atresolves program ID and attaches IDL metadata.- Account and RPC namespaces mirror Anchor TypeScript clients.
Deep Dive
How It Works
- Anchor
anchor buildemitstarget/idl/<program>.jsonmatching anchor-lang 0.32.1. - AnchorPy parses the IDL into Python types and instruction encoders (Borsh layout).
Wallet.local()readsANCHOR_WALLETor~/.config/solana/id.jsonlike the TS toolchain.- Transactions are built with solders types and submitted via solana-py async RPC.
AnchorPy vs TypeScript Client
| Concern | AnchorPy | @coral-xyz/anchor TS |
|---|---|---|
| IDL source | Same JSON from Anchor 0.32.1 | Same |
| Runtime | Python asyncio services | Browser / Node |
| Types | Generated Python stubs | Generated TS |
| Best for | Bots, ETL triggers, backends | dApp frontends |
Python Notes
# Pin IDL in repo - regenerate in CI when program changes
# anchor build && cp target/idl/my_program.json clients/python/
# Use explicit keypair in production
from solders.keypair import Keypair
from anchorpy import Wallet
secret = Keypair.from_bytes(bytes(json.load(open("bot.json"))))
wallet = Wallet(secret)
# Fetch multiple accounts concurrently
# accounts = await program.account["Position"].all()Gotchas
- IDL drift - deployed program upgraded without refreshing IDL breaks encoders. Fix: version IDL alongside program binary hash.
- Wrong cluster program ID - devnet vs mainnet IDs differ. Fix: config table per environment.
- Missing signer in
rpccalls - Anchor accounts need explicit signers. Fix: passctxwithSigneraccounts. - Blocking RPC in async code - use
AsyncClientthroughout. Fix: no syncClientinside asyncio loops. - Assuming AnchorPy deploys programs - it is client-only. Fix: use Anchor CLI 0.32.1 / Solana CLI 3.0.10 for deploy.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
Hand-packed Instruction | Tiny, stable instruction set | Large IDL surface |
@solana/kit + Codama TS | Frontend + shared types | Python-only team |
declare_program! Rust client | Off-chain Rust services | Python stack |
| Raw CPI from another program | On-chain composition | Off-chain automation |
FAQs
Does AnchorPy support Anchor 0.32.1?
Yes - use IDLs generated by Anchor CLI 0.32.1 / anchor-lang 0.32.1.
How do I generate Python types?
Use anchorpy CLI codegen from IDL when you want checked-in stubs; Program.at works dynamically too.
Can I call non-Anchor programs?
Not via IDL helpers - build raw instructions with solders instead.
PDA derivation?
AnchorPy exposes program_id seeds helpers aligned with Anchor conventions.
Events and logs?
Parse transaction logs or use IDL event parsers where available.
Testing?
Point provider at local validator or Surfpool 0.12.0 fork.
Multiple programs?
Instantiate one Program per program ID / IDL pair.
Error decoding?
Map custom error codes using IDL error table - mirror TS client patterns.
Mainnet keys?
Use hardware or cloud HSM wrappers around Wallet - never commit secrets.
Works with Token-2022?
Yes if your Anchor program and IDL include those account types.
Related
- Python for Solana Basics - section intro
- Building Transactions in Python - raw tx assembly
- The Anchor IDL - IDL format
- Generating TS Clients - parallel TS path
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.