X402 payment facilitator service written in Go, supporting exact@EVM payment scheme verification and settlement.
- ✅ Complete Protocol Implementation - Full X402 exact@EVM scheme support
- ✅ Production-Ready - Structured logging, error handling, graceful shutdown
- ✅ EVM Network Support - Supports any EVM-compatible network (configurable via RPC endpoint)
- ✅ HTTP API - RESTful endpoints for verify, settle, and supported networks
- ✅ Monitoring - Structured logging with request tracking
- ✅ Easy Configuration - Environment variable based configuration
- ✅ Secure - Request validation, CORS support
- ✅ Scalable - Concurrent processing with graceful shutdown
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ HTTP API │ │ Facilitator │ │ EVM Clients │
│ (Gin) │───▶│ Service │───▶│ (go-ethereum) │
│ │ │ │ │ │
│ /verify │ │ - Verify logic │ │ - RPC calls │
│ /settle │ │ - Settle logic │ │ - Transaction │
│ /supported │ │ - Network info │ │ execution │
│ /health │ │ - EIP-712 sig │ │ - Balance check │
│ /ready │ │ verification │ │ - Nonce check │
└─────────────────┘ └─────────────────┘ └─────────────────┘
- Go 1.21 or later
- Ethereum private key for transaction signing
- Access to an Ethereum RPC endpoint (local node or public RPC)
-
Install dependencies:
go mod download
-
Configure:
cp env.example .env # Edit .env file with your configuration # Required: FACILITATOR_PRIVATE_KEY # Required: FACILITATOR_CHAIN_RPC # Required: FACILITATOR_CHAIN_ID # Required: FACILITATOR_TOKEN_ADDRESS
-
Run:
# Using .env file (automatically loaded) go run cmd/main.go # Or specify custom config file go run cmd/main.go -config .env # Or use start script ./start.sh
POST /facilitator/verify
Content-Type: application/json
{
"paymentPayload": {
"x402Version": 1,
"scheme": "exact",
"network": "localhost",
"payload": {
"signature": "0x...",
"authorization": {
"from": "0x...",
"to": "0x...",
"value": "10000",
"validAfter": "1740672089",
"validBefore": "1740672154",
"nonce": "0x..."
}
}
},
"paymentRequirements": {
"scheme": "exact",
"network": "localhost",
"maxAmountRequired": "10000",
"resource": "https://api.example.com/premium-data",
"description": "Access to premium market data",
"payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
}
}Note: The network field must match the FACILITATOR_NETWORK configuration value.
Response:
{
"isValid": true,
"invalidReason": "",
"payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66"
}POST /facilitator/settle
Content-Type: application/json
# Same request body as /verify endpointResponse:
{
"success": true,
"errorReason": "",
"transaction": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"network": "localhost",
"payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66"
}GET /facilitator/supportedResponse:
{
"x402Version": 1,
"kinds": [
{
"x402Version": 1,
"scheme": "exact",
"network": "localhost"
}
]
}- Health Check:
GET /health- Basic health status - Readiness Check:
GET /ready- Detailed readiness status (checks if facilitator is initialized)
The service is configured via environment variables. You can use a .env file (see env.example) or set environment variables directly.
| Variable | Description | Default |
|---|---|---|
SERVER_HOST |
Server host address | 0.0.0.0 |
SERVER_PORT |
Server port | 8080 |
SERVER_READ_TIMEOUT |
Read timeout duration | 30s |
SERVER_WRITE_TIMEOUT |
Write timeout duration | 30s |
SERVER_IDLE_TIMEOUT |
Idle timeout duration | 120s |
SERVER_LOG_LEVEL |
Log level (trace, debug, info, warn, error, fatal, panic) | info |
SERVER_LOG_FORMAT |
Log format (json, console) | json |
# Server Configuration
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
SERVER_READ_TIMEOUT=30s
SERVER_WRITE_TIMEOUT=30s
SERVER_IDLE_TIMEOUT=120s
SERVER_LOG_LEVEL=info
SERVER_LOG_FORMAT=json
# Facilitator Configuration
FACILITATOR_NETWORK=localhost
FACILITATOR_CHAIN_RPC=http://127.0.0.1:8545
FACILITATOR_CHAIN_ID=1337
FACILITATOR_TOKEN_ADDRESS=0xYourTokenAddress
FACILITATOR_TOKEN_NAME=MyToken
FACILITATOR_TOKEN_VERSION=1
FACILITATOR_TOKEN_DECIMALS=6
FACILITATOR_PRIVATE_KEY=your-private-key-hex-without-0x-prefix
FACILITATOR_GAS_LIMIT=100000
FACILITATOR_SUPPORTED_SCHEME=exactThe service uses structured JSON logging (or console format) with the following features:
- Structured Logging - JSON format by default for easy parsing
- Request ID Tracking - Each request gets a unique ID (via
X-Request-IDheader) - Log Levels - Configurable log levels (trace, debug, info, warn, error, fatal, panic)
- Context Fields - Automatic service name and version in all logs
Log fields include:
service- Service name ("x402-facilitator")version- Service version (1.0.0)request_id- Unique request identifiermethod- HTTP methodpath- Request pathstatus- HTTP status codeduration_ms- Request duration in milliseconds
- Use HTTPS in production - Always use TLS/SSL for production deployments
- Secure private keys - Never commit private keys to version control
- Use environment variables or secure secret management
- The
.envfile should be in.gitignore
- Network security - Restrict RPC endpoint access
- Use private RPC endpoints when possible
- Consider rate limiting on RPC calls
- Monitor logs - Regularly review logs for suspicious activity
- Input validation - All requests are validated before processing
- CORS configuration - Currently allows all origins; restrict in production if needed
# Build binary
go build -o x402-facilitator ./cmd/main.go
# Or using the standard Go build command
go build -o bin/x402-facilitator ./cmdSee the examples/ directory for example usage:
cd examples
# Set up environment variables (see examples/common.go)
go run pay.goThis project is licensed under the Apache License - see the LICENSE file for details.
- Support for additional payment schemes (deferred, subscription)
- Database integration for payment history
- Webhook support for payment notifications
- Advanced rate limiting and throttling
- Prometheus metrics endpoint
- API key authentication middleware
- Multi-network support (single facilitator instance)
- SDK for popular languages
