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

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:

- `X402.PaymentRequired` for `PAYMENT-REQUIRED`
- `X402.PaymentSignature` for `PAYMENT-SIGNATURE`
- `X402.PaymentResponse` for `PAYMENT-RESPONSE`
- `X402.Wallet` for wallet address detection and validation

# `decode_payment_required`
*since 0.1.0* 

```elixir
@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`
*since 0.1.0* 

```elixir
@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`
*since 0.1.0* 

```elixir
@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`
*since 0.1.0* 

```elixir
@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`
*since 0.1.0* 

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

# `decode_and_validate_payment_signature`
*since 0.1.0* 

```elixir
@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`
*since 0.1.0* 

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

# `valid_wallet?`
*since 0.1.0* 

```elixir
@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`
*since 0.1.0* 

```elixir
@spec wallet_type(term()) :: :evm | :solana | :unknown
```

Returns the wallet type.

## Examples

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

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

---

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