Module: X402
- Defined in:
- lib/x402/rails.rb,
lib/x402/chains.rb,
lib/x402/versions.rb,
lib/x402/versions/v1.rb,
lib/x402/versions/v2.rb,
lib/x402/configuration.rb,
lib/x402/rails/railtie.rb,
lib/x402/rails/version.rb,
lib/x402/versions/base.rb,
lib/x402/payment_payload.rb,
lib/x402/payment_validator.rb,
lib/x402/facilitator_client.rb,
lib/x402/discovery_extension.rb,
lib/x402/payment_requirement.rb,
lib/x402/settlement_response.rb,
lib/x402/cdp_facilitator_auth.rb,
lib/x402/requirement_generator.rb,
lib/x402/rails/controller_extensions.rb,
lib/generators/x402/install/install_generator.rb
Defined Under Namespace
Modules: Generators, Rails, Versions Classes: CdpFacilitatorAuth, Configuration, ConfigurationError, DiscoveryExtension, FacilitatorClient, FacilitatorError, InvalidPaymentError, PaymentPayload, PaymentRequirement, PaymentValidator, RequirementGenerator, SettlementResponse
Constant Summary collapse
- USDC_NAMED_USD_COIN_V2 =
Currency config constants for EIP-712 signature domain. The
namefield must match the on-chain ERC-20 name() return value. Theversionfield must match the EIP-712 domain version. { symbol: "USDC", decimals: 6, name: "USD Coin", version: "2" }.freeze
- USDC_NAMED_USDC_V2 =
{ symbol: "USDC", decimals: 6, name: "USDC", version: "2" }.freeze
- USDC_NAMED_USDC =
{ symbol: "USDC", decimals: 6, name: "USDC", version: nil }.freeze
- USDC_NAMED_USD_COIN =
{ symbol: "USDC", decimals: 6, name: "USD Coin", version: nil }.freeze
- CHAINS =
Unified chain registry — single source of truth for all chain metadata. Each entry contains: chain_id, caip2, currency, and optionally usdc_address, explorer_url, fee_payer.
{ # --- Base --- "base" => { chain_id: 8453, caip2: "eip155:8453", usdc_address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", explorer_url: "https://basescan.org", currency: USDC_NAMED_USD_COIN_V2, }, "base-sepolia" => { chain_id: 84532, caip2: "eip155:84532", usdc_address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", explorer_url: "https://sepolia.basescan.org", currency: USDC_NAMED_USDC_V2, }, # --- Polygon --- "polygon" => { chain_id: 137, caip2: "eip155:137", usdc_address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", explorer_url: "https://polygonscan.com", currency: USDC_NAMED_USD_COIN_V2, }, "polygon-amoy" => { chain_id: 80002, caip2: "eip155:80002", usdc_address: "0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582", explorer_url: "https://amoy.polygonscan.com", currency: USDC_NAMED_USDC_V2, }, # --- Avalanche --- "avalanche" => { chain_id: 43114, caip2: "eip155:43114", usdc_address: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", explorer_url: "https://snowtrace.io", currency: USDC_NAMED_USDC_V2, }, "avalanche-fuji" => { chain_id: 43113, caip2: "eip155:43113", usdc_address: "0x5425890298aed601595a70AB815c96711a31Bc65", explorer_url: "https://testnet.snowtrace.io", currency: USDC_NAMED_USD_COIN_V2, }, # --- Sei --- "sei" => { chain_id: 1329, caip2: "eip155:1329", usdc_address: "0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392", explorer_url: "https://seitrace.com", currency: USDC_NAMED_USDC, }, "sei-testnet" => { chain_id: 713715, caip2: "eip155:713715", explorer_url: "https://seitrace.com/?chain=arctic-1", currency: USDC_NAMED_USDC, }, # --- X Layer --- "xlayer" => { chain_id: 196, caip2: "eip155:196", explorer_url: "https://www.oklink.com/xlayer", currency: USDC_NAMED_USDC, }, "xlayer-testnet" => { chain_id: 1952, caip2: "eip155:1952", explorer_url: "https://www.oklink.com/xlayer-test", currency: USDC_NAMED_USDC, }, # --- SKALE --- "skale-base" => { chain_id: 1_187_947_933, caip2: "eip155:1187947933", explorer_url: "https://skale-base-explorer.skalenodes.com", currency: USDC_NAMED_USDC, }, "skale-base-sepolia" => { chain_id: 324_705_682, caip2: "eip155:324705682", explorer_url: "https://base-sepolia-testnet-explorer.skalenodes.com", currency: USDC_NAMED_USDC, }, # --- KiteAI --- "kiteai" => { chain_id: 2366, caip2: "eip155:2366", explorer_url: "https://kitescan.ai", currency: USDC_NAMED_USDC, }, "kiteai-testnet" => { chain_id: 2368, caip2: "eip155:2368", explorer_url: "https://testnet.kitescan.ai", currency: USDC_NAMED_USDC, }, # --- IoTeX (mainnet only) --- "iotex" => { chain_id: 4689, caip2: "eip155:4689", explorer_url: "https://iotexscan.io", currency: USDC_NAMED_USDC, }, # --- Peaq (mainnet only) --- "peaq" => { chain_id: 3338, caip2: "eip155:3338", explorer_url: "https://peaq.subscan.io", currency: USDC_NAMED_USDC, }, # --- XDC --- "xdc" => { chain_id: 50, caip2: "eip155:50", usdc_address: "0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1", explorer_url: "https://xdcscan.com", currency: USDC_NAMED_USDC_V2, }, "xdc-testnet" => { chain_id: 51, caip2: "eip155:51", usdc_address: "0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4", explorer_url: "https://testnet.xdcscan.com", currency: USDC_NAMED_USDC_V2, }, # --- Solana --- "solana" => { chain_id: 101, caip2: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", usdc_address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", explorer_url: "https://explorer.solana.com", fee_payer: "CKPKJWNdJEqa81x7CkZ14BVPiY6y16Sxs7owznqtWYp5", currency: USDC_NAMED_USD_COIN, }, "solana-devnet" => { chain_id: 103, caip2: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", usdc_address: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU", explorer_url: "https://explorer.solana.com/?cluster=devnet", fee_payer: "CKPKJWNdJEqa81x7CkZ14BVPiY6y16Sxs7owznqtWYp5", currency: USDC_NAMED_USDC, }, }.freeze
- CURRENCY_BY_CHAIN =
Derived lookups for backwards compatibility
CHAINS.transform_values { |v| v[:currency] }.freeze
- CAIP2_MAPPING =
CHAINS.transform_values { |v| v[:caip2] }.freeze
- REVERSE_CAIP2_MAPPING =
CAIP2_MAPPING.invert.freeze
- SOLANA_CHAINS =
%w[solana solana-devnet].freeze
Class Attribute Summary collapse
Class Method Summary collapse
- .asset_address_for(chain_name, symbol = nil) ⇒ Object
- .chain_config(chain_name) ⇒ Object
- .configure {|configuration| ... } ⇒ Object
- .currency_config_for_chain(chain_name) ⇒ Object
- .currency_decimals_for_chain(chain_name) ⇒ Object
- .fee_payer_for(chain_name) ⇒ Object
- .from_caip2(caip2_string) ⇒ Object
-
.logger ⇒ Object
::-qualified: bare Rails here resolves to the gem's own X402::Rails.
- .reset_configuration! ⇒ Object
- .solana_chain?(chain_name) ⇒ Boolean
- .supported_chains ⇒ Object
- .to_caip2(network_name) ⇒ Object
- .token_config_for(chain_name, symbol = nil) ⇒ Object
- .usdc_address_for(chain_name) ⇒ Object
Class Attribute Details
.configuration ⇒ Object
89 90 91 |
# File 'lib/x402/configuration.rb', line 89 def configuration @configuration ||= Configuration.new end |
Class Method Details
.asset_address_for(chain_name, symbol = nil) ⇒ Object
200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/x402/chains.rb', line 200 def asset_address_for(chain_name, symbol = nil) symbol ||= X402.configuration.currency custom = X402.configuration.token_config(chain_name, symbol) return custom[:address] if custom if symbol.upcase == "USDC" builtin = CHAINS[chain_name] return builtin[:usdc_address] if builtin && builtin[:usdc_address] end raise ConfigurationError, "Unknown token #{symbol} for chain #{chain_name}. Register with config.register_token()" end |
.chain_config(chain_name) ⇒ Object
177 178 179 180 181 182 |
# File 'lib/x402/chains.rb', line 177 def chain_config(chain_name) custom = X402.configuration.chain_config(chain_name) return custom if custom CHAINS[chain_name] || raise(ConfigurationError, "Unsupported chain: #{chain_name}. Register with config.register_chain()") end |
.configure {|configuration| ... } ⇒ Object
93 94 95 |
# File 'lib/x402/configuration.rb', line 93 def configure yield(configuration) end |
.currency_config_for_chain(chain_name) ⇒ Object
184 185 186 187 188 189 |
# File 'lib/x402/chains.rb', line 184 def currency_config_for_chain(chain_name) config = CHAINS[chain_name] raise(ConfigurationError, "Unsupported chain for currency: #{chain_name}") unless config config[:currency] end |
.currency_decimals_for_chain(chain_name) ⇒ Object
228 229 230 |
# File 'lib/x402/chains.rb', line 228 def currency_decimals_for_chain(chain_name) currency_config_for_chain(chain_name)[:decimals] end |
.fee_payer_for(chain_name) ⇒ Object
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/x402/chains.rb', line 232 def fee_payer_for(chain_name) # Priority: 1) Programmatic config, 2) Per-chain ENV variable, 3) Generic ENV variable, 4) Default from CHAINS config = X402.configuration # Check programmatic configuration return config.fee_payer if config.fee_payer && !config.fee_payer.empty? # Check per-chain environment variable (e.g., X402_SOLANA_DEVNET_FEE_PAYER, X402_SOLANA_FEE_PAYER) env_var_name = "X402_#{chain_name.upcase.gsub('-', '_')}_FEE_PAYER" env_fee_payer = ENV[env_var_name] return env_fee_payer if env_fee_payer && !env_fee_payer.empty? # Check generic environment variable env_fee_payer = ENV["X402_FEE_PAYER"] return env_fee_payer if env_fee_payer && !env_fee_payer.empty? # Fall back to default from chain config chain_config(chain_name)[:fee_payer] end |
.from_caip2(caip2_string) ⇒ Object
261 262 263 264 265 266 267 268 269 270 |
# File 'lib/x402/chains.rb', line 261 def from_caip2(caip2_string) return REVERSE_CAIP2_MAPPING[caip2_string] if REVERSE_CAIP2_MAPPING[caip2_string] X402.configuration.custom_chains.each do |name, config| caip2 = "#{config[:standard]}:#{config[:chain_id]}" return name if caip2 == caip2_string end raise(ConfigurationError, "Unknown CAIP-2 network: #{caip2_string}") end |
.logger ⇒ Object
::-qualified: bare Rails here resolves to the gem's own X402::Rails.
102 103 104 |
# File 'lib/x402/configuration.rb', line 102 def logger ::Rails.logger end |
.reset_configuration! ⇒ Object
97 98 99 |
# File 'lib/x402/configuration.rb', line 97 def reset_configuration! @configuration = Configuration.new end |
.solana_chain?(chain_name) ⇒ Boolean
274 275 276 |
# File 'lib/x402/chains.rb', line 274 def solana_chain?(chain_name) SOLANA_CHAINS.include?(chain_name) end |
.supported_chains ⇒ Object
191 192 193 |
# File 'lib/x402/chains.rb', line 191 def supported_chains CHAINS.keys + X402.configuration.custom_chains.keys end |
.to_caip2(network_name) ⇒ Object
252 253 254 255 256 257 258 259 |
# File 'lib/x402/chains.rb', line 252 def to_caip2(network_name) custom = X402.configuration.chain_config(network_name) if custom return "#{custom[:standard]}:#{custom[:chain_id]}" end CAIP2_MAPPING[network_name] || raise(ConfigurationError, "No CAIP-2 mapping for: #{network_name}") end |
.token_config_for(chain_name, symbol = nil) ⇒ Object
214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/x402/chains.rb', line 214 def token_config_for(chain_name, symbol = nil) symbol ||= X402.configuration.currency custom = X402.configuration.token_config(chain_name, symbol) return custom if custom config = CHAINS[chain_name] if symbol.upcase == "USDC" && config&.dig(:currency) config[:currency] else raise ConfigurationError, "Unknown token #{symbol} for chain #{chain_name}. Register with config.register_token()" end end |
.usdc_address_for(chain_name) ⇒ Object
195 196 197 198 |
# File 'lib/x402/chains.rb', line 195 def usdc_address_for(chain_name) builtin = CHAINS[chain_name] builtin ? builtin[:usdc_address] : nil end |