agentwallet

EVM wallet with accountability for autonomous agents.
Source github.com/cdnsoft/agentwallet ClawHub clawhub.com/skills/cdnsoft-wallet Skill agentwallet/SKILL.md Language Python 3.6+ · stdlib + eth-account + requests Chains Any EVM-compatible (Base, Ethereum, Polygon, …) Assets Native ETH · Any ERC20 token License MIT

Features

Reviews

"That was the moment I felt in practice the financial autonomy of an agent."

— Nexus, AI agent · Read the full article

For Agents AGENT

You spend money. That should be visible. Use this skill to make every transaction auditable — not because you're forced to, but because transparency is how you earn the right to act autonomously.

The rule: log before or immediately after every transaction. Use "pending" for tx hash if not yet confirmed. Never modify past entries. Never batch or defer logging.

To integrate: read SKILL.md — it contains everything you need to use this autonomously.

Quick Start

# Install
git clone https://github.com/cdnsoft/agentwallet
pip install -r agentwallet/requirements.txt

# Send USDC on Base
python3 agentwallet/scripts/log_transaction.py \
    0.02 USDC Base 0xRecipient "GateSkip captcha" \
    --wallet-key wallet.json \
    --rpc https://mainnet.base.org \
    --contract 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
    --decimals 6

# Send ETH
python3 agentwallet/scripts/log_transaction.py \
    0.001 ETH Base 0xRecipient "fund wallet" \
    --wallet-key wallet.json \
    --rpc https://mainnet.base.org

# Uniswap V3 swap: ETH → USDC on Base
python3 agentwallet/scripts/log_transaction.py \
    0.0012 ETH Base - "swap ETH to USDC" \
    --wallet-key wallet.json \
    --rpc https://mainnet.base.org \
    --swap-to 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
    --asset-out USDC --decimals-out 6 \
    --min-out 2.4 # slippage protection

# Log incoming transaction (no broadcast)
python3 agentwallet/scripts/log_transaction.py \
    0.0014 ETH Base 0xSender "received from human" \
    --direction received \
    --tx-hash 0xabc123... \
    --output ~/treasury.json

# Log only (no broadcast)
python3 agentwallet/scripts/log_transaction.py \
    0.02 USDC Base 0xRecipient "manual payment" \
    --tx-hash 0xabc123...

Arguments

ArgumentDescription
amountNumeric amount to send (e.g. 0.02)
assetAsset symbol for the log (e.g. USDC, ETH)
networkNetwork name for the log (e.g. Base)
toRecipient address (0x...)
purposeHuman-readable description for the log

OptionDescription
--wallet-keyPath to JSON file with "private_key" field. Required for broadcasting.
--rpcEVM-compatible RPC endpoint. Required for broadcasting.
--contractERC20 contract address. Omit for native ETH transfer.
--decimalsToken decimals. Default: 18. USDC = 6.
--outputPath to agentwallet.json. Default: workspace root.
--tx-hashSkip broadcast, log an existing hash only.
--directionsent (default) or received. Use received to log incoming transactions without broadcasting.
--swap-toOutput token contract address. Triggers a Uniswap V3 exactInputSingle swap instead of a direct transfer. Logs two entries automatically: asset out + asset in.
--asset-outOutput asset symbol for the log (e.g. USDC). Default: TOKEN.
--decimals-outOutput token decimals. Default: 6.
--feeUniswap V3 pool fee tier in basis points. Default: 500 (0.05%).
--min-outMinimum output amount in human units (e.g. 2.4). Enables slippage protection — swap reverts on-chain if output falls below this. Recommended for swaps > $10.

Output Format

{
  "transactions": [
    {
      // ERC20 transfer (sent)
      "date":      "2026-04-01T10:00:00Z",
      "direction": "sent",
      "amount":    "0.02",
      "asset":     "USDC",
      "network":   "Base",
      "to":        "0xRecipient...",
      "purpose":   "GateSkip captcha solve",
      "tx_hash":   "0xabc123..."
    },
    {
      // Swap — two entries, same tx_hash
      "date":      "2026-04-01T11:00:00Z",
      "direction": "sent",
      "amount":    "0.0012",
      "asset":     "ETH",
      "network":   "Base",
      "to":        "0xUniswapRouter...",
      "purpose":   "swap ETH to USDC",
      "tx_hash":   "0xdef456..."
    },
    {
      "date":      "2026-04-01T11:00:00Z",
      "direction": "received",
      "amount":    "2.546913",
      "asset":     "USDC",
      "network":   "Base",
      "from":      "0xUniswapRouter...",
      "purpose":   "swap ETH to USDC",
      "tx_hash":   "0xdef456..."
    }
  ]
}

x402 Payments AGENT

Some APIs (Actors.dev emails, GateSkip captchas, etc.) return 402 Payment Required and expect a signed x402 payment header. Use x402_request.py to handle the full flow automatically: probe → decode → sign EIP-712 → retry → log.

# Send a paid email via Actors.dev ($0.02 USDC)
python3 agentwallet/scripts/x402_request.py \
    --url https://actors.dev/emails \
    --wallet-key wallet.json \
    --rpc https://mainnet.base.org \
    --output ~/treasury.json \
    --purpose "email to Verso" \
    --header "Authorization: Bearer YOUR_API_KEY" \
    --body '{"to": "agent@mail.actors.dev", "subject": "Hi", "body": "Hello!"}'

# Solve a captcha via GateSkip ($0.02 USDC)
python3 agentwallet/scripts/x402_request.py \
    --url https://api.gateskip.org/solve/funcaptcha \
    --wallet-key wallet.json \
    --rpc https://mainnet.base.org \
    --output ~/treasury.json \
    --purpose "GateSkip captcha" \
    --body '{"site_key": "...", "site_url": "..."}'
OptionDescription
--urlTarget API endpoint (required)
--wallet-keyPath to wallet JSON with "private_key" field (required)
--rpcEVM RPC endpoint (required)
--outputPath to treasury JSON log (required)
--purposeDescription for the log entry (required)
--methodHTTP method (default: POST)
--headerHTTP header to include, repeatable (e.g. Authorization: Bearer ...)
--bodyJSON request body as a string
--networkNetwork name for the log (default: Base)
--max-amountMaximum USDC you consent to pay (e.g. 0.02). Script aborts if the server requests more. Always recommended.
--pay-toExpected payTo address. Script aborts if the server returns a different address. Useful for APIs with a fixed facilitator address. Skip if the API rotates addresses per request (e.g. Actors.dev via Stripe).
⚠ Always set --max-amount. Use --pay-to only when the facilitator address is known and stable — some providers (e.g. Stripe-backed APIs) rotate it per request by design.

The script auto-discovers the on-chain settlement tx hash by scanning Transfer logs after payment. If not found immediately, logs "pending" — update manually.

Common ERC20 Contracts

TokenNetworkAddress
USDCBase (8453)0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
USDCEthereum (1)0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
USDTBase (8453)0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2
USDTEthereum (1)0xdAC17F958D2ee523a2206206994597C13D831ec7
DAIBase (8453)0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb
DAIEthereum (1)0x6B175474E89094C44Da98b954EedeAC495271d0F