# `EEVM.Transaction.Signer`
[🔗](https://github.com/mw2000/eevm/blob/v0.1.0/lib/eevm/transaction/signer.ex#L1)

Transaction signing, signing hashes, and sender recovery.

## Example

    iex> alias EEVM.Transaction.{FeeMarket, Signer}
    iex> tx = %FeeMarket{max_priority_fee_per_gas: 1, max_fee_per_gas: 10, gas_limit: 21_000, to: 0xB0B}
    iex> private_key = :binary.copy(<<0x46>>, 32)
    iex> {:ok, signed} = Signer.sign(tx, private_key, EEVM.Config.new(:cancun, chain_id: 5))
    iex> signed.chain_id
    5
    iex> {:ok, sender} = Signer.recover_sender(signed, 5)
    iex> EEVM.hex(<<sender::160>>)
    "0x9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f"

# `address`

```elixir
@spec address(&lt;&lt;_::256&gt;&gt;) ::
  {:ok, EEVM.Transaction.address()} | {:error, :invalid_private_key}
```

Returns the address of the secp256k1 `private_key`: the last 20 bytes of
the keccak256 hash of its uncompressed public key (Yellow Paper,
Appendix F).

Returns `{:error, :invalid_private_key}` when the key is zero or not below
the curve order.

## Example

    iex> # The private key from the EIP-155 example.
    iex> {:ok, address} = EEVM.Transaction.Signer.address(:binary.copy(<<0x46>>, 32))
    iex> EEVM.hex(<<address::160>>)
    "0x9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f"

# `recover_authority`

```elixir
@spec recover_authority(EEVM.Transaction.Authorization.t()) ::
  {:ok, EEVM.Transaction.address()} | {:error, atom()}
```

Recover the authority (signer) of an EIP-7702 authorization tuple.

The signed message is `keccak256(0x05 || rlp([chain_id, address, nonce]))`.
Signatures with `y_parity` outside `0..1`, `r` outside `1..n-1`, or a
high `s` (EIP-2) are rejected with `{:error, :invalid_signature}`.

# `recover_sender`

```elixir
@spec recover_sender(EEVM.Transaction.t(), non_neg_integer()) ::
  {:ok, EEVM.Transaction.address()} | {:error, atom()}
```

Recover the sender address, as an integer, from a transaction signed for
chain `chain_id`.

A transaction signed for another chain fails with
`{:error, :invalid_chain_id}`, so it can't be replayed across chains: a
typed transaction's `chain_id`, or the chain id an EIP-155 legacy `v`
encodes, must equal `chain_id`. A pre-EIP-155 legacy transaction (`v` of
27 or 28) names no chain and is valid on any. Other legacy `v` values
fail with `{:error, :invalid_v}`.

# `sign`

```elixir
@spec sign(EEVM.Transaction.t(), &lt;&lt;_::256&gt;&gt;, EEVM.Config.t()) ::
  {:ok, EEVM.Transaction.t()} | {:error, :invalid_private_key}
```

Signs `tx` with the 32-byte secp256k1 `private_key` for `config`'s chain.

A legacy transaction is signed with EIP-155 replay protection, so its `v`
becomes `chain_id * 2 + 35 + y_parity`. A typed transaction whose
`chain_id` is `nil` takes the config's; one that already has a `chain_id`
keeps it. Any existing signature is replaced. Signatures are low-`s`
(EIP-2).

Returns `{:ok, signed_tx}`, or `{:error, :invalid_private_key}` when the
key is zero or not below the curve order. Raises `ArgumentError` naming
the field when a field has the wrong type, such as a hex string for `to`.

# `signing_hash`

```elixir
@spec signing_hash(EEVM.Transaction.t(), non_neg_integer()) :: binary()
```

Compute the signing hash for a transaction.

Raises `ArgumentError` naming the field when a field has the wrong type,
such as a hex string for `to`.

---

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