use crate::{AuthError, Binary, String, Uint64};
use saa_schema::{saa_type, schemars::{self, JsonSchema}};
use std::collections::BTreeMap;
use serde_json::Value;
pub type Eip712Types = BTreeMap<String, Vec<Eip712DomainType>>;
#[cfg_attr(not(feature = "wasm"), derive(serde::Serialize, serde::Deserialize))]
#[saa_type(no_deny)]
#[non_exhaustive]
pub struct Eip712MessageProps {}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[non_exhaustive]
pub struct Eip712Message {
pub nonce: Option<Uint64>,
#[serde(flatten)]
pub props: BTreeMap<Value, Value>,
}
#[cfg(feature = "cosmwasm")]
impl saa_schema::Schemaifier for Eip712Message {
fn visit_schema(visitor: &mut cw_schema::SchemaVisitor) -> cw_schema::DefinitionReference {
if let Some(existing) = visitor.get_reference::<Self>() {
return existing;
}
let id = Self::id();
visitor.insert(
id,
cw_schema::Node {
name: "Eip712Message".into(),
description: Some("EIP-712 message structure".into()),
value: cw_schema::NodeType::Struct(cw_schema::StructType::Unit),
},
)
}
}
impl Eip712Message {
pub fn contains_key(&self, key: &str) -> bool {
key == "nonce" || self.props.contains_key(&Value::String(key.to_string()))
}
pub fn get(&self, key: &str) -> Option<Value> {
self.props.get(&Value::String(key.to_string()))
.cloned()
}
pub fn gets(&self, key: &str) -> Option<Vec<Value>> {
self.props.get(&Value::String(format!("{}s", key)))
.and_then(|value| match value {
Value::Seq(arr) => Some(arr.clone()),
_ => None,
})
}
pub fn is_empty(&self) -> bool {
self.props.is_empty() && self.nonce.is_none()
}
pub fn to_value(&self) -> Value {
let mut map = BTreeMap::<Value, Value>::new();
for (key, value) in &self.props {
map.insert(key.clone(), value.clone());
}
if let Some(nonce) = self.nonce {
map.insert(Value::String("nonce".into()), Value::String(nonce.to_string()));
}
Value::Map(map)
}
pub fn to_string(&self) -> Result<String, AuthError> {
crate::to_json_string(&self.to_value())
.map_err(|e| AuthError::generic(e.to_string()))
}
pub fn to_binary(&self) -> Result<Binary, AuthError> {
crate::to_json_binary(&self.to_value())
.map_err(|e| AuthError::generic(e.to_string()))
}
}
impl JsonSchema for Eip712Message {
fn schema_name() -> String {
"Eip712Message".to_string()
}
fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
schemars::schema::Schema::Object(schemars::schema::SchemaObject {
metadata: Some(Box::new(schemars::schema::Metadata {
description: Some("EIP-712 message structure".to_string()),
..Default::default()
})),
instance_type: Some(schemars::schema::SingleOrVec::Single(Box::new(
schemars::schema::InstanceType::Object)
)),
..Default::default()
})
}
}
#[saa_type]
pub struct Eip712DomainType {
pub name: String,
#[serde(rename = "type")]
pub r#type: String,
}
#[saa_type]
pub struct Eip712Domain {
pub name: Option<String>,
pub version: Option<String>,
#[serde(rename = "chainId", skip_serializing_if = "Option::is_none")]
pub chain_id: Option<crate::Uint64>,
#[serde(rename = "verifyingContract")]
pub verifying_contract: Option<String>,
pub salt: Option<Vec<u8>>,
}
#[saa_type]
pub struct EthTypedInfo {
pub addr_hash : Option<String>,
pub pre_hash : Vec<u8>,
pub salt_used : bool,
}
#[saa_type(no_deny)]
#[non_exhaustive]
pub struct EthTypedPayload {
pub types : Option<Eip712Types>,
pub primary_type : Option<String>,
pub message_property : Option<String>,
pub domain : Option<Eip712Domain>,
pub contract_addr : Option<String>,
pub salt : Option<Binary>
}