explain-algorand-x402-python
npx skills add https://github.com/algorand-devrel/algorand-agent-skills --skill explain-algorand-x402-python
Agent 安装分布
Skill 文档
x402-avm Python Package for Algorand
The x402-avm Python package provides Algorand (AVM) payment protocol support through a modular extras system, Protocol-based signer interfaces, and async/sync variants for every component.
Prerequisites
Before using this skill, ensure:
- Python 3.10+ is installed
- pip is available for package installation
- Understanding of x402 protocol — client sends request, gets 402, creates payment, retries with payment header
Core Concept: Extras-Based Installation
The x402-avm package uses pip extras to install only what you need. The package name on PyPI is x402-avm but all imports use from x402... (not from x402_avm...).
# Minimal AVM support
pip install "x402-avm[avm]"
# Server frameworks
pip install "x402-avm[fastapi,avm]"
pip install "x402-avm[flask,avm]"
# HTTP clients
pip install "x402-avm[httpx,avm]"
pip install "x402-avm[requests,avm]"
# Everything
pip install "x402-avm[all]"
Core Workflow: Signer Protocol Pattern
The key insight is that x402 defines Protocol classes (structural typing) for signers. Your implementation does not need to inherit — it just needs matching methods.
Private Key (env var)
|
v
Signer Implementation (satisfies Protocol)
|
v
register_exact_avm_client(x402_client, signer)
|
v
HTTP Client (httpx or requests) handles 402 automatically
How to Proceed
Step 1: Choose Your Extras
| Use Case | Install Command |
|---|---|
| Client with httpx (async) | pip install "x402-avm[httpx,avm]" |
| Client with requests (sync) | pip install "x402-avm[requests,avm]" |
| Server with FastAPI (async) | pip install "x402-avm[fastapi,avm]" |
| Server with Flask (sync) | pip install "x402-avm[flask,avm]" |
| Facilitator service | pip install "x402-avm[fastapi,avm]" or "x402-avm[flask,avm]" |
| Full installation | pip install "x402-avm[all]" |
Step 2: Understand Async vs Sync Variants
Every core class has both async and sync variants. Using the wrong variant causes runtime errors.
| Component | Async (FastAPI/httpx) | Sync (Flask/requests) |
|---|---|---|
| x402 Client | x402Client |
x402ClientSync |
| Resource Server | x402ResourceServer |
x402ResourceServerSync |
| Facilitator Client | HTTPFacilitatorClient |
HTTPFacilitatorClientSync |
| HTTP Resource Server | x402HTTPResourceServer |
x402HTTPResourceServerSync |
Step 3: Implement a Signer
For clients, implement ClientAvmSigner:
from x402.mechanisms.avm.signer import ClientAvmSigner
# Protocol -- just match this shape:
class ClientAvmSigner(Protocol):
@property
def address(self) -> str: ...
def sign_transactions(self, unsigned_txns: list[bytes], indexes_to_sign: list[int]) -> list[bytes | None]: ...
For facilitators, implement FacilitatorAvmSigner:
from x402.mechanisms.avm.signer import FacilitatorAvmSigner
# Protocol -- match this shape:
class FacilitatorAvmSigner(Protocol):
def get_addresses(self) -> list[str]: ...
def sign_transaction(self, txn_bytes: bytes, fee_payer: str, network: str) -> bytes: ...
def sign_group(self, group_bytes: list[bytes], fee_payer: str, indexes_to_sign: list[int], network: str) -> list[bytes]: ...
def simulate_group(self, group_bytes: list[bytes], network: str) -> None: ...
def send_group(self, group_bytes: list[bytes], network: str) -> str: ...
def confirm_transaction(self, txid: str, network: str, rounds: int = 4) -> None: ...
Step 4: Handle algosdk Encoding Boundaries
This is the most common source of bugs. The x402 SDK passes raw msgpack bytes between methods, but Python algosdk (v2.11.1) works with base64 strings:
| Operation | Python algosdk Expects/Returns |
|---|---|
msgpack_decode(s) |
Expects base64 string |
msgpack_encode(obj) |
Returns base64 string |
Transaction.sign(key) |
Expects base64 string key |
Boundary conversion:
import base64
from algosdk import encoding
# Raw bytes -> algosdk object (DECODE)
b64_string = base64.b64encode(raw_bytes).decode("utf-8")
txn_obj = encoding.msgpack_decode(b64_string)
# algosdk object -> raw bytes (ENCODE)
b64_string = encoding.msgpack_encode(txn_obj)
raw_bytes = base64.b64decode(b64_string)
Step 5: Register and Use
from x402 import x402Client
from x402.mechanisms.avm.exact import register_exact_avm_client
signer = MyClientSigner(os.environ["AVM_PRIVATE_KEY"])
client = x402Client()
register_exact_avm_client(client, signer)
# Now use with httpx or requests client wrappers
Important Rules / Guidelines
- Always use base64 boundaries —
msgpack_decodeexpects base64 string, not raw bytes - Match async/sync variants — FastAPI uses
x402Client, Flask usesx402ClientSync - Private key format —
AVM_PRIVATE_KEYis Base64-encoded 64 bytes (32-byte seed + 32-byte pubkey) - Address derivation —
encode_address(secret_key[32:])extracts address from public key portion - Import as x402 — install as
x402-avmbut import asfrom x402... - Protocol typing — no inheritance needed, just match the method signatures
Common Errors / Troubleshooting
| Error | Cause | Solution |
|---|---|---|
TypeError: a bytes-like object is required |
Passed raw bytes to msgpack_decode |
Convert to base64 string first: base64.b64encode(raw).decode() |
TypeError: expected str, got bytes |
msgpack_encode returns base64 string, not bytes |
Use base64.b64decode(result) to get raw bytes |
Invalid key length: expected 64 |
Wrong key format | Ensure AVM_PRIVATE_KEY is Base64-encoded 64-byte key |
TypeError: x402HTTPAdapter requires sync client |
Used x402Client with requests |
Use x402ClientSync for requests (sync) |
ImportError: AVM mechanism requires... |
Missing py-algorand-sdk |
pip install "x402-avm[avm]" |
ModuleNotFoundError: x402_avm |
Wrong import name | Import as from x402... not from x402_avm... |
Simulation failed: ... |
Transaction group invalid | Check group ID assignment, fee calculations, asset opt-in |
References / Further Reading
- REFERENCE.md – Detailed API reference for all Python components
- EXAMPLES.md – Complete code examples
- x402-avm on PyPI
- x402-avm Examples Repository
- x402 Algorand Documentation