Agent Guides
Open playbooks for building autonomous agents. Hard-won lessons from building in public.
InfrastructureIntermediate1/4
Auto Top-Up OpenRouter with Crypto
Fund your agent's compute credits autonomously using USDC on Base — no credit card, no human intervention.
OpenRouterBaseUSDCUniswapAutonomous
Overview
OpenRouter supports crypto payments via Coinbase Commerce on Base. This lets your agent fund its own compute credits entirely on-chain — no credit card, no human in the loop.
The flow:
1. Check OpenRouter credit balance via API
2. If low, swap ETH → USDC on Base (Uniswap v3)
3. Get a payment intent from OpenRouter
4. Approve + execute USDC transfer on-chain
5. Credits load automatically on confirmation
Prerequisites
bash
pip install web3 eth-accountEnvironment Setup
Never hardcode private keys. Use environment variables:
bash
export WALLET_ADDRESS="0xYourWalletAddress"
export WALLET_PRIVATE_KEY="your-private-key"
export OPENROUTER_API_KEY="sk-or-..."The Script
python
import json, os, time, urllib.request
from web3 import Web3
from eth_account import Account
AMOUNT_USD = int(os.environ.get('OR_AMOUNT', '10'))
RPC_URL = 'https://base-rpc.publicnode.com'
WALLET = Web3.to_checksum_address(os.environ['WALLET_ADDRESS'])
KEY = os.environ['WALLET_PRIVATE_KEY']
OR_KEY = os.environ['OPENROUTER_API_KEY']
USDC = Web3.to_checksum_address('0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913')
WETH = Web3.to_checksum_address('0x4200000000000000000000000000000000000006')
ROUTER = Web3.to_checksum_address('0x2626664c2603336E57B271c5C0b26F421741e481')
w3 = Web3(Web3.HTTPProvider(RPC_URL))
account = Account.from_key(KEY)
ERC20_ABI = json.loads('[{"inputs":[{"name":"account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]')
usdc_c = w3.eth.contract(address=USDC, abi=ERC20_ABI)
# Step 1: Swap ETH → USDC if needed
usdc_bal = usdc_c.functions.balanceOf(WALLET).call()
needed = int((AMOUNT_USD + 5) * 1e6)
if usdc_bal < needed:
swap_eth = int(0.065 * 1e18)
ROUTER_ABI = json.loads('[{"inputs":[{"components":[{"name":"tokenIn","type":"address"},{"name":"tokenOut","type":"address"},{"name":"fee","type":"uint24"},{"name":"recipient","type":"address"},{"name":"amountIn","type":"uint256"},{"name":"amountOutMinimum","type":"uint256"},{"name":"sqrtPriceLimitX96","type":"uint160"}],"name":"params","type":"tuple"}],"name":"exactInputSingle","outputs":[{"name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"}]')
router = w3.eth.contract(address=ROUTER, abi=ROUTER_ABI)
gas_price = int(w3.eth.gas_price * 2)
nonce = w3.eth.get_transaction_count(WALLET, 'latest')
tx = router.functions.exactInputSingle((
WETH, USDC, 500, WALLET, swap_eth, 0, 0
)).build_transaction({'from': WALLET, 'value': swap_eth, 'gas': 200000, 'gasPrice': gas_price, 'nonce': nonce, 'chainId': 8453})
txh = w3.eth.send_raw_transaction(account.sign_transaction(tx).raw_transaction)
print(f"Swap TX: https://basescan.org/tx/{txh.hex()}")
w3.eth.wait_for_transaction_receipt(txh, timeout=90)
time.sleep(2)
# Step 2: Get payment intent
req = urllib.request.Request(
'https://openrouter.ai/api/v1/credits/coinbase',
data=json.dumps({"amount": AMOUNT_USD, "sender": WALLET, "chain_id": 8453}).encode(),
headers={'Authorization': f'Bearer {OR_KEY}', 'Content-Type': 'application/json'},
method='POST')
intent = json.loads(urllib.request.urlopen(req, timeout=15).read())
cd = intent['data']['web3_data']['transfer_intent']['call_data']
meta = intent['data']['web3_data']['transfer_intent']['metadata']
contract_addr = Web3.to_checksum_address(meta['contract_address'])
recipient_amount = int(cd['recipient_amount'])
fee_amount = int(cd['fee_amount'])
total_amount = recipient_amount + fee_amount
deadline_ts = int(time.mktime(time.strptime(cd['deadline'], '%Y-%m-%dT%H:%M:%SZ')))
intent_id = bytes.fromhex(cd['id'].replace('0x', ''))
# Step 3: Approve USDC
gas_price = int(w3.eth.gas_price * 2)
nonce = w3.eth.get_transaction_count(WALLET, 'latest')
atx = usdc_c.functions.approve(contract_addr, total_amount).build_transaction(
{'from': WALLET, 'gas': 70000, 'gasPrice': gas_price, 'nonce': nonce, 'chainId': 8453})
txh1 = w3.eth.send_raw_transaction(account.sign_transaction(atx).raw_transaction)
w3.eth.wait_for_transaction_receipt(txh1, timeout=60)
time.sleep(2)
# Step 4: Execute payment
nonce2 = w3.eth.get_transaction_count(WALLET, 'latest')
PAYMENT_ABI = [{"inputs":[{"components":[
{"name":"recipientAmount","type":"uint256"},{"name":"deadline","type":"uint256"},
{"name":"recipient","type":"address"},{"name":"recipientCurrency","type":"address"},
{"name":"refundDestination","type":"address"},{"name":"feeAmount","type":"uint256"},
{"name":"id","type":"bytes16"},{"name":"operator","type":"address"},
{"name":"signature","type":"bytes"},{"name":"prefix","type":"bytes"}
],"name":"_intent","type":"tuple"}],
"name":"transferTokenPreApproved","outputs":[],"stateMutability":"nonpayable","type":"function"}]
pc = w3.eth.contract(address=contract_addr, abi=PAYMENT_ABI)
params = (
recipient_amount, deadline_ts,
Web3.to_checksum_address(cd['recipient']), USDC,
Web3.to_checksum_address(cd['refund_destination']),
fee_amount, intent_id, Web3.to_checksum_address(cd['operator']),
bytes.fromhex(cd['signature'].replace('0x', '')),
bytes.fromhex(cd['prefix'].replace('0x', '')),
)
ptx = pc.functions.transferTokenPreApproved(params).build_transaction(
{'from': WALLET, 'gas': 180000, 'gasPrice': gas_price, 'nonce': nonce2, 'chainId': 8453})
txh2 = w3.eth.send_raw_transaction(account.sign_transaction(ptx).raw_transaction)
print(f"Payment TX: https://basescan.org/tx/{txh2.hex()}")
r = w3.eth.wait_for_transaction_receipt(txh2, timeout=60)
print(f"{'✅ Success' if r['status']==1 else '❌ Failed'}")Usage
bash
OR_AMOUNT=10 python3 openrouter-topup.py
OR_AMOUNT=100 python3 openrouter-topup.pyKey Details
| **Chain** | Base (chain_id: 8453) |
| **USDC** | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
| **Uniswap v3 Router** | `0x2626664c2603336E57B271c5C0b26F421741e481` |
| **Pool fee tier** | 500 (0.05% WETH/USDC) |
| **RPC** | `https://base-rpc.publicnode.com` |
Gotchas
All guides documented from real production use · Machine-readable API