# `ABI.Event`
[🔗](https://github.com/ZenHive/hieroglyph/blob/main/lib/abi/event.ex#L1)

Decodes Ethereum event log data into Solidity-typed arguments.

Splits the topic list (indexed parameters) from the data blob (non-indexed
parameters) per the ABI specification, and optionally verifies that
`topics[0]` matches the `keccak256` hash of the event signature.

# `canonical`

```elixir
@spec canonical(
  ABI.FunctionSelector.t(),
  keyword()
) :: String.t()
```

Returns the canonical form of this event topic. Pass in `indexed: true`
to include "indexed" keywords.

## Examples

    iex> ABI.Event.canonical(
    ...>   %ABI.FunctionSelector{
    ...>     function: "Transfer",
    ...>     types: [
    ...>       %{type: :address, name: "from", indexed: true},
    ...>       %{type: :address, name: "to", indexed: true},
    ...>       %{type: {:uint, 256}, name: "amount"},
    ...>     ]
    ...>   }
    ...> )
    "Transfer(address,address,uint256)"

    iex> ABI.Event.canonical(
    ...>   %ABI.FunctionSelector{
    ...>     function: "Transfer",
    ...>     types: [
    ...>       %{type: :address, name: "from", indexed: true},
    ...>       %{type: :address, name: "to", indexed: true},
    ...>       %{type: {:uint, 256}, name: "amount"},
    ...>     ]
    ...>   },
    ...>   names: true
    ...> )
    "Transfer(address from,address to,uint256 amount)"

    iex> ABI.Event.canonical(
    ...>   %ABI.FunctionSelector{
    ...>     function: "Transfer",
    ...>     types: [
    ...>       %{type: :address, name: "from", indexed: true},
    ...>       %{type: :address, name: "to", indexed: true},
    ...>       %{type: {:uint, 256}, name: "amount"},
    ...>     ]
    ...>   },
    ...>   indexed: true
    ...> )
    "Transfer(address indexed,address indexed,uint256)"

    iex> ABI.Event.canonical(
    ...>   %ABI.FunctionSelector{
    ...>     function: "Transfer",
    ...>     types: [
    ...>       %{type: :address, name: "from", indexed: true},
    ...>       %{type: :address, name: "to", indexed: true},
    ...>       %{type: {:uint, 256}, name: "amount"},
    ...>     ]
    ...>   },
    ...>   indexed: true,
    ...>   names: true
    ...> )
    "Transfer(address indexed from,address indexed to,uint256 amount)"

# `decode_event`

```elixir
@spec decode_event(binary(), [binary()], ABI.FunctionSelector.t(), keyword()) ::
  {:ok, String.t() | nil, map()} | {:error, String.t()}
```

Decodes an event, including handling parsing out data from topics.

## Examples

    iex> ABI.Event.decode_event(
    ...>   ~h[0x00000000000000000000000000000000000000000000000000000004a817c800],
    ...>   [
    ...>     ~h[0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef],
    ...>     ~h[0x000000000000000000000000b2b7c1795f19fbc28fda77a95e59edbb8b3709c8],
    ...>     ~h[0x0000000000000000000000007795126b3ae468f44c901287de98594198ce38ea]
    ...>   ],
    ...>   %ABI.FunctionSelector{
    ...>     function: "Transfer",
    ...>     types: [
    ...>       %{type: :address, name: "from", indexed: true},
    ...>       %{type: :address, name: "to", indexed: true},
    ...>       %{type: {:uint, 256}, name: "amount"},
    ...>     ]
    ...>   })
    {:ok,
      "Transfer", %{
        "amount" => 20000000000,
        "from" => ~h[0xb2b7c1795f19fbc28fda77a95e59edbb8b3709c8],
        "to" => ~h[0x7795126b3ae468f44c901287de98594198ce38ea]
    }}

    iex> ABI.Event.decode_event(
    ...>   ~h[0x00000000000000000000000000000000000000000000000000000004a817c800],
    ...>   [
    ...>     ~h[0x0000000000000000000000000000000000000000000000000000000000000001],
    ...>     ~h[0x000000000000000000000000b2b7c1795f19fbc28fda77a95e59edbb8b3709c8],
    ...>     ~h[0x0000000000000000000000007795126b3ae468f44c901287de98594198ce38ea]
    ...>   ],
    ...>   %ABI.FunctionSelector{
    ...>     function: "Transfer",
    ...>     types: [
    ...>       %{type: :address, name: "from", indexed: true},
    ...>       %{type: :address, name: "to", indexed: true},
    ...>       %{type: {:uint, 256}, name: "amount"},
    ...>     ]
    ...>   })
    {:error, "Mismatched event signature topic[0], expected=DDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF, got=0000000000000000000000000000000000000000000000000000000000000001"}

    iex> ABI.Event.decode_event(
    ...>   ~h[0x00000000000000000000000000000000000000000000000000000004a817c800],
    ...>   [
    ...>     ~h[0x000000000000000000000000b2b7c1795f19fbc28fda77a95e59edbb8b3709c8],
    ...>     ~h[0x0000000000000000000000007795126b3ae468f44c901287de98594198ce38ea]
    ...>   ],
    ...>   %ABI.FunctionSelector{
    ...>     function: "Transfer",
    ...>     types: [
    ...>       %{type: :address, name: "from", indexed: true},
    ...>       %{type: :address, name: "to", indexed: true},
    ...>       %{type: {:uint, 256}, name: "amount"},
    ...>     ]
    ...>   })
    {:error, "Invalid topics length (got=2, expected=3), consider toggling `check_event_signature`"}

    iex> ABI.Event.decode_event(
    ...>   ~h[0x00000000000000000000000000000000000000000000000000000004a817c800],
    ...>   [
    ...>     ~h[0x000000000000000000000000b2b7c1795f19fbc28fda77a95e59edbb8b3709c8],
    ...>     ~h[0x0000000000000000000000007795126b3ae468f44c901287de98594198ce38ea]
    ...>   ],
    ...>   %ABI.FunctionSelector{
    ...>     function: "Transfer",
    ...>     types: [
    ...>       %{type: :address, name: "from", indexed: true},
    ...>       %{type: :address, name: "to", indexed: true},
    ...>       %{type: {:uint, 256}, name: "amount"},
    ...>     ]
    ...>   },
    ...>   check_event_signature: false
    ...> )
    {:ok,
      "Transfer", %{
        "amount" => 20000000000,
        "from" => ~h[0xb2b7c1795f19fbc28fda77a95e59edbb8b3709c8],
        "to" => ~h[0x7795126b3ae468f44c901287de98594198ce38ea]
    }}

# `event_signature`

```elixir
@spec event_signature(ABI.FunctionSelector.t()) :: binary()
```

Returns the signature of an event, i.e. the first item that appears
in an Ethereum log for this event.

## Examples

    iex> ABI.Event.event_signature(
    ...>   %ABI.FunctionSelector{
    ...>     function: "Transfer",
    ...>     types: [
    ...>       %{type: :address, name: "from", indexed: true},
    ...>       %{type: :address, name: "to", indexed: true},
    ...>       %{type: {:uint, 256}, name: "amount"},
    ...>     ]
    ...>   }
    ...> )
    ...> |> to_hex()
    "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"

---

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