1use keccak_hash::keccak;
2
3use crate::{StructName, TypeDefinition, TypeRef, Types, Value, ValueKind};
4
5#[derive(Debug, thiserror::Error)]
6pub enum TypedDataHashError {
7 #[error("Missing referenced type: {0}")]
8 MissingReferencedType(String),
9 #[error("Missing struct member: {0}")]
10 MissingStructMember(String),
11 #[error("Expected string")]
12 ExpectedString,
13 #[error("Expected bytes")]
14 ExpectedBytes,
15 #[error("Expected boolean")]
16 ExpectedBoolean,
17 #[error("Expected `{0}` array, found {1}")]
18 ExpectedArray(String, ValueKind),
19 #[error("Expected `{0}` struct, found {1}")]
20 ExpectedObject(String, ValueKind),
21 #[error("Expected integer")]
22 ExpectedInteger,
23 #[error("Expected address length 20 but found {0}")]
24 ExpectedAddressLength(usize),
25 #[error("Expected bytes length {0} but found {1}")]
26 ExpectedBytesLength(usize, usize),
27 #[error("Expected array length {0} but found {1}")]
28 ExpectedArrayLength(usize, usize),
29 #[error("Expected integer max length 32 bytes but found {0}")]
30 IntegerTooLong(usize),
31 #[error("Type not byte-aligned: {0} {1}")]
32 TypeNotByteAligned(&'static str, usize),
33 #[error("Expected bytes length between 1 and 32: {0}")]
34 BytesLength(usize),
35 #[error("Expected integer length between 8 and 256: {0}")]
36 IntegerLength(usize),
37 #[error("Expected string to be hex bytes")]
38 ExpectedHex,
39 #[error("Untyped properties: {0:?}")]
40 UntypedProperties(Vec<String>),
41}
42
43impl Value {
44 #[allow(clippy::ptr_arg)]
48 pub fn hash(
49 &self,
50 struct_name: &StructName,
51 types: &Types,
52 ) -> Result<[u8; 32], TypedDataHashError> {
53 let encoded_data = self
54 .encode(&TypeRef::Struct(struct_name.clone()), types)?
55 .to_vec();
56 Ok(keccak(encoded_data).to_fixed_bytes())
57 }
58}
59
60impl TypeDefinition {
61 #[allow(clippy::ptr_arg)]
63 pub fn hash(
64 &self,
65 struct_name: &StructName,
66 types: &Types,
67 ) -> Result<[u8; 32], TypedDataHashError> {
68 let encoded_type = self.encode(struct_name, types)?.to_vec();
69 let type_hash = keccak(encoded_type).to_fixed_bytes();
70 Ok(type_hash)
71 }
72}