apollo_utils/
submessages.rs

1use std::str::FromStr;
2
3use core::fmt::Debug;
4use cosmwasm_std::{Event, StdError, StdResult, SubMsgResponse};
5
6/// Parse an attribute string from an [`Event`]
7pub fn parse_attribute_value<T: FromStr<Err = E>, E: Debug>(
8    event: &Event,
9    attr_key: &str,
10) -> StdResult<T> {
11    T::from_str(
12        event
13            .attributes
14            .iter()
15            .find(|attr| attr.key == attr_key)
16            .ok_or_else(|| {
17                StdError::generic_err(format!(
18                    "Event {} event does not contain {} attribute",
19                    event.ty, attr_key
20                ))
21            })?
22            .value
23            .as_str(),
24    )
25    .map_err(|e| {
26        StdError::generic_err(format!(
27            "Failed to parse attribute value from string. Error: {:?}",
28            e
29        ))
30    })
31}
32
33/// Find event from SubMsg response
34///
35/// Returns a [`StdResult`] containing reference to the event if found otherwise
36/// [`StdError`]
37pub fn find_event<'a>(res: &'a SubMsgResponse, event_type: &str) -> StdResult<&'a Event> {
38    res.events
39        .iter()
40        .find(|event| event.ty == event_type)
41        .ok_or(StdError::generic_err(format!(
42            "No `{}` event found",
43            event_type
44        )))
45}
46
47#[cfg(test)]
48mod tests {
49    use std::num::ParseIntError;
50
51    use cosmwasm_std::Attribute;
52
53    use super::*;
54
55    #[test]
56    fn test_find_event_success() {
57        let event1 = Event::new("event_type_1");
58        let event2 = Event::new("event_type_2");
59        let events = vec![event1, event2];
60        let res = SubMsgResponse { events, data: None };
61        let result = find_event(&res, "event_type_1");
62        assert!(result.is_ok());
63        let found_event = result.unwrap();
64        assert_eq!(found_event.ty, "event_type_1");
65    }
66
67    #[test]
68    fn test_find_event_not_found() {
69        let event1 = Event::new("event_type_1");
70        let event2 = Event::new("event_type_2");
71        let events = vec![event1, event2];
72        let res = SubMsgResponse { events, data: None };
73        let result = find_event(&res, "event_type_3");
74        assert!(result.is_err());
75        let err = result.unwrap_err();
76        assert_eq!(
77            err.to_string(),
78            "Generic error: No `event_type_3` event found"
79        );
80    }
81
82    #[test]
83    fn test_parse_attribute_value_success() {
84        let attr1 = Attribute::new("key_1", "value_1");
85        let attr2 = Attribute::new("key_2", "2");
86        let attributes = vec![attr1, attr2];
87        let event = Event::new("event_type").add_attributes(attributes);
88
89        let result = parse_attribute_value::<i32, ParseIntError>(&event, "key_2");
90        assert!(result.is_ok());
91        let parsed_value = result.unwrap();
92        assert_eq!(parsed_value, 2);
93    }
94
95    #[test]
96    fn test_parse_attribute_value_not_found() {
97        let attr1 = Attribute::new("key_1", "value_1");
98        let attr2 = Attribute::new("key_2", "2");
99        let attributes = vec![attr1, attr2];
100        let event = Event::new("event_type").add_attributes(attributes);
101
102        let result = parse_attribute_value::<i32, ParseIntError>(&event, "key_3");
103        assert!(result.is_err());
104        let err = result.unwrap_err();
105        assert_eq!(
106            err.to_string(),
107            "Generic error: Event event_type event does not contain key_3 attribute"
108        );
109    }
110
111    #[test]
112    fn test_parse_attribute_value_parse_error() {
113        let attr1 = Attribute::new("key_1", "value_1");
114        let attr2 = Attribute::new("key_2", "not_a_number");
115        let attributes = vec![attr1, attr2];
116        let event = Event::new("event_type").add_attributes(attributes);
117
118        let result = parse_attribute_value::<i32, ParseIntError>(&event, "key_2");
119        assert!(result.is_err());
120        let err = result.unwrap_err();
121        assert_eq!(
122            err.to_string(),
123            "Generic error: Failed to parse attribute value from string. Error: ParseIntError { kind: InvalidDigit }"
124        );
125    }
126}