This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Vend - Monetized Transaction History API using x402 and Alchemy
Vend is an open-source blockchain data vending machine that enables pay-per-query access to blockchain data:
- x402 protocol - HTTP-based micropayments (USDC on Base) with 402 Payment Required status
- Alchemy SDK - Fast, reliable blockchain data across multiple chains
- Express.js - Payment-gated REST API backend
- Vending machine model - Insert payment → Get data instantly (no accounts, no API keys)
npm install # Install dependencies
npm run dev # Start with auto-reload (development mode)
npm start # Start production servernpm test # Run all tests
npm test:watch # Run tests in watch mode
npm test -- --coverage # Run tests with coveragecp .env.example .env # Copy environment template
# Edit .env with your Alchemy API key and payment addressnpm test -- tests/api.test.js # Run specific test file
npm test -- -t "health" # Run tests matching pattern- Client requests
/api/transfers→ Server responds402 Payment Required - Client sends USDC payment on Base network
- Client retries request with
X-Payment-Hashheader containing transaction hash - Server verifies payment → Queries Alchemy → Returns blockchain data
Payment Middleware (src/middleware/payment.js)
- Implements x402 protocol
- Returns 402 with payment instructions if no payment proof
- Verifies payment on-chain via Alchemy SDK (production-ready implementation)
- Queries Base blockchain for USDC transfer events
- Validates recipient address and payment amount
- Attaches payment info to
req.paymentfor successful verifications
Alchemy Service (src/services/alchemy.js)
- Wraps Alchemy SDK for asset transfers, token balances, and metadata
- Handles pagination, network mapping, and error handling
- Main functions:
getAssetTransfers(),getTokenBalances(),getTokenMetadata()
Routes (src/routes/)
transfers.js: Main API endpoint for transaction history with payment gating- Validates query parameters (address, category, fromBlock, toBlock, etc.)
- Returns paginated results with payment and pagination metadata
Configuration (src/config.js)
- Loads environment variables via dotenv
- Validates required config on startup (ALCHEMY_API_KEY, PAYMENT_ADDRESS)
- Provides typed config object for app
Error Handling (src/middleware/errorHandler.js)
- Global error handler catches all unhandled errors
- Returns structured JSON error responses
- Includes stack traces in development only
Payment Verification Status ✅ PRODUCTION READY
- Production-ready on-chain payment verification implemented
- Queries Base blockchain (Sepolia/Mainnet) via Alchemy SDK
- Verifies USDC transfers by parsing ERC20 Transfer events
- Validates:
- Transaction exists and succeeded (status === 1)
- USDC contract address matches (Base Sepolia: 0x036CbD53842c5426634e7929541eC2318f3dCF7e, Base Mainnet: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913)
- Recipient address matches
PAYMENT_ADDRESS - Amount is >=
PAYMENT_PRICE_PER_QUERY(with 0.000001 USDC tolerance)
- Development mode still accepts
X-Payment-Hash: demofor testing
Network Configuration
- Alchemy network set via
ALCHEMY_NETWORKenv var (eth-mainnet, polygon-mainnet, base-mainnet, etc.) - Payment network set via
PAYMENT_NETWORK(base-sepolia for testnet, base-mainnet for production) - Network mapping in
src/services/alchemy.jsconverts config names to Alchemy SDK Network constants
Pagination
- Alchemy limits responses to 1000 transfers per request
- Use
pageKeyfrom response for subsequent requests - Page keys expire after 10 minutes
- Vend passes through Alchemy's pagination transparently
Transfer Categories
external: ETH transfers between EOAsinternal: ETH transfers from smart contractserc20: ERC-20 token transferserc721: NFT transferserc1155: Multi-token standard transfersspecialnft: Special NFT collections like CryptoPunks
Required:
ALCHEMY_API_KEY- Alchemy API key from dashboard.alchemy.comPAYMENT_ADDRESS- Ethereum address to receive payments
Optional:
PORT- Server port (default: 3000)ALCHEMY_NETWORK- Network to query (default: eth-mainnet)PAYMENT_NETWORK- Payment network (default: base-sepolia)PAYMENT_PRICE_PER_QUERY- Price in USD (default: 0.01)LOG_LEVEL- Pino log level (default: info)NODE_ENV- Environment (development/production)
src/
├── index.js # Express app setup, routes registration, server startup
├── config.js # Environment configuration and validation
├── logger.js # Pino logger configuration
├── middleware/
│ ├── payment.js # x402 payment verification (NEEDS PRODUCTION IMPL)
│ └── errorHandler.js # Global error handling
├── routes/
│ └── transfers.js # Transaction history endpoint
└── services/
└── alchemy.js # Alchemy SDK wrapper
Why this structure?
- Middleware handles cross-cutting concerns (payments, errors)
- Services abstract external APIs (Alchemy)
- Routes contain endpoint logic and validation
- Config centralized for easy testing and environment switching
- Create route file in
src/routes/(e.g.,balances.js) - Implement service logic in
src/services/if needed - Apply
paymentRequired()middleware with appropriate price - Register route in
src/index.js:app.use('/api/balances', balancesRouter) - Add tests in
tests/ - Update README.md with endpoint documentation
Real payment verification is now implemented in src/middleware/payment.js:
- ✅ Queries Base network via Alchemy SDK for transaction by hash
- ✅ Verifies transaction receipt status is successful (status === 1)
- ✅ Parses USDC transfer event from logs (ERC20 Transfer event signature: 0xddf252ad...)
- ✅ Validates recipient address matches
config.payment.address - ✅ Validates amount is >=
expectedAmount(with tolerance for rounding) - ✅ Handles both Base Sepolia and Base Mainnet USDC contracts
- Future enhancement: Could integrate x402 facilitator API for faster verification
- Add network to
NETWORK_MAPinsrc/services/alchemy.js - Update
.env.examplewith new network options - Test with network-specific addresses
- Document in README and tutorials
express- Web frameworkalchemy-sdk- Blockchain data queriespino/pino-pretty- Structured loggingdotenv- Environment configurationcors- CORS handlingjest+supertest- Testing
Payment verification requires Alchemy API key ✅
- Payment verification queries Base blockchain via Alchemy
- Uses the same API key as blockchain data queries
- Monitor Alchemy usage to ensure sufficient compute units for both data + payment verification
x402-express package doesn't exist
- Custom implementation provided in
src/middleware/payment.js - Based on x402 protocol specification
- Can be replaced with official package when available
Demo mode bypass
- Development mode allows
X-Payment-Hash: demoto skip payment - Controlled by
NODE_ENV=developmentcheck - Never enable in production
Payment verification timing
- Each payment verification requires 1 blockchain query (~150 CU)
- Transactions must be confirmed before verification succeeds
- Base transactions typically confirm in 2-10 seconds
- Consider caching payment hashes to avoid re-verification for repeated requests
Alchemy rate limits
- Free tier: 300M compute units/month
getAssetTransferscosts ~150 CU per call- Monitor usage at dashboard.alchemy.com
- Implement caching for high-traffic scenarios
Page key expiration
- Alchemy pagination keys expire after 10 minutes
- If pageKey fails, restart pagination from beginning
- Consider caching full result sets for expensive queries
Tests use Jest with ES modules (note --experimental-vm-modules in package.json scripts).
Test structure:
tests/api.test.js- API endpoint tests with supertesttests/payment.test.js- Payment middleware unit tests
Running tests:
- Requires
ALCHEMY_API_KEYin.envfor integration tests - Some tests skip if API key not configured
- Use
demopayment hash to bypass payment in tests
Mocking:
- Mock Alchemy SDK in tests to avoid API calls
- Mock payment verification for deterministic tests
Comprehensive guides in /docs:
getting-started.md- Setup and first queryx402-integration.md- Payment protocol deep divealchemy-guide.md- Advanced blockchain queriesdeployment.md- Production deployment options
Common extension points:
- Additional endpoints - Token balances, NFT metadata, gas estimates
- Caching - Redis for payment verification and query results
- Database - PostgreSQL for payment records and analytics
- WebSockets - Real-time transaction notifications
- GraphQL - Alternative API interface
- Multi-token payments - Accept ETH, other tokens besides USDC
- Subscription model - Monthly access instead of per-query
Before deploying to production:
- Implement real payment verification (blockchain query) - ✅ COMPLETED
- Set
NODE_ENV=production - Use Alchemy paid plan for higher limits
- Enable HTTPS/SSL
- Add rate limiting
- Setup monitoring (Sentry, LogDNA, etc.)
- Configure CORS for specific domains
- Add request validation and sanitization
- Implement payment caching to avoid re-verification (recommended for efficiency)
- Setup backup and disaster recovery
- Document API for users
- Test payment flow on Base mainnet with real USDC
- Set
PAYMENT_NETWORK=base-mainnetin production - Verify
PAYMENT_ADDRESSis correct