# `X402.PaymentSignature`
[🔗](https://github.com/cardotrejos/x402/blob/main/lib/x402/payment_signature.ex#L1)

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"`

# `decode`
*since 0.1.0* 

```elixir
@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}

# `header_name`
*since 0.1.0* 

```elixir
@spec header_name() :: String.t()
```

Returns the canonical x402 header name.

## Examples

    iex> X402.PaymentSignature.header_name()
    "PAYMENT-SIGNATURE"

# `decode_and_validate`
*since 0.1.0* 

```elixir
@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}

# `decode_and_validate`
*since 0.1.0* 

```elixir
@spec decode_and_validate(String.t(), map()) ::
  {:ok, map()} | {:error, decode_and_validate_error()}
```

Decodes and validates a `PAYMENT-SIGNATURE` header against requirements.

# `validate`
*since 0.1.0* 

```elixir
@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"]}}

# `validate`
*since 0.1.0* 

```elixir
@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`.

# `decode_and_validate_error`

```elixir
@type decode_and_validate_error() :: decode_error() | validate_error()
```

# `decode_error`

```elixir
@type decode_error() :: :invalid_base64 | :invalid_json | :payload_too_large
```

# `upto_validation_error`

```elixir
@type upto_validation_error() ::
  :missing_max_price
  | :missing_payment_value
  | :invalid_max_price
  | :invalid_payment_value
  | :payment_value_exceeds_max_price
```

# `validate_error`

```elixir
@type validate_error() ::
  :invalid_payload
  | {:missing_fields, [String.t()]}
  | {:invalid_upto_payment, upto_validation_error()}
  | {:invalid_format, [{field :: String.t(), reason :: atom()}]}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
