{"id":33914697,"url":"https://github.com/quiknode-labs/x402-rails","last_synced_at":"2026-04-08T13:31:47.020Z","repository":{"id":321671379,"uuid":"1085808265","full_name":"quiknode-labs/x402-rails","owner":"quiknode-labs","description":"Accept instant blockchain micropayments in your Rails applications using the x402 payment protocol.","archived":false,"fork":false,"pushed_at":"2026-01-20T15:51:33.000Z","size":99,"stargazers_count":35,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-07T04:58:08.049Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quiknode-labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-29T14:39:18.000Z","updated_at":"2026-02-20T19:51:19.000Z","dependencies_parsed_at":"2025-10-30T23:19:52.251Z","dependency_job_id":"be455ed4-84a5-4076-a520-7a9369918943","html_url":"https://github.com/quiknode-labs/x402-rails","commit_stats":null,"previous_names":["quiknode-labs/x402-rails"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/quiknode-labs/x402-rails","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quiknode-labs%2Fx402-rails","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quiknode-labs%2Fx402-rails/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quiknode-labs%2Fx402-rails/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quiknode-labs%2Fx402-rails/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quiknode-labs","download_url":"https://codeload.github.com/quiknode-labs/x402-rails/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quiknode-labs%2Fx402-rails/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31558380,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T10:21:54.569Z","status":"ssl_error","status_checked_at":"2026-04-08T10:21:38.171Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-12T06:36:49.977Z","updated_at":"2026-04-08T13:31:47.011Z","avatar_url":"https://github.com/quiknode-labs.png","language":"Ruby","funding_links":[],"categories":["Uncategorized"],"sub_categories":["Uncategorized"],"readme":"# x402-rails\n\n## Now supporting x402 v2!\n\n\u003e **⚠️ Note:** This gem now defaults to x402 protocol **v2**. If you need v1 compatibility, set `config.version = 1` in your initializer. See [Protocol Versions](#protocol-versions) for details on the differences.\n\n![Coverage](./coverage/coverage.svg)\n\nAccept instant blockchain micropayments in your Rails applications using the [x402 payment protocol](https://www.x402.org/).\n\nSupports Base, avalanche, and other blockchain networks.\n\n## Features\n\n- **1 line of code** to accept digital dollars (USDC)\n- **No fees** on supported networks (Base)\n- **~1 second** response times (optimistic mode)\n- **$0.001 minimum** payment amounts\n- **Optimistic \u0026 non-optimistic** settlement modes\n- **Automatic settlement** after successful responses\n- **Browser paywall** and API support\n- **Rails 7.0+** compatible\n\n## Example Video\n\nhttps://github.com/user-attachments/assets/05983bb3-7422-4c06-97ab-2fb53d6428cc\n\n## Installation\n\nAdd to your Gemfile:\n\n```ruby\ngem 'x402-rails'\n```\n\nThen run:\n\n```bash\nbundle install\n```\n\n## Quick Start\n\n### 1. Configure the gem\n\nCreate `config/initializers/x402.rb`:\n\n```ruby\nX402.configure do |config|\n  config.wallet_address = ENV['X402_WALLET_ADDRESS']  # Your recipient wallet\n  config.facilitator = \"https://x402.org/facilitator\"\n  config.chain = \"base-sepolia\"  # or \"base\" for base mainnet\n  config.currency = \"USDC\"\n  config.optimistic = false  # Forces to check for settlement before giving response.\nend\n```\n\n### 2. Protect your endpoints\n\nUse `x402_paywall` in any controller action:\n\n```ruby\nclass ApiController \u003c ApplicationController\n  def weather\n    x402_paywall(amount: 0.001)  # $0.001 in USD\n    return if performed?\n\n    render json: {\n      temperature: 72,\n      paid_by: request.env['x402.payment'][:payer]\n    }\n  end\nend\n```\n\nThat's it! Your endpoint now requires payment.\n\n## Usage Patterns\n\n### Direct Method Call\n\nCall `x402_paywall` in any action:\n\n```ruby\ndef show\n  x402_paywall(amount: 0.01)\n  return if performed?\n  # Action continues after payment verified\n  render json: @data\nend\n```\n\n### Before Action Hook\n\nProtect multiple actions:\n\n```ruby\nclass PremiumController \u003c ApplicationController\n  before_action :require_payment, only: [:show, :index]\n\n  def show\n    # Payment already verified\n    render json: @premium_content\n  end\n\n  private\n\n  def require_payment\n    x402_paywall(amount: 0.001, chain: \"base\")\n    return if performed?\n  end\nend\n```\n\n### Per-Action Pricing\n\nDifferent prices for different actions:\n\n```ruby\ndef basic_data\n  x402_paywall(amount: 0.001)\n  return if performed?\n  render json: basic_info\nend\n\ndef premium_data\n  x402_paywall(amount: 0.01)\n  return if performed?\n  render json: premium_info\nend\n```\n\n## Configuration Options\n\n### Global Configuration\n\nSet defaults in `config/initializers/x402.rb`:\n\n```ruby\nX402.configure do |config|\n  # Required: Your wallet address where payments will be received\n  config.wallet_address = ENV['X402_WALLET_ADDRESS']\n\n  # Facilitator service URL (default: \"https://x402.org/facilitator\")\n  config.facilitator = ENV.fetch(\"X402_FACILITATOR_URL\", \"https://x402.org/facilitator\")\n\n  # Blockchain network (default: \"base-sepolia\")\n  # Options: \"base-sepolia\", \"base\", \"avalanche-fuji\", \"avalanche\"\n  config.chain = ENV.fetch(\"X402_CHAIN\", \"base-sepolia\")\n\n  # Payment token (default: \"USDC\")\n  # Currently only USDC is supported\n  config.currency = ENV.fetch(\"X402_CURRENCY\",\"USDC\")\n\n  # Optimistic mode (default: true)\n  # true: Fast response, settle payment after response is sent\n  # false: Wait for blockchain settlement before sending response\n  config.optimistic = ENV.fetch(\"X402_OPTIMISTIC\",false)\nend\n```\n\n### Configuration Attributes\n\n| Attribute        | Required | Default                          | Description                                                                       |\n| ---------------- | -------- | -------------------------------- | --------------------------------------------------------------------------------- |\n| `wallet_address` | **Yes**  | -                                | Your Ethereum wallet address where payments will be received                      |\n| `facilitator`    | No       | `\"https://x402.org/facilitator\"` | Facilitator service URL for payment verification and settlement                   |\n| `chain`          | No       | `\"base-sepolia\"`                 | Blockchain network to use (`base-sepolia`, `base`, `avalanche-fuji`, `avalanche`) |\n| `currency`       | No       | `\"USDC\"`                         | Payment token symbol (currently only USDC supported)                              |\n| `optimistic`     | No       | `true`                           | Settlement mode (see Optimistic vs Non-Optimistic Mode below)                     |\n| `version`        | No       | `2`                              | Protocol version (1 or 2). See Protocol Versions section                          |\n\n### Custom Chains and Tokens\n\nYou can register custom EVM chains and tokens beyond the built-in options.\n\n#### Register a Custom Chain\n\nAdd support for any EVM-compatible chain:\n\n```ruby\nX402.configure do |config|\n  config.wallet_address = ENV['X402_WALLET_ADDRESS']\n\n  # Register Polygon mainnet\n  config.register_chain(\n    name: \"polygon\",\n    chain_id: 137,\n    standard: \"eip155\"\n  )\n\n  # Register the token for that chain\n  config.register_token(\n    chain: \"polygon\",\n    symbol: \"USDC\",\n    address: \"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359\",\n    decimals: 6,\n    name: \"USD Coin\",\n    version: \"2\"\n  )\n\n  config.chain = \"polygon\"\n  config.currency = \"USDC\"\nend\n```\n\n#### Register a Custom Token on a Built-in Chain\n\n\u003e **⚠️ Note:** The Facilitator used **must support** the specified chain and token to ensure proper functionality.\n\nAccept different tokens on existing chains:\n\n```ruby\nX402.configure do |config|\n  config.wallet_address = ENV['X402_WALLET_ADDRESS']\n\n  # Accept WETH on Base instead of USDC\n  config.register_token(\n    chain: \"base\",\n    symbol: \"WETH\",\n    address: \"0x4200000000000000000000000000000000000006\",\n    decimals: 18,\n    name: \"Wrapped Ether\",\n    version: \"1\"\n  )\n\n  config.chain = \"base\"\n  config.currency = \"WETH\"\nend\n```\n\n#### Token Registration Parameters\n\n| Parameter  | Required | Description                                    |\n| ---------- | -------- | ---------------------------------------------- |\n| `chain`    | Yes      | Chain name (built-in or custom registered)     |\n| `symbol`   | Yes      | Token symbol (e.g., \"USDC\", \"WETH\")            |\n| `address`  | Yes      | Token contract address                         |\n| `decimals` | Yes      | Token decimals (e.g., 6 for USDC, 18 for WETH) |\n| `name`     | Yes      | Token name for EIP-712 domain                  |\n| `version`  | No       | EIP-712 version (default: \"1\")                 |\n\n**Note:** Custom chains and tokens are only supported for EVM (eip155) networks. Solana chains use a different implementation.\n\n### Accept Multiple Payment Options\n\nAllow clients to pay on any of several supported chains by using `config.accept()`:\n\n```ruby\nX402.configure do |config|\n  config.wallet_address = ENV['X402_WALLET_ADDRESS']\n\n  # Register a custom chain\n  config.register_chain(name: \"polygon-amoy\", chain_id: 80002, standard: \"eip155\")\n  config.register_token(\n    chain: \"polygon-amoy\",\n    symbol: \"USDC\",\n    address: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n    decimals: 6,\n    name: \"USD Coin\",\n    version: \"2\"\n  )\n\n  # Accept payments on multiple chains\n  config.accept(chain: \"base-sepolia\", currency: \"USDC\")\n  config.accept(chain: \"polygon-amoy\", currency: \"USDC\")\nend\n```\n\nWhen `config.accept()` is used, the 402 response will include all accepted payment options:\n\n```json\n{\n  \"accepts\": [\n    { \"network\": \"eip155:84532\", \"asset\": \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\", ... },\n    { \"network\": \"eip155:80002\", \"asset\": \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\", ... }\n  ]\n}\n```\n\nClients can then choose which chain to pay on based on their preferences or available funds.\n\n**Per-accept wallet addresses:** You can specify different recipient addresses per chain:\n\n```ruby\nconfig.accept(chain: \"base-sepolia\", currency: \"USDC\", wallet_address: \"0xWallet1\")\nconfig.accept(chain: \"polygon-amoy\", currency: \"USDC\", wallet_address: \"0xWallet2\")\n```\n\n**Fallback behavior:** If no `config.accept()` calls are made, the default `config.chain` and `config.currency` are used.\n\n## Protocol Versions\n\nx402-rails supports both v1 and v2 of the x402 protocol. **v2 is the default**.\n\n### Key Differences\n\n| Feature         | v1 (Legacy)                   | v2 (Default)                     |\n| --------------- | ----------------------------- | -------------------------------- |\n| Network format  | Simple names (`base-sepolia`) | CAIP-2 (`eip155:84532`)          |\n| Payment header  | `X-PAYMENT`                   | `PAYMENT-SIGNATURE`              |\n| Response header | `X-PAYMENT-RESPONSE`          | `PAYMENT-RESPONSE`               |\n| Requirements    | Body only                     | `PAYMENT-REQUIRED` header + body |\n| Amount field    | `maxAmountRequired`           | `amount`                         |\n\n### v2 (Default)\n\n```ruby\nX402.configure do |config|\n  config.wallet_address = ENV['X402_WALLET_ADDRESS']\n  config.version = 2  # Default, can be omitted\nend\n```\n\nv2 uses CAIP-2 network identifiers (`eip155:84532`) and the `PAYMENT-SIGNATURE` header. Payment requirements are sent in both the `PAYMENT-REQUIRED` header (base64-encoded) and the response body (JSON).\n\n### v1 (Legacy)\n\n```ruby\nX402.configure do |config|\n  config.wallet_address = ENV['X402_WALLET_ADDRESS']\n  config.version = 1\nend\n```\n\nv1 uses simple network names (`base-sepolia`) and the `X-PAYMENT` header. Payment requirements are sent only in the response body.\n\n### Per-Endpoint Version\n\nOverride the version for specific endpoints:\n\n```ruby\ndef premium_v2\n  x402_paywall(amount: 0.001, version: 2)\n  return if performed?\n  render json: { data: \"v2 endpoint\" }\nend\n\ndef legacy_v1\n  x402_paywall(amount: 0.001, version: 1)\n  return if performed?\n  render json: { data: \"v1 endpoint\" }\nend\n```\n\n## Environment Variables\n\nConfigure via environment variables:\n\n```bash\n# Required\nX402_WALLET_ADDRESS=0xYourAddress\n\n# Optional (with defaults)\nX402_FACILITATOR_URL=https://x402.org/facilitator\nX402_CHAIN=base-sepolia\nX402_CURRENCY=USDC\nX402_OPTIMISTIC=true  # \"true\" or \"false\"\n```\n\n## Examples\n\n### Weather API\n\n```ruby\nclass WeatherController \u003c ApplicationController\n  def current\n    x402_paywall(amount: 0.001)\n    return if performed?\n    render json: { temp: 72, condition: \"sunny\" }\n  end\n\n  def forecast\n    x402_paywall(amount: 0.01)\n    return if performed?\n    render json: { forecast: [...] }\n  end\nend\n```\n\n## x402 Architecture\n\n```\n┌──────────┐      ┌──────────┐      ┌─────────────┐\n│  Client  │─────▶│   Rails  │─────▶│ Facilitator │\n│          │      │   x402   │      │   (x402.org) │\n└──────────┘      └──────────┘      └─────────────┘\n     │                  │                    │\n     │                  │                    ▼\n     │                  │             ┌──────────────┐\n     │                  │             │  Blockchain  │\n     │                  │             │   (Base)     │\n     └──────────────────┴─────────────┴──────────────┘\n```\n\n## Error Handling\n\nThe gem raises these errors:\n\n- `X402::ConfigurationError` - Invalid configuration\n- `X402::InvalidPaymentError` - Invalid payment payload\n- `X402::FacilitatorError` - Facilitator communication issues\n\n## Security\n\n- Payments validated via EIP-712 signatures\n- Nonce prevents replay attacks\n- Time windows limit authorization validity\n- Facilitator verifies all parameters\n- Settlement happens on-chain (immutable)\n\n## Requirements\n\n- Ruby 3.0+\n- Rails 7.0+\n\n## Resources\n\n- [x402 Protocol Docs](https://docs.cdp.coinbase.com/x402)\n- [GitHub Repository](https://github.com/coinbase/x402)\n- [Facilitator API](https://x402.org/facilitator)\n- [Step-by-Step Rails Integration Guide](https://www.quicknode.com/guides/infrastructure/x402-payment-integration-with-rails)\n\n\n## License\n\nMIT License. See [LICENSE.txt](LICENSE.txt).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquiknode-labs%2Fx402-rails","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquiknode-labs%2Fx402-rails","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquiknode-labs%2Fx402-rails/lists"}