1use {
2 cosmwasm_std::{from_json, to_json_binary, Addr, Api, Binary, StdError, StdResult},
3 serde::{de::DeserializeOwned, Serialize},
4 std::{cmp::min, error::Error},
5};
6
7pub trait IntoAddr: Into<String> + Clone {
8 fn into_addr(self, api: &dyn Api) -> StdResult<Addr> {
9 api.addr_validate(&self.into())
10 }
11 fn into_unchecked_addr(&self) -> Addr {
12 Addr::unchecked(self.clone())
13 }
14}
15
16impl<T> IntoAddr for T where T: Into<String> + Clone {}
17
18pub trait IntoBinaryResult {
19 fn into_binary(self) -> StdResult<Binary>;
21}
22
23impl<T> IntoBinaryResult for StdResult<T>
24where
25 T: Serialize,
26{
27 fn into_binary(self) -> StdResult<Binary> {
28 to_json_binary(&self?)
29 }
30}
31
32pub trait IntoBinary {
33 fn into_binary(self) -> StdResult<Binary>;
35}
36
37impl<T> IntoBinary for T
38where
39 T: Serialize,
40{
41 fn into_binary(self) -> StdResult<Binary> {
42 to_json_binary(&self)
43 }
44}
45
46pub trait FromBinaryResult {
47 fn des_into<T: DeserializeOwned>(self) -> StdResult<T>;
49}
50
51impl FromBinaryResult for StdResult<Binary> {
52 fn des_into<T: DeserializeOwned>(self) -> StdResult<T> {
53 from_json(&self?)
54 }
55}
56
57pub trait FromBinary {
58 fn des_into<T: DeserializeOwned>(self) -> StdResult<T>;
60}
61
62impl FromBinary for Binary {
63 fn des_into<T: DeserializeOwned>(self) -> StdResult<T> {
64 from_json(&self)
65 }
66}
67
68pub trait IntoStdResult<T> {
69 fn into_std_result(self) -> StdResult<T>;
70}
71impl<T, E> IntoStdResult<T> for Result<T, E>
72where
73 E: std::error::Error,
74{
75 fn into_std_result(self) -> StdResult<T> {
76 self.map_err(|err| StdError::generic_err(err.to_string()))
77 }
78}
79
80pub trait MapMin {
81 type Output;
82 type Input;
83 fn map_min(&self, with: Self::Input) -> Self::Output;
84}
85
86impl<T: Ord + Copy> MapMin for Option<T> {
87 type Output = Option<T>;
88 type Input = T;
89
90 fn map_min(&self, with: Self::Input) -> Self::Output {
91 self.map(|val| min(val, with))
92 }
93}
94
95pub trait AssertOwner {
96 fn get_admin(&self) -> Addr;
97
98 fn assert_admin(&self, address: Addr) -> StdResult<()> {
99 if self.get_admin() != address {
100 return Err(StdError::generic_err("Unauthorized"));
101 }
102
103 Ok(())
104 }
105}
106
107pub trait Unclone {
108 type Output;
109 fn unclone(&self) -> Self::Output;
110}
111
112impl<T> Unclone for Option<T>
113where
114 T: Clone,
115{
116 type Output = T;
117
118 fn unclone(&self) -> Self::Output {
119 self.clone().unwrap()
120 }
121}
122
123pub trait Wrapper: Sized {
124 fn wrap_ok<E: Error>(self) -> Result<Self, E> {
126 Ok(self)
127 }
128
129 fn wrap_some(self) -> Option<Self> {
130 Some(self)
131 }
132}
133
134impl<T> Wrapper for T {}
135
136#[cfg(test)]
137mod test {
138 use cosmwasm_std::{testing::mock_dependencies, Addr, Coin, StdError};
139
140 use crate::traits::{FromBinary, FromBinaryResult, IntoAddr, IntoBinary, IntoBinaryResult};
141
142 #[test]
143 fn test() {
144 let coin = Coin::new(1, "asd");
145
146 let coin_binary = coin.clone().into_binary().unwrap();
147
148 let res_binary = Ok::<_, StdError>(coin.clone()).into_binary().unwrap();
149
150 let coin_std: Coin = coin_binary.des_into().unwrap();
151 let coin_res = Ok(res_binary).des_into::<Coin>().unwrap();
152
153 assert_eq!(coin_std, coin);
154 assert_eq!(coin_res, coin);
155
156 assert_eq!(
157 Addr::unchecked("terra123"),
158 "terra123".into_unchecked_addr()
159 );
160 assert_eq!(
161 Addr::unchecked("terra123"),
162 "terra123".to_string().into_unchecked_addr()
163 );
164
165 let deps = mock_dependencies();
166
167 assert_eq!(
168 Addr::unchecked("terra123"),
169 "terra123".into_addr(&deps.api).unwrap()
170 );
171 assert_eq!(
172 Addr::unchecked("terra123"),
173 "terra123".to_string().into_addr(&deps.api).unwrap()
174 );
175 }
176}