x402-rails
Accept instant blockchain micropayments in your Rails applications using the x402 payment protocol.
Supports Base, avalanche, and other blockchain networks.
Features
- 1 line of code to accept digital dollars (USDC)
- No fees on supported networks (Base)
- ~1 second response times (optimistic mode)
- $0.001 minimum payment amounts
- Optimistic & non-optimistic settlement modes
- Automatic settlement after successful responses
- Browser paywall and API support
- Rails 7.0+ compatible
Example Video
Installation
Add to your Gemfile:
gem 'x402-rails'Then run:
bundle installQuick Start
1. Configure the gem
Create config/initializers/x402.rb:
X402.configure do |config|
config.wallet_address = ENV['X402_WALLET_ADDRESS'] # Your recipient wallet
config.facilitator = "https://x402.org/facilitator"
config.chain = "base-sepolia" # or "base" for base mainnet
config.currency = "USDC"
config.optimistic = false # Forces to check for settlement before giving response.
end2. Protect your endpoints
Use x402_paywall in any controller action:
class ApiController < ApplicationController
def weather
x402_paywall(amount: 0.001) # $0.001 in USD
return if performed?
render json: {
temperature: 72,
paid_by: request.env['x402.payment'][:payer]
}
end
endThat's it! Your endpoint now requires payment.
Usage Patterns
Direct Method Call
Call x402_paywall in any action:
def show
x402_paywall(amount: 0.01)
return if performed?
# Action continues after payment verified
render json: @data
endBefore Action Hook
Protect multiple actions:
class PremiumController < ApplicationController
before_action :require_payment, only: [:show, :index]
def show
# Payment already verified
render json: @premium_content
end
private
def require_payment
x402_paywall(amount: 0.001, chain: "base")
return if performed?
end
endPer-Action Pricing
Different prices for different actions:
def basic_data
x402_paywall(amount: 0.001)
return if performed?
render json: basic_info
end
def premium_data
x402_paywall(amount: 0.01)
return if performed?
render json: premium_info
endConfiguration Options
Global Configuration
Set defaults in config/initializers/x402.rb:
X402.configure do |config|
# Required: Your wallet address where payments will be received
config.wallet_address = ENV['X402_WALLET_ADDRESS']
# Facilitator service URL (default: "https://x402.org/facilitator")
config.facilitator = ENV.fetch("X402_FACILITATOR_URL", "https://x402.org/facilitator")
# Blockchain network (default: "base-sepolia")
# Options: "base-sepolia", "base", "avalanche-fuji", "avalanche"
config.chain = ENV.fetch("X402_CHAIN", "base-sepolia")
# Payment token (default: "USDC")
# Currently only USDC is supported
config.currency = ENV.fetch("X402_CURRENCY","USDC")
# Optimistic mode (default: true)
# true: Fast response, settle payment after response is sent
# false: Wait for blockchain settlement before sending response
config.optimistic = ENV.fetch("X402_OPTIMISTIC",false)
endConfiguration Attributes
| Attribute | Required | Default | Description |
|---|---|---|---|
wallet_address |
Yes | - | Your Ethereum wallet address where payments will be received |
facilitator |
No | "https://x402.org/facilitator" |
Facilitator service URL for payment verification and settlement |
chain |
No | "base-sepolia" |
Blockchain network to use (base-sepolia, base, avalanche-fuji, avalanche) |
currency |
No | "USDC" |
Payment token symbol (currently only USDC supported) |
optimistic |
No | true |
Settlement mode (see Optimistic vs Non-Optimistic Mode below) |
rpc_urls |
No | {} |
Custom RPC endpoint URLs per chain (see Custom RPC URLs below) |
Custom RPC URLs
By default, x402-rails uses public QuickNode RPC endpoints for each supported chain. For production use or higher reliability, you can configure custom RPC URLs from providers like QuickNode.
Configuration Priority (highest to lowest):
- Programmatic configuration via
config.rpc_urls - Per-chain environment variables
- Built-in default RPC URLs
Method 1: Programmatic Configuration
Configure RPC URLs in your initializer:
X402.configure do |config|
config.wallet_address = ENV['X402_WALLET_ADDRESS']
# Custom RPC URLs per chain
config.rpc_urls["base"] = "https://your-base-rpc.quiknode.pro/your-key"
config.rpc_urls["base-sepolia"] = "https://your-sepolia-rpc.quiknode.pro/your-key"
config.rpc_urls["avalanche"] = "https://your-avalanche-rpc.quiknode.pro/your-key"
endMethod 2: Environment Variables
Set per-chain environment variables:
# Per-chain RPC URL overrides
X402_BASE_RPC_URL=https://your-base-rpc.quiknode.pro/your-key
X402_BASE_SEPOLIA_RPC_URL=https://your-sepolia-rpc.quiknode.pro/your-key
X402_AVALANCHE_RPC_URL=https://your-avalanche-rpc.quiknode.pro/your-key
X402_AVALANCHE_FUJI_RPC_URL=https://your-fuji-rpc.quiknode.pro/your-keyMethod 3: Default RPC URLs
If no custom RPC URL is configured, it will default to the public QuickNode RPC urls.
Environment Variables
Configure via environment variables:
# Required
X402_WALLET_ADDRESS=0xYourAddress
# Optional (with defaults)
X402_FACILITATOR_URL=https://x402.org/facilitator
X402_CHAIN=base-sepolia
X402_CURRENCY=USDC
X402_OPTIMISTIC=true # "true" or "false"
# Custom RPC URLs (optional, per-chain overrides)
X402_BASE_RPC_URL=https://your-base-rpc.quiknode.pro/your-key
X402_BASE_SEPOLIA_RPC_URL=https://your-base-speoliarpc.quiknode.pro/your-key
X402_AVALANCHE_RPC_URL=https://your-avalanche.quiknode.pro/your-key
X402_AVALANCHE_FUJI_RPC_URL=https://your-fuji-rpc.quiknode.pro/your-keyExamples
Weather API
class WeatherController < ApplicationController
def current
x402_paywall(amount: 0.001)
return if performed?
render json: { temp: 72, condition: "sunny" }
end
def forecast
x402_paywall(amount: 0.01)
return if performed?
render json: { forecast: [...] }
end
endx402 Architecture
┌──────────┐ ┌──────────┐ ┌─────────────┐
│ Client │─────▶│ Rails │─────▶│ Facilitator │
│ │ │ x402 │ │ (x402.org) │
└──────────┘ └──────────┘ └─────────────┘
│ │ │
│ │ ▼
│ │ ┌──────────────┐
│ │ │ Blockchain │
│ │ │ (Base) │
└──────────────────┴─────────────┴──────────────┘
Error Handling
The gem raises these errors:
-
X402::ConfigurationError- Invalid configuration -
X402::InvalidPaymentError- Invalid payment payload -
X402::FacilitatorError- Facilitator communication issues
Security
- Payments validated via EIP-712 signatures
- Nonce prevents replay attacks
- Time windows limit authorization validity
- Facilitator verifies all parameters
- Settlement happens on-chain (immutable)
Requirements
- Ruby 3.0+
- Rails 7.0+
Resources
License
MIT License. See LICENSE.txt.