andromeda_data_storage/
primitive.rs

1use andromeda_std::{amp::AndrAddr, andr_exec, andr_instantiate, andr_query};
2use cosmwasm_schema::{cw_serde, schemars::Map, QueryResponses};
3use cosmwasm_std::{Addr, Binary, Coin, Decimal, StdError, Uint128};
4
5#[andr_instantiate]
6#[cw_serde]
7pub struct InstantiateMsg {
8    pub restriction: PrimitiveRestriction,
9}
10
11#[andr_exec]
12#[cw_serde]
13pub enum ExecuteMsg {
14    /// If key is not specified the default key will be used.
15    SetValue {
16        key: Option<String>,
17        value: Primitive,
18    },
19    /// If key is not specified the default key will be used.
20    DeleteValue {
21        key: Option<String>,
22    },
23    UpdateRestriction {
24        restriction: PrimitiveRestriction,
25    },
26}
27
28#[andr_query]
29#[cw_serde]
30#[derive(QueryResponses)]
31pub enum QueryMsg {
32    #[returns(GetValueResponse)]
33    GetValue { key: Option<String> },
34    #[returns(Vec<String>)]
35    AllKeys {},
36    #[returns(Vec<String>)]
37    OwnerKeys { owner: AndrAddr },
38}
39
40#[cw_serde]
41pub enum Primitive {
42    Uint128(Uint128),
43    Decimal(Decimal),
44    Coin(Coin),
45    Addr(Addr),
46    String(String),
47    Bool(bool),
48    Vec(Vec<Primitive>),
49    Binary(Binary),
50    Object(Map<String, Primitive>),
51}
52
53#[cw_serde]
54pub enum PrimitiveRestriction {
55    Private,
56    Public,
57    Restricted,
58}
59
60fn parse_error(type_name: String) -> StdError {
61    StdError::ParseErr {
62        target_type: type_name.clone(),
63        msg: format!("Primitive is not a {type_name}"),
64    }
65}
66
67impl From<String> for Primitive {
68    fn from(value: String) -> Self {
69        Primitive::String(value)
70    }
71}
72
73impl From<Uint128> for Primitive {
74    fn from(value: Uint128) -> Self {
75        Primitive::Uint128(value)
76    }
77}
78
79impl From<Decimal> for Primitive {
80    fn from(value: Decimal) -> Self {
81        Primitive::Decimal(value)
82    }
83}
84
85impl From<bool> for Primitive {
86    fn from(value: bool) -> Self {
87        Primitive::Bool(value)
88    }
89}
90
91impl From<Coin> for Primitive {
92    fn from(value: Coin) -> Self {
93        Primitive::Coin(value)
94    }
95}
96
97impl From<Addr> for Primitive {
98    fn from(value: Addr) -> Self {
99        Primitive::Addr(value)
100    }
101}
102
103impl From<Vec<Primitive>> for Primitive {
104    fn from(value: Vec<Primitive>) -> Self {
105        Primitive::Vec(value)
106    }
107}
108
109impl From<Binary> for Primitive {
110    fn from(value: Binary) -> Self {
111        Primitive::Binary(value)
112    }
113}
114
115impl From<Map<String, Primitive>> for Primitive {
116    fn from(value: Map<String, Primitive>) -> Self {
117        Primitive::Object(value)
118    }
119}
120
121// These are methods to help the calling user quickly retreive the data in the Primitive as they
122// often already know what the type should be.
123impl Primitive {
124    pub fn try_get_uint128(&self) -> Result<Uint128, StdError> {
125        match self {
126            Primitive::Uint128(value) => Ok(*value),
127            _ => Err(parse_error(String::from("Uint128"))),
128        }
129    }
130
131    pub fn try_get_decimal(&self) -> Result<Decimal, StdError> {
132        match self {
133            Primitive::Decimal(value) => Ok(*value),
134            _ => Err(parse_error(String::from("Decimal"))),
135        }
136    }
137
138    pub fn try_get_string(&self) -> Result<String, StdError> {
139        match self {
140            Primitive::String(value) => Ok(value.to_string()),
141            _ => Err(parse_error(String::from("String"))),
142        }
143    }
144
145    pub fn try_get_bool(&self) -> Result<bool, StdError> {
146        match self {
147            Primitive::Bool(value) => Ok(*value),
148            _ => Err(parse_error(String::from("bool"))),
149        }
150    }
151
152    pub fn try_get_vec(&self) -> Result<Vec<Primitive>, StdError> {
153        match self {
154            Primitive::Vec(vector) => Ok(vector.to_vec()),
155            _ => Err(parse_error(String::from("Vec"))),
156        }
157    }
158
159    pub fn try_get_coin(&self) -> Result<Coin, StdError> {
160        match self {
161            Primitive::Coin(coin) => Ok(coin.clone()),
162            _ => Err(parse_error(String::from("Coin"))),
163        }
164    }
165
166    pub fn try_get_addr(&self) -> Result<Addr, StdError> {
167        match self {
168            Primitive::Addr(addr) => Ok(addr.clone()),
169            _ => Err(parse_error(String::from("Addr"))),
170        }
171    }
172
173    pub fn try_get_binary(&self) -> Result<Binary, StdError> {
174        match self {
175            Primitive::Binary(value) => Ok(value.clone()),
176            _ => Err(parse_error(String::from("Binary"))),
177        }
178    }
179
180    pub fn try_get_object(&self) -> Result<Map<String, Primitive>, StdError> {
181        match self {
182            Primitive::Object(value) => Ok(value.clone()),
183            _ => Err(parse_error(String::from("Binary"))),
184        }
185    }
186}
187
188#[cw_serde]
189pub struct GetValueResponse {
190    pub key: String,
191    pub value: Primitive,
192}
193
194#[cfg(test)]
195mod tests {
196    use super::*;
197    use cosmwasm_std::to_json_binary;
198
199    #[test]
200    fn test_parse_error() {
201        assert_eq!(
202            StdError::ParseErr {
203                target_type: "target_type".to_string(),
204                msg: "Primitive is not a target_type".to_string()
205            },
206            parse_error("target_type".to_string())
207        );
208    }
209
210    #[test]
211    fn try_get_uint128() {
212        let primitive = Primitive::Uint128(Uint128::from(5_u128));
213        assert_eq!(Uint128::from(5_u128), primitive.try_get_uint128().unwrap());
214
215        let primitive = Primitive::Bool(true);
216        assert_eq!(
217            parse_error("Uint128".to_string()),
218            primitive.try_get_uint128().unwrap_err()
219        );
220    }
221
222    #[test]
223    fn try_get_string() {
224        let primitive = Primitive::String("String".to_string());
225        assert_eq!("String".to_string(), primitive.try_get_string().unwrap());
226
227        let primitive = Primitive::Bool(true);
228        assert_eq!(
229            parse_error("String".to_string()),
230            primitive.try_get_string().unwrap_err()
231        );
232    }
233
234    #[test]
235    fn try_get_bool() {
236        let primitive = Primitive::Bool(true);
237        assert!(primitive.try_get_bool().unwrap());
238
239        let primitive = Primitive::String("String".to_string());
240        assert_eq!(
241            parse_error("bool".to_string()),
242            primitive.try_get_bool().unwrap_err()
243        );
244    }
245
246    #[test]
247    fn try_get_vec() {
248        let primitive = Primitive::Vec(vec![Primitive::Bool(true)]);
249        assert_eq!(
250            vec![Primitive::Bool(true)],
251            primitive.try_get_vec().unwrap()
252        );
253
254        let primitive = Primitive::Vec(vec![Primitive::Vec(vec![Primitive::Bool(true)])]);
255        assert_eq!(
256            vec![Primitive::Vec(vec![Primitive::Bool(true)])],
257            primitive.try_get_vec().unwrap()
258        );
259
260        let primitive = Primitive::String("String".to_string());
261        assert_eq!(
262            parse_error("Vec".to_string()),
263            primitive.try_get_vec().unwrap_err()
264        );
265    }
266
267    #[test]
268    fn try_get_decimal() {
269        let primitive = Primitive::Decimal(Decimal::zero());
270        assert_eq!(Decimal::zero(), primitive.try_get_decimal().unwrap());
271
272        let primitive = Primitive::String("String".to_string());
273        assert_eq!(
274            parse_error("Decimal".to_string()),
275            primitive.try_get_decimal().unwrap_err()
276        );
277    }
278
279    #[test]
280    fn try_get_binary() {
281        let primitive = Primitive::Binary(to_json_binary("data").unwrap());
282        assert_eq!(
283            to_json_binary("data").unwrap(),
284            primitive.try_get_binary().unwrap()
285        );
286
287        let primitive = Primitive::String("String".to_string());
288        assert_eq!(
289            parse_error("Binary".to_string()),
290            primitive.try_get_binary().unwrap_err()
291        );
292    }
293
294    #[test]
295    fn try_get_object() {
296        let mut map = Map::new();
297        map.insert("key".to_string(), Primitive::Bool(true));
298        let primitive = Primitive::Object(map.clone());
299        assert_eq!(map.clone(), primitive.try_get_object().unwrap());
300    }
301}