use super::SolType;
use crate::Eip712Domain;
use alloc::{borrow::Cow, string::String, vec::Vec};
use alloy_primitives::{B256, keccak256};
pub trait SolStruct: SolType<RustType = Self> {
const NAME: &'static str;
fn eip712_components() -> Vec<Cow<'static, str>>;
fn eip712_root_type() -> Cow<'static, str>;
fn eip712_encode_type() -> Cow<'static, str> {
fn eip712_encode_types(
root_type: Cow<'static, str>,
mut components: Vec<Cow<'static, str>>,
) -> Cow<'static, str> {
if components.is_empty() {
return root_type;
}
components.sort_unstable();
components.dedup();
let mut s = String::with_capacity(
root_type.len() + components.iter().map(|s| s.len()).sum::<usize>(),
);
s.push_str(&root_type);
for component in components {
s.push_str(&component);
}
Cow::Owned(s)
}
eip712_encode_types(Self::eip712_root_type(), Self::eip712_components())
}
#[inline]
fn eip712_type_hash(&self) -> B256 {
keccak256(Self::eip712_encode_type().as_bytes())
}
fn eip712_encode_data(&self) -> Vec<u8>;
#[inline]
fn eip712_hash_struct(&self) -> B256 {
let mut hasher = alloy_primitives::Keccak256::new();
hasher.update(self.eip712_type_hash());
hasher.update(self.eip712_encode_data());
hasher.finalize()
}
#[doc(alias = "sign_typed_data")]
#[doc(alias = "hash_typed_data")]
fn eip712_signing_hash(&self, domain: &Eip712Domain) -> B256 {
let mut digest_input = [0u8; 2 + 32 + 32];
digest_input[0] = 0x19;
digest_input[1] = 0x01;
digest_input[2..34].copy_from_slice(&domain.hash_struct()[..]);
digest_input[34..66].copy_from_slice(&self.eip712_hash_struct()[..]);
keccak256(digest_input)
}
}