# `Cartouche.Typed.Type`
[🔗](https://github.com/zenhive/cartouche/blob/main/lib/cartouche/typed.ex#L17)

EIP-712 type definition — an ordered list of `{name, field_type}` field
entries. Field types are either primitives (`:address`, `{:uint, 256}`,
`:bool`, …) or string references to other named types.

# `field_type`

```elixir
@type field_type() :: primitive() | String.t()
```

# `primitive`

```elixir
@type primitive() ::
  :address
  | {:uint, number()}
  | {:bytes, number()}
  | :string
  | :bytes
  | {:array, primitive()}
  | :bool
```

# `t`

```elixir
@type t() :: %Cartouche.Typed.Type{fields: type_list()}
```

# `type_list`

```elixir
@type type_list() :: [{String.t(), field_type()}]
```

# `deserialize`

```elixir
@spec deserialize([%{name: String.t(), type: String.t()}]) :: t()
```

Deserializes a Type from JSON or a map into a struct.

## Examples

    iex> [%{
    ...>   "name" => "from",
    ...>   "type" => "Person",
    ...> }, %{
    ...>   "name" => "to",
    ...>   "type" => "Person",
    ...> }, %{
    ...>   "name" => "contents",
    ...>   "type" => "string",
    ...> }]
    ...> |> Cartouche.Typed.Type.deserialize()
    %Cartouche.Typed.Type{fields: [{"from", "Person"}, {"to", "Person"}, {"contents", :string}]}

# `deserialize_type`

```elixir
@spec deserialize_type(String.t()) :: field_type()
```

Deserializes a primitive or custom type. We differentiate
custom types by not being a primitive type.

## Examples

    iex> Cartouche.Typed.Type.deserialize_type("address")
    :address

    iex> Cartouche.Typed.Type.deserialize_type("bytes")
    :bytes

    iex> Cartouche.Typed.Type.deserialize_type("uint256")
    {:uint, 256}

    iex> Cartouche.Typed.Type.deserialize_type("bytes32")
    {:bytes, 32}

    iex> Cartouche.Typed.Type.deserialize_type("bool")
    :bool

    iex> Cartouche.Typed.Type.deserialize_type("bytes32[]")
    {:array, {:bytes, 32}}

    iex> Cartouche.Typed.Type.deserialize_type("Person")
    "Person"

    iex> Cartouche.Typed.Type.deserialize_type("bag")
    ** (RuntimeError) unknown type: bag

# `deserialize_value!`

```elixir
@spec deserialize_value!(term(), primitive()) :: term()
```

Deserializes a value of a given type for being stored in this struct.

## Examples

    iex> Cartouche.Typed.Type.deserialize_value!("0x0000000000000000000000000000000000000001", :address)
    <<1::160>>

    iex> Cartouche.Typed.Type.deserialize_value!(55, {:uint, 256})
    55

    iex> Cartouche.Typed.Type.deserialize_value!(true, :bool)
    true

    iex> Cartouche.Typed.Type.deserialize_value!("0x00000000000000000000000000000000000000000000000000000000000000CC", {:bytes, 32})
    <<0xCC::256>>

    iex> Cartouche.Typed.Type.deserialize_value!("0xCC", {:bytes, 32})
    <<0xCC::256>>

    iex> Cartouche.Typed.Type.deserialize_value!("Cow", :string)
    "Cow"

    iex> Cartouche.Typed.Type.deserialize_value!("0xCCDD", :bytes)
    <<0xCC, 0xDD>>

    iex> Cartouche.Typed.Type.deserialize_value!(["0xCCDD", "0xEE"], {:array, :bytes})
    [<<0xCC, 0xDD>>, <<0xEE>>]

# `encode_data_value`

```elixir
@spec encode_data_value(term(), primitive()) :: term()
```

Encodes a value for `encodeData`, as per the EIP-712 spec. Specifically, raw values are
expanded to 32-bytes, and dynamic types are hashed.

## Examples

    iex> Cartouche.Typed.Type.encode_data_value(<<1::160>>, :address)
    <<1::256>>

    iex> Cartouche.Typed.Type.encode_data_value(55, {:uint, 256})
    <<0::248, 55>>

    iex> Cartouche.Typed.Type.encode_data_value(<<0xCC>>, {:bytes, 32})
    <<0::248, 0xCC>>

    iex> Cartouche.Typed.Type.encode_data_value(<<0xCC, 0xDD>>, :bytes)
    ~h[9014B850703629D30F5C8C6C86A6AD981AB9319997490629D7DA37E8CAE985A1]

    iex> Cartouche.Typed.Type.encode_data_value("Cow", :string)
    ~h[8C1D2BD5348394761719DA11EC67EEDAE9502D137E8940FEE8ECD6F641EE1648]

    iex> Cartouche.Typed.Type.encode_data_value([<<0xCC, 0xDD>>, <<0xEE>>], {:array, :bytes})
    ~h[134619415A3C9FE841D99F7CFD5C0BCCFC7CF0DAE90743A3D717C748A3961CF5]

# `serialize`

```elixir
@spec serialize(t()) :: [%{name: String.t(), type: String.t()}]
```

Serializes a Type, such that it can be used with JSON or JavaScript.

## Examples

    iex> %Cartouche.Typed.Type{fields: [{"from", "Person"}, {"to", "Person"}, {"contents", :string}]}
    ...> |> Cartouche.Typed.Type.serialize()
    [%{
      "name" => "from",
      "type" => "Person",
    }, %{
      "name" => "to",
      "type" => "Person",
    }, %{
      "name" => "contents",
      "type" => "string",
    }]

# `serialize_type`

```elixir
@spec serialize_type(field_type()) :: String.t()
```

Serializes a primitive or custom type.

## Examples

    iex> Cartouche.Typed.Type.serialize_type(:address)
    "address"

    iex> Cartouche.Typed.Type.serialize_type({:uint, 256})
    "uint256"

    iex> Cartouche.Typed.Type.serialize_type({:bytes, 32})
    "bytes32"

    iex> Cartouche.Typed.Type.serialize_type(:bytes)
    "bytes"

    iex> Cartouche.Typed.Type.serialize_type(:bool)
    "bool"

    iex> Cartouche.Typed.Type.serialize_type({:array, :bytes})
    "bytes[]"

    iex> Cartouche.Typed.Type.serialize_type("Person")
    "Person"

# `serialize_value`

```elixir
@spec serialize_value(term(), primitive()) :: term()
```

Serializes a value of a given type to pass to JSON or JavaScript.

## Examples

    iex> Cartouche.Typed.Type.serialize_value(<<1::160>>, :address)
    "0x0000000000000000000000000000000000000001"

    iex> Cartouche.Typed.Type.serialize_value(55, {:uint, 256})
    55

    iex> Cartouche.Typed.Type.serialize_value(true, :bool)
    true

    iex> Cartouche.Typed.Type.serialize_value(<<0xCC::256>>, {:bytes, 32})
    "0x00000000000000000000000000000000000000000000000000000000000000cc"

    iex> Cartouche.Typed.Type.serialize_value(<<0xCC>>, {:bytes, 32})
    "0x00000000000000000000000000000000000000000000000000000000000000cc"

    iex> Cartouche.Typed.Type.serialize_value("Cow", :string)
    "Cow"

    iex> Cartouche.Typed.Type.serialize_value(<<0xCC, 0xDD>>, :bytes)
    "0xccdd"

    iex> Cartouche.Typed.Type.serialize_value([<<0xCC, 0xDD>>, <<0xEE>>], {:array, :bytes})
    ["0xccdd", "0xee"]

---

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