# `X402.Scheme.ExactEVM`
[🔗](https://github.com/cardotrejos/x402/blob/v0.9.0/lib/x402/scheme/exact_evm.ex#L1)

Built-in `X402.Scheme` for `exact` payments on EVM (`eip155:*`) networks.

The exact-EVM scheme specification defines several **asset transfer
methods**, selected by the requirements' `extra.assetTransferMethod`:

| `extra.assetTransferMethod` | Transfer method | Scheme payload                                 |
| --------------------------- | --------------- | ---------------------------------------------- |
| absent or `"eip3009"`       | EIP-3009        | `%{"signature", "authorization"}`              |
| `"permit2"`                 | Permit2         | `%{"signature", "permit2Authorization"}`       |

Any other value is unsupported (`transfer_method/1`). Both methods are
implemented for both roles:

* **Client** — `sign/3` signs an EIP-3009 `TransferWithAuthorization`
  through `X402.EIP3009` for the default method, or a Permit2
  `PermitWitnessTransferFrom` through `X402.Permit2.sign_exact/2` when
  the requirements select `"permit2"` (spender: the `x402ExactPermit2Proxy`,
  witness: `payTo`, permitted amount: the exact `amount`). An entry is
  signable when the selected method's EIP-712 domain can be derived from
  the requirements — `extra.name` / `extra.version` for EIP-3009, an
  `eip155:*` network for Permit2.
* **Server** — `precheck/3` runs the local pre-checks before the
  facilitator round-trip on whichever authorization object the payload
  carries: for EIP-3009, `to` must equal `payTo`, `value` must equal the
  advertised `amount`, and the `validAfter`/`validBefore` window must
  cover now plus a settlement buffer
  (`X402.Scheme.EVM.authorization_precheck/3`); for Permit2, `witness.to`
  must equal `payTo`, `permitted.amount` must equal `amount`,
  `permitted.token` must equal `asset`, `spender` must be the
  `x402ExactPermit2Proxy`, and the `witness.validAfter`/`deadline`
  window must cover now plus the buffer
  (`X402.Scheme.EVM.permit2_precheck/3`). Payloads carrying neither map
  are skipped.

Envelope validation of the `PAYMENT-SIGNATURE` payload is handled by
`X402.PaymentSignature`; this scheme adds no extra structural checks
(`c:X402.Scheme.validate_payload/3` returns `:ok`).

# `transfer_method`

```elixir
@type transfer_method() :: :eip3009 | :permit2
```

An asset transfer method of the exact-EVM scheme.

# `networks`
*since 0.6.0* 

```elixir
@spec networks() :: [String.t()]
```

Returns `["eip155:*"]` — every EVM network.

## Examples

    iex> X402.Scheme.ExactEVM.networks()
    ["eip155:*"]

# `precheck`
*since 0.6.0* 

```elixir
@spec precheck(map(), map(), keyword()) ::
  :ok | {:error, {:precheck_failed, X402.Scheme.EVM.precheck_failure()}}
```

Runs the local pre-checks with exact-amount equality enforced.

Dispatches on the payload shape: `payload.authorization` runs
`X402.Scheme.EVM.authorization_precheck/3`, `payload.permit2Authorization`
runs `X402.Scheme.EVM.permit2_precheck/3` against the
`x402ExactPermit2Proxy` spender. Both run when both maps are present;
neither present passes.

# `scheme`
*since 0.6.0* 

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

Returns `"exact"`.

## Examples

    iex> X402.Scheme.ExactEVM.scheme()
    "exact"

# `sign`
*since 0.6.0* 

```elixir
@spec sign(map(), X402.Signer.t(), keyword()) :: {:ok, map()} | {:error, term()}
```

Signs the scheme payload for the selected transfer method.

EIP-3009 requirements sign via `X402.EIP3009.sign/3`, honoring the
client's `:valid_after_buffer` option; Permit2 requirements sign via
`X402.Permit2.sign_exact/2` (valid immediately, expiring after
`maxTimeoutSeconds`). Other options are ignored.

# `signable?`
*since 0.6.0* 

```elixir
@spec signable?(map()) :: boolean()
```

Whether the selected transfer method's EIP-712 domain can be derived
from the requirements.

## Examples

    iex> X402.Scheme.ExactEVM.signable?(%{
    ...>   "network" => "eip155:84532",
    ...>   "asset" => "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
    ...>   "extra" => %{"name" => "USDC", "version" => "2"}
    ...> })
    true

    iex> X402.Scheme.ExactEVM.signable?(%{
    ...>   "network" => "eip155:84532",
    ...>   "asset" => "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
    ...>   "extra" => %{"assetTransferMethod" => "permit2"}
    ...> })
    true

    iex> X402.Scheme.ExactEVM.signable?(%{"extra" => %{}})
    false

    iex> X402.Scheme.ExactEVM.signable?(%{
    ...>   "network" => "eip155:84532",
    ...>   "extra" => %{"assetTransferMethod" => "erc7710"}
    ...> })
    false

# `transfer_method`
*since 0.9.0* 

```elixir
@spec transfer_method(map()) ::
  {:ok, transfer_method()} | {:error, {:unsupported_transfer_method, term()}}
```

Resolves the asset transfer method selected by the requirements.

Reads `extra.assetTransferMethod`: absent or `"eip3009"` selects
`:eip3009`, `"permit2"` selects `:permit2`, anything else is
`{:error, {:unsupported_transfer_method, value}}`.

## Examples

    iex> X402.Scheme.ExactEVM.transfer_method(%{"extra" => %{"name" => "USDC"}})
    {:ok, :eip3009}

    iex> X402.Scheme.ExactEVM.transfer_method(%{"extra" => %{"assetTransferMethod" => "permit2"}})
    {:ok, :permit2}

    iex> X402.Scheme.ExactEVM.transfer_method(%{"extra" => %{"assetTransferMethod" => "erc7710"}})
    {:error, {:unsupported_transfer_method, "erc7710"}}

    iex> X402.Scheme.ExactEVM.transfer_method(%{})
    {:ok, :eip3009}

# `validate_payload`
*since 0.6.0* 

```elixir
@spec validate_payload(map(), map(), keyword()) :: :ok
```

Always `:ok` — envelope validation covers the `exact` payload shape.

## Examples

    iex> X402.Scheme.ExactEVM.validate_payload(%{}, %{}, [])
    :ok

---

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