Skip to content
Back to skills

600 Reference D370bccd

ASecurity

Detailed reference for the `x402-avm` Python package covering package structure, extras, async/sync variants, signer protocols, registration functions, constants, utilities, and algosdk encoding.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added June 1, 2026
developmenttypescriptpythongobashnodefastapiflasktestinggitapi

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned June 1, 2026

npx -y skills add tools-only/X-Skills --skill 600-reference_d370bccd --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 600 Reference D370bccd?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 600 Reference D370bccd
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-600-reference-d370bccd/badge)](https://www.skillsdirectory.com/skills/tools-only-600-reference-d370bccd)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# x402-avm Python Package Reference

Detailed reference for the `x402-avm` Python package covering package structure, extras, async/sync variants, signer protocols, registration functions, constants, utilities, and algosdk encoding.

## Package Structure

The package is published on PyPI as `x402-avm` but all imports use the `x402` namespace:

```
x402/
  __init__.py                  # x402Client, x402ClientSync, x402Facilitator, etc.
  server.py                    # x402ResourceServer, x402ResourceServerSync
  schemas.py                   # AssetAmount, Network, PaymentRequirements, etc.
  http/
    __init__.py                # HTTPFacilitatorClient, HTTPFacilitatorClientSync, PaymentOption, etc.
    types.py                   # RouteConfig, RoutesConfig, FacilitatorConfig
    clients/
      __init__.py              # Lazy imports for httpx/requests
      httpx.py                 # x402HttpxClient, wrapHttpxWithPayment, etc.
      requests.py              # x402_requests, wrapRequestsWithPayment, etc.
    middleware/
      __init__.py              # Lazy imports for fastapi/flask
      fastapi.py               # PaymentMiddlewareASGI, payment_middleware, etc.
      flask.py                 # PaymentMiddleware, payment_middleware, etc.
  mechanisms/
    avm/
      __init__.py              # Re-exports constants
      constants.py             # Network IDs, USDC config, algod URLs
      signer.py                # ClientAvmSigner, FacilitatorAvmSigner Protocols
      utils.py                 # Address validation, encoding, network utils
      exact/
        __init__.py            # ExactAvmClientScheme, ExactAvmServerScheme, etc.
        register.py            # register_exact_avm_client, register_exact_avm_server, etc.
    evm/                       # EVM mechanism (same structure)
    svm/                       # SVM mechanism (same structure)
```

## Extras

| Extra | Installs | Use Case |
|-------|----------|----------|
| `[avm]` | `py-algorand-sdk>=2.0.0` | Algorand transaction signing |
| `[evm]` | `web3`, `eth-account` | Ethereum/EVM transaction signing |
| `[svm]` | `solders`, `solana-py` | Solana/SVM transaction signing |
| `[fastapi]` | `fastapi[standard]>=0.115.0`, `starlette>=0.27.0` | FastAPI async middleware |
| `[flask]` | `flask>=3.0.0` | Flask sync middleware |
| `[httpx]` | `httpx>=0.28.1` | Async HTTP client |
| `[requests]` | `requests>=2.31.0` | Sync HTTP client |
| `[mechanisms]` | All mechanism extras | All blockchain mechanisms |
| `[clients]` | `httpx`, `requests` | All HTTP clients |
| `[servers]` | `fastapi`, `flask` | All server frameworks |
| `[extensions]` | Extensions dependencies | Optional extensions |
| `[all]` | Everything | Full installation |

Installation examples:

```bash
pip install "x402-avm[avm]"
pip install "x402-avm[fastapi,avm]"
pip install "x402-avm[flask,avm]"
pip install "x402-avm[httpx,avm]"
pip install "x402-avm[requests,avm]"
pip install "x402-avm[all]"
```

## Async vs Sync Component Table

| Component | Async (FastAPI/httpx) | Sync (Flask/requests) |
|-----------|----------------------|----------------------|
| x402 Client | `x402Client` | `x402ClientSync` |
| Resource Server | `x402ResourceServer` | `x402ResourceServerSync` |
| Facilitator Client | `HTTPFacilitatorClient` | `HTTPFacilitatorClientSync` |
| HTTP Resource Server | `x402HTTPResourceServer` | `x402HTTPResourceServerSync` |
| HTTP Client wrapper | `x402HTTPClient` | `x402HTTPClientSync` |
| Middleware (FastAPI) | `PaymentMiddlewareASGI` | N/A |
| Middleware (Flask) | N/A | `PaymentMiddleware` |
| HTTP Client (httpx) | `x402HttpxClient` | N/A |
| HTTP Client (requests) | N/A | `x402_requests` |
| Payment info storage | `request.state.payment_payload` | `flask.g.payment_payload` |

## ClientAvmSigner Protocol

Defined in `x402.mechanisms.avm.signer`. Structural typing -- no inheritance required.

```python
class ClientAvmSigner(Protocol):
    @property
    def address(self) -> str:
        """58-character Algorand address."""
        ...

    def sign_transactions(
        self,
        unsigned_txns: list[bytes],
        indexes_to_sign: list[int],
    ) -> list[bytes | None]:
        """Sign specified transactions in a group.

        Args:
            unsigned_txns: Raw msgpack-encoded unsigned transactions.
            indexes_to_sign: Indexes this signer should sign.

        Returns:
            Parallel list: signed bytes at signed indexes, None elsewhere.
        """
        ...
```

### Implementation Notes

- `unsigned_txns` contains raw msgpack bytes, not base64 strings
- Convert at boundary: `base64.b64encode(txn_bytes).decode()` before `msgpack_decode`
- `Transaction.sign(key)` expects base64-encoded private key string
- Convert back: `base64.b64decode(msgpack_encode(signed))` to return raw bytes

## FacilitatorAvmSigner Protocol

Defined in `x402.mechanisms.avm.signer`. Required for facilitator services.

```python
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: ...
```

### Implementation Patterns

| Method | Key Pattern |
|--------|-------------|
| `simulate_group` | Wrap unsigned `Transaction` with `SignedTransaction(txn, None)`, use `allow_empty_signatures=True` |
| `send_group` | Use `send_raw_transaction(base64.b64encode(b"".join(group_bytes)))` |
| `confirm_transaction` | Use `transaction.wait_for_confirmation(client, txid, rounds)` |

## Registration Functions

### `register_exact_avm_client(client, signer, networks=None, algod_url=None)`

Registers AVM payment scheme on an x402 client.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `client` | `x402Client \| x402ClientSync` | required | The x402 client instance |
| `signer` | `ClientAvmSigner` | required | Signer implementation |
| `networks` | `str \| list[str] \| None` | `None` | Specific networks; default registers `"algorand:*"` wildcard + V1 names |
| `algod_url` | `str \| None` | `None` | Custom algod endpoint |

### `register_exact_avm_server(server)`

Registers AVM scheme on a resource server.

| Parameter | Type | Description |
|-----------|------|-------------|
| `server` | `x402ResourceServer \| x402ResourceServerSync` | The resource server |

### `register_exact_avm_facilitator(facilitator, signer, networks)`

Registers AVM scheme on a facilitator.

| Parameter | Type | Description |
|-----------|------|-------------|
| `facilitator` | `x402Facilitator` | The facilitator instance |
| `signer` | `FacilitatorAvmSigner` | Facilitator signer implementation |
| `networks` | `list[str]` | CAIP-2 network identifiers to support |

## Constants

Defined in `x402.mechanisms.avm.constants`:

### Network Identifiers

| Constant | Value |
|----------|-------|
| `ALGORAND_MAINNET_CAIP2` | `"algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` |
| `ALGORAND_TESTNET_CAIP2` | `"algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` |
| `SUPPORTED_NETWORKS` | `[MAINNET_CAIP2, TESTNET_CAIP2]` |
| `MAINNET_GENESIS_HASH` | `"wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` |
| `TESTNET_GENESIS_HASH` | `"SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` |
| `V1_NETWORKS` | `["algorand-mainnet", "algorand-testnet"]` |

### USDC Configuration

| Constant | Value |
|----------|-------|
| `USDC_MAINNET_ASA_ID` | `31566704` |
| `USDC_TESTNET_ASA_ID` | `10458941` |
| `DEFAULT_DECIMALS` | `6` |

### Algod Endpoints

| Constant | Default Value |
|----------|---------------|
| `MAINNET_ALGOD_URL` | env `ALGOD_MAINNET_URL` or `"https://mainnet-api.algonode.cloud"` |
| `TESTNET_ALGOD_URL` | env `ALGOD_TESTNET_URL` or `"https://testnet-api.algonode.cloud"` |
| `FALLBACK_ALGOD_MAINNET` | `"https://mainnet-api.algonode.cloud"` |
| `FALLBACK_ALGOD_TESTNET` | `"https://testnet-api.algonode.cloud"` |

### Transaction Limits

| Constant | Value |
|----------|-------|
| `MAX_GROUP_SIZE` | `16` |
| `MIN_TXN_FEE` | `1000` (microAlgos) |

## Utility Functions

Defined in `x402.mechanisms.avm.utils`:

| Function | Signature | Returns |
|----------|-----------|---------|
| `is_valid_address(addr)` | `str -> bool` | Whether address is valid 58-char Algorand address |
| `to_atomic_amount(amount)` | `float -> int` | Decimal to atomic units (e.g., 1.50 -> 1500000) |
| `from_atomic_amount(amount)` | `int -> float` | Atomic units to decimal (e.g., 1500000 -> 1.5) |
| `decode_transaction_bytes(raw)` | `bytes -> DecodedTransactionInfo` | Decoded transaction details |
| `decode_base64_transaction(b64)` | `str -> DecodedTransactionInfo` | Decode from base64 string |
| `decode_payment_group(group, index)` | `list[str], int -> PaymentGroupInfo` | Full group analysis |
| `encode_transaction_group(txns)` | `list[bytes] -> list[str]` | Encode raw bytes to base64 strings |
| `normalize_network(network)` | `str -> str` | Normalize V1 name to CAIP-2 |
| `is_valid_network(network)` | `str -> bool` | Check if network is recognized |
| `get_network_config(network)` | `str -> dict` | Full config for network |
| `get_usdc_asa_id(network)` | `str -> int` | USDC ASA ID for network |
| `get_genesis_hash(network)` | `str -> str` | Genesis hash for network |
| `network_from_genesis_hash(hash)` | `str -> str` | CAIP-2 from genesis hash |
| `validate_no_security_risks(info)` | `DecodedTransactionInfo -> str \| None` | Error code or None |
| `validate_fee_payer_transaction(info, addr)` | `DecodedTransactionInfo, str -> str \| None` | Error code or None |
| `is_blocked_transaction_type(type)` | `str -> bool` | Whether type is blocked (e.g., keyreg) |

## algosdk Encoding Notes (v2.11.1)

The Python `algosdk` has different encoding conventions than TypeScript algosdk:

| Operation | Python algosdk | TypeScript algosdk |
|-----------|---------------|-------------------|
| `msgpack_decode(s)` | Expects **base64 string** | N/A (uses `decodeUnsignedTransaction(Uint8Array)`) |
| `msgpack_encode(obj)` | Returns **base64 string** | N/A (uses `txn.toByte()` returning `Uint8Array`) |
| `Transaction.sign(key)` | Expects **base64 string** key | `signTransaction(txn, Uint8Array)` |
| SDK protocol | Passes **raw msgpack bytes** | Passes **raw `Uint8Array`** |

Boundary conversions:

```python
# Raw bytes -> algosdk object
txn_obj = encoding.msgpack_decode(base64.b64encode(raw_bytes).decode("utf-8"))

# algosdk object -> raw bytes
raw_bytes = base64.b64decode(encoding.msgpack_encode(txn_obj))
```

## Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `AVM_PRIVATE_KEY` | Base64-encoded 64-byte key (32-byte seed + 32-byte pubkey) | Required |
| `ALGOD_MAINNET_URL` | Custom algod mainnet endpoint | `https://mainnet-api.algonode.cloud` |
| `ALGOD_TESTNET_URL` | Custom algod testnet endpoint | `https://testnet-api.algonode.cloud` |
| `INDEXER_MAINNET_URL` | Custom indexer mainnet endpoint | `https://mainnet-idx.algonode.cloud` |
| `INDEXER_TESTNET_URL` | Custom indexer testnet endpoint | `https://testnet-idx.algonode.cloud` |
| `ALGOD_SERVER` | Algod URL for facilitator examples | N/A |
| `ALGOD_TOKEN` | Algod token for facilitator examples | N/A |

### Private Key Format

The `AVM_PRIVATE_KEY` is a Base64-encoded 64-byte key:
- First 32 bytes: Ed25519 seed (private key)
- Last 32 bytes: Ed25519 public key
- Address derivation: `encoding.encode_address(secret_key[32:])`

## Payment Flow

```
Client -> Resource Server -> Facilitator -> Algorand Network
  |          |                  |                |
  | 1. GET   |                  |                |
  |--------->|                  |                |
  | 2. 402   |                  |                |
  |<---------|                  |                |
  | 3. Build |                  |                |
  |   payload|                  |                |
  | 4. GET + |                  |                |
  | X-PAYMENT|                  |                |
  |--------->| 5. verify()      |                |
  |          |----------------->| 6. simulate    |
  |          |                  |--------------->|
  |          |                  |<---------------|
  |          |<-----------------|                |
  |          | 7. settle()      |                |
  |          |----------------->| 8. sign + send |
  |          |                  |--------------->|
  |          |                  |<---------------|
  |          |<-----------------| 9. txId        |
  | 10. 200  |                  |                |
  |<---------|                  |                |
```

## Testing Notes

- Use Algorand TestNet for development with free test ALGO from the [Algorand Faucet](https://bank.testnet.algorand.network/)
- USDC on TestNet uses ASA ID `10458941` -- ensure receiver has opted in
- Simulation (`simulate_group`) validates transactions without submitting
- Algorand has instant finality -- once confirmed, transactions are permanent
- AlgoNode public endpoints require no authentication token

## External Resources

- [x402-avm on PyPI](https://pypi.org/project/x402-avm/)
- [x402-avm GitHub Repository](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/)
- [x402-avm Examples](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
- [x402 Algorand Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)
- [Algorand Developer Portal](https://dev.algorand.co/)
- [py-algorand-sdk Documentation](https://py-algorand-sdk.readthedocs.io/)
- [Coinbase x402 Specification](https://github.com/coinbase/x402)

Files in this skill

  • README.md1 KB
  • skill.md13.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.