Decodes and validates x402 PAYMENT-SIGNATURE header values.
The header value is Base64-encoded JSON. After decoding, this module validates the required x402 signature fields:
"transactionHash""network""scheme""payerWallet"
Summary
Header Encoding
Decodes a Base64 PAYMENT-SIGNATURE value to a map.
Returns the canonical x402 header name.
Payment Verification
Decodes and validates a PAYMENT-SIGNATURE header in one step.
Decodes and validates a PAYMENT-SIGNATURE header against requirements.
Validates that all required signature fields are present and non-empty.
Validates a decoded PAYMENT-SIGNATURE payload against payment requirements.
Header Encoding
@spec decode(String.t()) :: {:ok, map()} | {:error, decode_error()}
Decodes a Base64 PAYMENT-SIGNATURE value to a map.
Examples
iex> payload = %{"transactionHash" => "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "network" => "eip155:8453", "scheme" => "exact", "payerWallet" => "0x1111111111111111111111111111111111111111"}
iex> value = payload |> Jason.encode!() |> Base.encode64()
iex> X402.PaymentSignature.decode(value)
{:ok, payload}
iex> X402.PaymentSignature.decode("not-base64")
{:error, :invalid_base64}
@spec header_name() :: String.t()
Returns the canonical x402 header name.
Examples
iex> X402.PaymentSignature.header_name()
"PAYMENT-SIGNATURE"
Payment Verification
@spec decode_and_validate(String.t()) :: {:ok, map()} | {:error, decode_and_validate_error()}
Decodes and validates a PAYMENT-SIGNATURE header in one step.
Examples
iex> payload = %{"transactionHash" => "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "network" => "eip155:8453", "scheme" => "exact", "payerWallet" => "0x1111111111111111111111111111111111111111"}
iex> value = payload |> Jason.encode!() |> Base.encode64()
iex> X402.PaymentSignature.decode_and_validate(value)
{:ok, payload}
@spec decode_and_validate(String.t(), map()) :: {:ok, map()} | {:error, decode_and_validate_error()}
Decodes and validates a PAYMENT-SIGNATURE header against requirements.
@spec validate(map()) :: {:ok, map()} | {:error, validate_error()}
Validates that all required signature fields are present and non-empty.
Examples
iex> payload = %{
...> "transactionHash" => "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
...> "network" => "eip155:8453",
...> "scheme" => "exact",
...> "payerWallet" => "0x1111111111111111111111111111111111111111"
...> }
iex> X402.PaymentSignature.validate(payload)
{:ok, payload}
iex> X402.PaymentSignature.validate(%{"network" => "eip155:8453"})
{:error, {:missing_fields, ["payerWallet", "scheme", "transactionHash"]}}
@spec validate(map(), map()) :: {:ok, map()} | {:error, validate_error()}
Validates a decoded PAYMENT-SIGNATURE payload against payment requirements.
For the "upto" scheme, this ensures the payment value is less than or equal
to maxPrice.
Types
@type decode_and_validate_error() :: decode_error() | validate_error()
@type decode_error() :: :invalid_base64 | :invalid_json | :payload_too_large
@type upto_validation_error() ::
:missing_max_price
| :missing_payment_value
| :invalid_max_price
| :invalid_payment_value
| :payment_value_exceeds_max_price
@type validate_error() :: :invalid_payload | {:missing_fields, [String.t()]} | {:invalid_upto_payment, upto_validation_error()} | {:invalid_format, [{field :: String.t(), reason :: atom()}]}