Convenience API for working with x402 payment headers and wallet addresses.

X402 exposes the most common encode/decode and validation operations while delegating implementation details to dedicated modules:

Summary

Header Encoding

Decodes a PAYMENT-REQUIRED header payload.

Decodes a PAYMENT-RESPONSE header payload.

Decodes a PAYMENT-SIGNATURE header payload.

Encodes a PAYMENT-REQUIRED header payload.

Encodes a PAYMENT-RESPONSE header payload.

Payment Verification

Decodes and validates a PAYMENT-SIGNATURE payload.

Validates a decoded PAYMENT-SIGNATURE payload.

Functions

Returns true when the wallet address is a valid EVM or Solana address.

Returns the wallet type.

Header Encoding

decode_payment_required(header)

(since 0.1.0)
@spec decode_payment_required(String.t()) ::
  {:ok, map()} | {:error, :invalid_base64 | :invalid_json | :payload_too_large}

Decodes a PAYMENT-REQUIRED header payload.

Examples

iex> {:ok, encoded} = X402.PaymentRequired.encode(%{"scheme" => "exact"})
iex> {:ok, decoded} = X402.decode_payment_required(encoded)
iex> decoded["scheme"]
"exact"

decode_payment_response(header)

(since 0.1.0)
@spec decode_payment_response(String.t()) ::
  {:ok, map()} | {:error, :invalid_base64 | :invalid_json | :payload_too_large}

Decodes a PAYMENT-RESPONSE header payload.

Examples

iex> {:ok, encoded} = X402.PaymentResponse.encode(%{"settled" => true})
iex> {:ok, decoded} = X402.decode_payment_response(encoded)
iex> decoded["settled"]
true

decode_payment_signature(header)

(since 0.1.0)
@spec decode_payment_signature(String.t()) ::
  {:ok, map()} | {:error, :invalid_base64 | :invalid_json}

Decodes a PAYMENT-SIGNATURE header payload.

Examples

iex> payload = %{
...>   "transactionHash" => "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
...>   "network" => "eip155:8453",
...>   "scheme" => "exact",
...>   "payerWallet" => "0x1111111111111111111111111111111111111111"
...> }
iex> encoded = payload |> Jason.encode!() |> Base.encode64()
iex> {:ok, decoded} = X402.decode_payment_signature(encoded)
iex> decoded["network"]
"eip155:8453"

encode_payment_required(payload)

(since 0.1.0)
@spec encode_payment_required(map()) ::
  {:ok, String.t()} | {:error, :invalid_payload | :invalid_json}

Encodes a PAYMENT-REQUIRED header payload.

Examples

iex> {:ok, header} = X402.encode_payment_required(%{"scheme" => "exact"})
iex> is_binary(header)
true

encode_payment_response(payload)

(since 0.1.0)
@spec encode_payment_response(map()) ::
  {:ok, String.t()} | {:error, :invalid_payload | :invalid_json}

Encodes a PAYMENT-RESPONSE header payload.

Examples

iex> {:ok, header} = X402.encode_payment_response(%{"settled" => true})
iex> is_binary(header)
true

Payment Verification

decode_and_validate_payment_signature(header)

(since 0.1.0)
@spec decode_and_validate_payment_signature(String.t()) ::
  {:ok, map()}
  | {:error,
     :invalid_base64
     | :invalid_json
     | :invalid_payload
     | {:missing_fields, [String.t()]}
     | {:invalid_upto_payment, X402.PaymentSignature.upto_validation_error()}}

Decodes and validates a PAYMENT-SIGNATURE payload.

Examples

iex> payload = %{
...>   "transactionHash" => "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
...>   "network" => "eip155:8453",
...>   "scheme" => "exact",
...>   "payerWallet" => "0x1111111111111111111111111111111111111111"
...> }
iex> encoded = payload |> Jason.encode!() |> Base.encode64()
iex> {:ok, _decoded} = X402.decode_and_validate_payment_signature(encoded)

validate_payment_signature(payload)

(since 0.1.0)
@spec validate_payment_signature(map()) ::
  {:ok, map()}
  | {:error,
     :invalid_payload
     | {:missing_fields, [String.t()]}
     | {:invalid_upto_payment, X402.PaymentSignature.upto_validation_error()}}

Validates a decoded PAYMENT-SIGNATURE payload.

Examples

iex> X402.validate_payment_signature(%{
...>   "transactionHash" => "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
...>   "network" => "eip155:8453",
...>   "scheme" => "exact",
...>   "payerWallet" => "0x1111111111111111111111111111111111111111"
...> })
{:ok, %{
  "network" => "eip155:8453",
  "payerWallet" => "0x1111111111111111111111111111111111111111",
  "scheme" => "exact",
  "transactionHash" => "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}}

Functions

valid_wallet?(wallet)

(since 0.1.0)
@spec valid_wallet?(term()) :: boolean()

Returns true when the wallet address is a valid EVM or Solana address.

Examples

iex> X402.valid_wallet?("0x1111111111111111111111111111111111111111")
true

iex> X402.valid_wallet?("not-a-wallet")
false

wallet_type(wallet)

(since 0.1.0)
@spec wallet_type(term()) :: :evm | :solana | :unknown

Returns the wallet type.

Examples

iex> X402.wallet_type("0x1111111111111111111111111111111111111111")
:evm

iex> X402.wallet_type("9xQeWvG816bUx9EPfQmQTYnC16hHhV6bQf8kX6y4YB9")
:solana