1
2use core::fmt::Debug;
3use saa_schema::wasm_serde;
4
5use crate::{ensure, AuthError, Binary, CredentialInfo};
6
7#[cfg(feature = "wasm")]
8use crate::cosmwasm::{CustomMsg, Storage, Env};
9
10#[wasm_serde]
11pub struct AuthPayload<E = Binary> {
12 pub hrp: Option<String>,
13 pub address: Option<String>,
14 pub credential_id: Option<Binary>,
15 pub extension: Option<E>
16}
17
18
19impl<E> AuthPayload<E> {
20
21 pub fn validate(&self) -> Result<(), AuthError> {
22 let error : &str = "Only one of the 'address' or 'hrp' can be provided";
23
24 if self.hrp.is_some() {
25 ensure!(
26 self.address.is_none(),
27 AuthError::generic(error)
28 );
29 }
30 if self.address.is_some() {
31 ensure!(self.hrp.is_none(), AuthError::generic(error));
32 let addr = self.address.clone().unwrap();
33 ensure!(
34 addr.len() > 3 && (addr.starts_with("0x") || addr.contains("1")),
35 AuthError::generic("Invalid address")
36 );
37 }
38 Ok(())
39 }
40
41 #[cfg(feature = "wasm")]
42 pub fn validate_cosmwasm(
43 &self,
44 #[cfg(feature = "storage")]
45 store: &dyn Storage
46 ) -> Result<(), AuthError> {
47
48 self.validate()?;
49 #[cfg(feature = "storage")]
50 if self.credential_id.is_some() {
51 let info_res = crate::storage::get_cred_info(
52 store,
53 self.credential_id.clone().unwrap().to_vec()
54 );
55 ensure!(info_res.is_ok(), AuthError::NotFound);
56
57 if self.hrp.is_some() {
58 let name = info_res.unwrap().name;
59 ensure!(
60 name == crate::CredentialName::CosmosArbitrary || name == crate::CredentialName::Secp256k1,
61 AuthError::generic("'hrp' can only be passed for 'cosmos-arbitrary' or 'secp256k1'")
62 );
63 }
64 }
65 Ok(())
66 }
67
68}
69
70
71#[wasm_serde]
72pub struct MsgDataToSign<M = String> {
73 pub chain_id: String,
74 pub contract_address: String,
75 pub messages: Vec<M>,
76 pub nonce: String,
77}
78
79
80#[derive(Clone, Debug, PartialEq)]
81#[cfg_attr(feature = "wasm", derive(
82 ::saa_schema::serde::Serialize,
83 ::saa_schema::serde::Deserialize,
84 ::saa_schema::schemars::JsonSchema
85), schemars(crate = "::saa_schema::schemars"
86))]
87#[cfg_attr(feature = "substrate", derive(
88 ::saa_schema::scale::Encode, ::saa_schema::scale::Decode
89))]
90#[cfg_attr(feature = "solana", derive(
91 ::saa_schema::borsh::BorshSerialize, ::saa_schema::borsh::BorshDeserialize
92))]
93#[cfg_attr(all(feature = "std", feature="substrate"), derive(saa_schema::scale_info::TypeInfo))]
94#[allow(clippy::derive_partial_eq_without_eq)]
95pub struct MsgDataToVerify {
96 pub chain_id: String,
97 pub contract_address: String,
98 pub nonce: String,
99}
100
101
102impl<M> Into<MsgDataToVerify> for &MsgDataToSign<M> {
103 fn into(self) -> MsgDataToVerify {
104 MsgDataToVerify {
105 chain_id: self.chain_id.clone(),
106 contract_address: self.contract_address.clone(),
107 nonce: self.nonce.clone(),
108 }
109 }
110}
111
112
113#[cfg(feature = "wasm")]
114impl MsgDataToVerify {
115 pub fn validate_cosmwasm(
116 &self,
117 #[cfg(feature = "replay")]
118 store: &dyn Storage,
119 env: &Env
120 ) -> Result<(), AuthError> {
121 ensure!(self.chain_id == env.block.chain_id, AuthError::ChainIdMismatch);
122 ensure!(self.contract_address == env.contract.address.to_string(), AuthError::ContractMismatch);
123 ensure!(self.nonce.len() > 0, AuthError::MissingData("Nonce".to_string()));
124 #[cfg(feature = "replay")]
125 ensure!(crate::storage::ACCOUNT_NUMBER.load(store)
126 .unwrap_or_default().to_string() == self.nonce, AuthError::DifferentNonce);
127 Ok(())
128 }
129}
130
131
132#[cfg(feature = "wasm")]
133impl<M> MsgDataToSign<M> {
134 pub fn validate_cosmwasm(
135 &self,
136 #[cfg(feature = "replay")]
137 store: &dyn Storage,
138 env: &Env
139 ) -> Result<(), AuthError> {
140 Into::<MsgDataToVerify>::into(self)
141 .validate_cosmwasm(
142 #[cfg(feature = "replay")]
143 store,
144 env
145 )
146 }
147}
148
149
150#[wasm_serde]
151pub struct SignedDataMsg {
152 pub data: Binary,
153 pub signature: Binary,
154 pub payload: Option<AuthPayload>,
155}
156
157
158
159#[wasm_serde]
160pub struct AccountCredentials {
161 pub credentials: Vec<(Binary, CredentialInfo)>,
162 pub verifying_id: Binary,
163 pub native_caller: bool,
164}
165
166
167
168#[cfg(feature = "wasm")]
169impl CustomMsg for SignedDataMsg {}