Ruby gem for generating signed payment HTTP headers and links using the x402 protocol.
Supports USDC and other token payments on Base, Avalanche, Solana, and other EVM networks with EIP-712 signing.
This gem depends on the eth gem which requires native extensions for cryptographic operations. You'll need to install system dependencies first:
brew install automake openssl libtool pkg-config gmp libffisudo apt-get install build-essential libgmp-dev libssl-devapk add build-base gmp-dev openssl-dev autoconf automake libtoolAdd this line to your application's Gemfile:
gem 'x402-payments'And then execute:
bundle installOr install it yourself as:
gem install x402-paymentsConfigure the gem using environment variables. See examples/.env.example for a template.
| Variable | Required | Description |
|---|---|---|
X402_PRIVATE_KEY |
Yes (EVM) | EVM private key for signing |
X402_PAY_TO |
Yes (EVM) | EVM recipient wallet address |
X402_SOL_PRIVATE_KEY |
Yes (Solana) | Solana private key (base58 or JSON array) |
X402_SOL_PAY_TO |
Yes (Solana) | Solana recipient wallet address |
X402_CHAIN |
No | Network to use (default: base-sepolia) |
X402_CURRENCY |
No | Token symbol (default: USDC) |
X402_PROTOCOL_VERSION |
No | Protocol version 1 or 2 (default: 2) |
X402_MAX_TIMEOUT_SECONDS |
No | Payment validity timeout (default: 600) |
X402_SOLANA_FEE_PAYER |
No | Solana fee payer (default: x402.org facilitator) |
X402_SOLANA_COMPUTE_UNIT_LIMIT |
No | Solana compute unit limit (default: 200000) |
X402_SOLANA_COMPUTE_UNIT_PRICE |
No | Priority fee in micro-lamports (default: 1000) |
X402_SOLANA_RPC_URL |
No | Custom Solana mainnet RPC URL |
X402_SOLANA_DEVNET_RPC_URL |
No | Custom Solana devnet RPC URL |
X402_BASE_RPC_URL |
No | Custom Base mainnet RPC URL |
X402_BASE_SEPOLIA_RPC_URL |
No | Custom Base Sepolia RPC URL |
X402_AVALANCHE_RPC_URL |
No | Custom Avalanche mainnet RPC URL |
X402_AVALANCHE_FUJI_RPC_URL |
No | Custom Avalanche Fuji RPC URL |
EVM Networks:
base-sepolia(testnet) - Defaultbase(mainnet)avalanche-fuji(testnet)avalanche(mainnet)
Solana Networks:
solana-devnet(testnet)solana(mainnet)
You can register custom EVM chains and tokens beyond the built-in options.
X402::Payments.configure do |config|
config.default_pay_to = ENV['X402_PAY_TO']
config.private_key = ENV['X402_PRIVATE_KEY']
# Register Polygon Amoy testnet
config.register_chain(
name: "polygon-amoy",
chain_id: 80002,
standard: "eip155"
)
# Register the token for that chain
config.register_token(
chain: "polygon-amoy",
symbol: "USDC",
address: "0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582",
decimals: 6,
name: "USD Coin",
version: "2"
)
# Set the RPC URL for the custom chain
config.rpc_urls["polygon-amoy"] = "https://bitter-attentive-pool.matic-amoy.quiknode.pro"
config.chain = "polygon-amoy"
config.currency = "USDC"
endYou can also set RPC URLs via environment variables using the pattern X402_<CHAIN>_RPC_URL:
export X402_POLYGON_AMOY_RPC_URL="https://bitter-attentive-pool.matic-amoy.quiknode.pro"X402::Payments.configure do |config|
config.default_pay_to = ENV['X402_PAY_TO']
config.private_key = ENV['X402_PRIVATE_KEY']
# Accept WETH on Base instead of USDC
config.register_token(
chain: "base",
symbol: "WETH",
address: "0x4200000000000000000000000000000000000006",
decimals: 18,
name: "Wrapped Ether",
version: "1"
)
config.chain = "base"
config.currency = "WETH"
end| Parameter | Required | Description |
|---|---|---|
chain |
Yes | Chain name (built-in or custom registered) |
symbol |
Yes | Token symbol (e.g., "USDC", "WETH") |
address |
Yes | Token contract address |
decimals |
Yes | Token decimals (e.g., 6 for USDC, 18 for WETH) |
name |
Yes | Token name for EIP-712 domain |
version |
No | EIP-712 version (default: "1") |
For Solana payments, ensure you've set the Solana-specific environment variables (see Configuration section above), then set your chain:
export X402_CHAIN="solana-devnet" # or "solana" for mainnetYou can also override the fee payer per-request:
X402::Payments.generate_header(
amount: 0.001,
resource: "http://example.com/api",
network: "solana-devnet",
fee_payer: "CustomFacilitatorFeePayer" # use different facilitator
)Note: Both sender and receiver must have a USDC Associated Token Account (ATA). The sender must have USDC in their wallet (receiving USDC creates the ATA automatically).
x402-payments supports both v1 and v2 of the x402 protocol. v2 is the default.
X402::Payments.configure do |config|
config.private_key = ENV['X402_PRIVATE_KEY']
config.default_pay_to = ENV['X402_PAY_TO']
config.protocol_version = 2 # Default, can be omitted
endv2 uses CAIP-2 network identifiers (eip155:84532) and the PAYMENT-SIGNATURE header.
X402::Payments.configure do |config|
config.private_key = ENV['X402_PRIVATE_KEY']
config.default_pay_to = ENV['X402_PAY_TO']
config.protocol_version = 1
endv1 uses simple network names (base-sepolia) and the X-PAYMENT header.
require 'x402/payments'
# Generate a signed payment header
header = X402::Payments.generate_header(
amount: 0.001, # Amount in USD
resource: "http://localhost:3000/api/weather", # Protected resource URL
description: "Payment for weather API access", # Optional description
pay_to: "0xRecipientAddress" # Optional: override recipient (defaults to config)
)
# Use the header in an HTTP request (v2 uses PAYMENT-SIGNATURE, v1 uses X-PAYMENT)
# curl -H "PAYMENT-SIGNATURE: #{header}" http://localhost:3000/api/weatherNote: The pay_to parameter allows you to specify a different recipient wallet address per payment. If not provided, it uses the configured default_pay_to.
The gem works seamlessly in Rails applications:
# config/initializers/x402.rb
X402::Payments.configure do |config|
config.default_pay_to = ENV['X402_PAY_TO']
config.private_key = ENV['X402_PRIVATE_KEY']
config.chain = Rails.env.production? ? 'base' : 'base-sepolia'
# Optional: Override RPC URLs programmatically
# config.rpc_urls = {
# 'base' => 'https://your-custom-base-rpc.com',
# 'base-sepolia' => 'https://your-sepolia-rpc.com'
# }
end
# In your controller or service
class PaymentService
def self.generate_payment_for(resource_url, amount)
X402::Payments.generate_header(
amount: amount,
resource: resource_url,
description: "Payment for #{resource_url}"
)
end
end#!/usr/bin/env ruby
require 'x402/payments'
# Set environment variables or configure directly
X402::Payments.configure do |config|
config.default_pay_to = "0xYourDefaultRecipient"
config.private_key = "0xYourPrivateKeyHere"
config.chain = "base-sepolia"
# config.rpc_urls = { 'base-sepolia' => 'https://your-custom-rpc.com' }
end
# Generate payment
header = X402::Payments.generate_header(
amount: 0.001,
resource: "http://localhost:3000/api/data",
# version: 1, # Override configured protocol version (1 or 2)
# network: "avalanche", # Override default network
# private_key: "0xDifferentKey", # Override default key
# pay_to: "0xRecipientWalletAddress", # Override recipient address
)
puts "Payment Header:"
puts header
# v2 (default) uses PAYMENT-SIGNATURE, v1 uses X-PAYMENT
HTTParty.get("http://localhost:3000/api/data", headers: { "PAYMENT-SIGNATURE" => header })- Payment Requirements: The gem creates a payment requirement specifying the amount (in USDC atomic units), network, and resource
- Transaction Signing:
- EVM: Uses EIP-3009
TransferWithAuthorizationto create a signature that authorizes the payment - Solana: Creates a partially-signed
TransferCheckedtransaction (facilitator adds fee payer signature)
- EVM: Uses EIP-3009
- Header Encoding: Encodes the signed payment data as a base64 string for the HTTP header (
PAYMENT-SIGNATUREfor v2,X-PAYMENTfor v1) - Server Validation: The server validates the signature/transaction and settles the payment on-chain via the facilitator
A complete example script is provided in examples/generate_payment.rb:
# Create your .env file in examples directory
cd examples
cp .env.example .env
# Edit .env with your credentials
# Run the example
cd ..
export $(cat examples/.env | xargs)
ruby examples/generate_payment.rbThis will generate a signed payment header and provide a ready-to-use curl command for testing. See examples/README.md for more details.
After checking out the repo, run:
bin/setup # Install dependencies
bundle exec rake spec # Run tests
bin/console # Interactive prompt for experimentationBug reports and pull requests are welcome on GitHub at https://github.com/yourusername/x402-payments.
- Ruby 3.0+
MIT License. See LICENSE.txt.