Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 42 additions & 29 deletions lib/eip712/typed.ex
Original file line number Diff line number Diff line change
Expand Up @@ -297,24 +297,42 @@ defmodule EIP712.Typed do
defstruct [:name, :version, :chain_id, :verifying_contract]

@type t() :: %__MODULE__{
name: String.t(),
version: String.t(),
chain_id: number(),
verifying_contract: <<_::160>>
name: nil | String.t(),
version: nil | String.t(),
chain_id: nil | number(),
verifying_contract: nil | <<_::160>>
}

def domain_type(),
do: %{
"EIP712Domain" => %Type{
fields: [
{"name", :string},
{"version", :string},
{"chainId", {:uint, 256}},
{"verifyingContract", :address}
# {"salt", {:bytes, 32}}
]
}
}
@all_domain_fields [
{:name, "name", :string},
{:version, "version", :string},
{:chain_id, "chainId", {:uint, 256}},
{:verifying_contract, "verifyingContract", :address}
]

@doc """
Returns the EIP712Domain type, including only fields that are non-nil
in the given domain. Per the EIP-712 spec, optional domain fields
(like `verifyingContract` or `salt`) should be omitted from the type
hash when not present.

When called without arguments, includes all fields (backwards compatible).
"""
def domain_type(domain \\ nil)

def domain_type(nil) do
fields = for {_key, eip_name, type} <- @all_domain_fields, do: {eip_name, type}
%{"EIP712Domain" => %Type{fields: fields}}
end

def domain_type(%__MODULE__{} = domain) do
fields =
for {key, eip_name, type} <- @all_domain_fields,
not is_nil(Map.get(domain, key)),
do: {eip_name, type}

%{"EIP712Domain" => %Type{fields: fields}}
end

@doc ~S"""
Deserializes a domain from JSON or JavaScript encoding to a struct.
Expand Down Expand Up @@ -416,18 +434,13 @@ defmodule EIP712.Typed do
"verifyingContract" => <<204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204>>
}
"""
def serialize_keys(%__MODULE__{
name: name,
version: version,
chain_id: chain_id,
verifying_contract: verifying_contract
}) do
%{
"name" => name,
"version" => version,
"chainId" => chain_id,
"verifyingContract" => verifying_contract
}
def serialize_keys(%__MODULE__{} = domain) do
for {key, eip_name, _type} <- @all_domain_fields,
value = Map.get(domain, key),
not is_nil(value),
into: %{} do
{eip_name, value}
end
end
end

Expand Down Expand Up @@ -798,7 +811,7 @@ defmodule EIP712.Typed do
"""
@spec domain_seperator(t()) :: binary()
def domain_seperator(%__MODULE__{domain: domain}) do
hash_struct("EIP712Domain", Domain.serialize_keys(domain), Domain.domain_type())
hash_struct("EIP712Domain", Domain.serialize_keys(domain), Domain.domain_type(domain))
end

@doc """
Expand Down