Module: Blockchain0xX402::Server
- Defined in:
- lib/blockchain0x_x402/server.rb
Defined Under Namespace
Classes: PricingEntry, RackMiddleware, VerifyFailure, VerifyOk
Constant Summary collapse
- CAIP2_BY_NETWORK =
{ 'mainnet' => 'eip155:8453', 'testnet' => 'eip155:84532', }.freeze
- PAYMENT_ENV_KEY =
'blockchain0x.x402_payment'
Class Method Summary collapse
-
.build_402_body(entry:, resource:, default_network:, max_age_seconds:) ⇒ Object
Render the canonical 402 body.
-
.build_requirement(entry, default_network) ⇒ Object
Build a PaymentRequirement struct from a pricing entry + network fallback.
-
.usdc_decimal_to_wei(decimal) ⇒ Object
Convert a human decimal USDC amount (“0.10”) to a 6-decimal wei integer string (“100000”).
- .verify_x_payment(sdk:, header:, entry:) ⇒ Object
- .x402_response_to_hash(resp) ⇒ Object
Class Method Details
.build_402_body(entry:, resource:, default_network:, max_age_seconds:) ⇒ Object
Render the canonical 402 body. Used internally by the middleware; exported for alternative adapters.
96 97 98 99 100 |
# File 'lib/blockchain0x_x402/server.rb', line 96 def self.build_402_body(entry:, resource:, default_network:, max_age_seconds:) req = build_requirement(entry, default_network) req.max_age_seconds = max_age_seconds Wire::X402Response.new(version: 1, resource: resource, accepts: [req]) end |
.build_requirement(entry, default_network) ⇒ Object
Build a PaymentRequirement struct from a pricing entry + network fallback. Exported so alternative adapters (Rails ActionController::API, Grape) can reuse it.
81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/blockchain0x_x402/server.rb', line 81 def self.build_requirement(entry, default_network) network = entry.network || default_network || 'mainnet' Wire::PaymentRequirement.new( scheme: 'exact-usdc', network: network, chain_id: CAIP2_BY_NETWORK.fetch(network), pay_to_address: entry.pay_to_address, amount_wei_usdc: usdc_decimal_to_wei(entry.amount_usdc), payment_request_id: entry.payment_request_id, max_age_seconds: nil, ) end |
.usdc_decimal_to_wei(decimal) ⇒ Object
Convert a human decimal USDC amount (“0.10”) to a 6-decimal wei integer string (“100000”). Mirrors the equivalent helper in @blockchain0x/x402’s shared.ts.
70 71 72 73 74 75 76 |
# File 'lib/blockchain0x_x402/server.rb', line 70 def self.usdc_decimal_to_wei(decimal) whole, frac = decimal.split('.', 2) whole = '0' if whole.nil? || whole.empty? frac ||= '' frac = frac.ljust(6, '0')[0, 6] (whole.to_i * 1_000_000 + frac.to_i).to_s end |
.verify_x_payment(sdk:, header:, entry:) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/blockchain0x_x402/server.rb', line 132 def self.verify_x_payment(sdk:, header:, entry:) if header.nil? || header.empty? return VerifyFailure.new('header_missing', 'X-Payment header is required.') end begin payment = Wire.parse_payment_header(header) rescue WireError => e return VerifyFailure.new('header_malformed', e.) end if payment.payment_request_id != entry.payment_request_id return VerifyFailure.new( 'requirement_mismatch', "X-Payment references #{payment.payment_request_id}, " \ "route quoted #{entry.payment_request_id}.", ) end begin sdk.payment_requests_settle( payment_request_id: payment.payment_request_id, body: { 'txHash' => payment.tx_hash, 'payerAddress' => payment.payer_address, 'amountUsdcVerified' => payment.amount_usdc, }, ) rescue StandardError => e msg = e. msg = 'settle() rejected the proof.' if msg.nil? || msg.empty? return VerifyFailure.new('settle_rejected', msg) end VerifyOk.new(payment) end |
.x402_response_to_hash(resp) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/blockchain0x_x402/server.rb', line 102 def self.x402_response_to_hash(resp) { 'version' => resp.version, 'resource' => resp.resource, 'accepts' => resp.accepts.map do |r| h = { 'scheme' => r.scheme, 'network' => r.network, 'chainId' => r.chain_id, 'payToAddress' => r.pay_to_address, 'amountWeiUsdc' => r.amount_wei_usdc, 'paymentRequestId' => r.payment_request_id, } h['maxAgeSeconds'] = r.max_age_seconds unless r.max_age_seconds.nil? h end, } end |