Skip to content

Class X402::BSV::ProofGateway

Inherits: X402::BSV::Gateway

Merkleworks x402 compatible gateway.

Challenge: X402-Challenge (merkleworks JSON with nonce UTXO + request binding) Proof: X402-Proof (echoed challenge hash + rawtx + txid)

Supports two modes: * Profile A: challenge includes nonce UTXO metadata only * Profile B: nonce_provider returns a pre-signed partial_tx template

Constants

ACCEPTABLE_MEMPOOL_STATUSES

ARC status values that confirm ARC knows about the tx and hasn't rejected it. ARC progresses a broadcast tx through roughly:

RECEIVED → STORED → ANNOUNCED_TO_NETWORK →
REQUESTED_BY_NETWORK → SENT_TO_NETWORK →
ACCEPTED_BY_NETWORK → SEEN_ON_NETWORK → MINED

Any of these mean "ARC has the tx and is processing it"; the client has demonstrably broadcast. The bad states we must reject are UNKNOWN (never seen), REJECTED, DOUBLE_SPEND_ATTEMPTED —anything in this whitelist is acceptable.

Bitcoin's single-spend guarantee at the network layer is the actual replay gate; this check just confirms the client fulfilled their broadcast obligation. Matches the merkleworks reference implementation's visible check.

Public Instance Methods

challenge_headers(rack_request, route)

Build a 402 challenge with merkleworks X402-Challenge header. - @param rack_request [Rack::Request] - @param route [X402::Configuration::Route] - @raise [ConfigurationError] if route uses callable amount_sats (fiat pricing) - @return [Hash] challenge headers

initialize(nonce_provider:, arc_client:, payee_locking_script_hex: = nil, wallet: = nil, challenge_secret: = nil, challenge_store: = nil, network_visibility_cache: = nil)

  • @param nonce_provider [#call] callable returning nonce UTXO hash; receives (rack_request, payee:, amount:) kwargs. Profile B providers include :partial_tx (binary) in the response.
  • @param arc_client [#status] ARC client for mempool queries
  • @param payee_locking_script_hex [String, nil] payee script (falls back to config)
  • @param challenge_store [#store!, #lookup, #consume!] per-instance challenge cache (default: in-memory, per-process).
  • @param network_visibility_cache [NetworkVisibility::Cache, nil] per-gateway positive-only TTL cache shielding ARC from duplicate-submission bursts. Defaults to a fresh +NetworkVisibility::Cache.new+.
  • @return [ProofGateway] a new instance of ProofGateway

proof_header_names()

  • @return [Array] proof header names this gateway responds to

settle!(_header_name, proof_payload, rack_request, route)

Verify a merkleworks x402 proof against the challenge and check mempool. - @param _header_name [String] which proof header matched - @param proof_payload [String] base64url-encoded proof - @param rack_request [Rack::Request] - @param route [X402::Configuration::Route] - @raise [VerificationError] on invalid proof, binding mismatch, or mempool failure - @return [SettlementResult]