Skip to main content

aleph_types/message/
post.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
4pub struct PostContent {
5    #[serde(rename = "type")]
6    pub post_type: String,
7    #[serde(rename = "ref", default, skip_serializing_if = "Option::is_none")]
8    pub reference: Option<String>,
9    #[serde(default, skip_serializing_if = "Option::is_none")]
10    pub content: Option<serde_json::Value>,
11}
12
13impl PostContent {
14    pub fn is_amend(&self) -> bool {
15        self.post_type == "amend"
16    }
17
18    pub fn post_type_str(&self) -> &str {
19        &self.post_type
20    }
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26    use crate::chain::Chain;
27    use crate::message::base_message::MessageContentEnum;
28    use crate::message::{ContentSource, Message, MessageType};
29    use crate::timestamp::Timestamp;
30    use crate::{address, channel, item_hash, signature};
31    use assert_matches::assert_matches;
32
33    const POST_FIXTURE: &str = include_str!(concat!(
34        env!("CARGO_MANIFEST_DIR"),
35        "/../../fixtures/messages/post/post.json"
36    ));
37
38    const AMEND_FIXTURE: &str = include_str!(concat!(
39        env!("CARGO_MANIFEST_DIR"),
40        "/../../fixtures/messages/post/amend.json"
41    ));
42
43    #[test]
44    fn test_deserialize_post() {
45        let message: Message = serde_json::from_str(POST_FIXTURE).unwrap();
46
47        assert_eq!(
48            message.sender,
49            address!("0xB68B9D4f3771c246233823ed1D3Add451055F9Ef")
50        );
51        assert_eq!(message.chain, Chain::Ethereum);
52        assert_eq!(
53            message.signature,
54            Some(signature!(
55                "0x636728dbea33fa6064f099045421b980dff3c71932cd89c2bf42387ebb6f53890a24e13f16678463876224772b90838c2b9557cd8fc2cdae45509ce8cb89e3fd1b"
56            ))
57        );
58        assert_matches!(message.message_type, MessageType::Post);
59        assert_matches!(
60            message.content_source,
61            ContentSource::Inline { item_content: _ }
62        );
63        assert_eq!(
64            message.item_hash,
65            item_hash!("d281eb8a69ba1f4dda2d71aaf3ded06caa92edd690ef3d0632f41aa91167762c")
66        );
67        assert_eq!(message.time, Timestamp::from(1762515431.653));
68        assert_eq!(message.channel, Some(channel!("TEST")));
69
70        // Check content fields
71        assert_eq!(
72            &message.content.address,
73            &address!("0xB68B9D4f3771c246233823ed1D3Add451055F9Ef")
74        );
75        assert_eq!(&message.content.time, &Timestamp::from(1762515431.653));
76        assert_eq!(message.sent_at(), &message.content.time);
77
78        // Check aggregate content fields
79        let post_content = match message.content() {
80            MessageContentEnum::Post(content) => content,
81            other => {
82                panic!("Expected MessageContentEnum::Post, got {:?}", other);
83            }
84        };
85
86        #[derive(Deserialize)]
87        struct ContentStruct {
88            body: String,
89        }
90        let deserialized_content =
91            serde_json::from_value::<ContentStruct>(post_content.content.clone().unwrap()).unwrap();
92        assert_eq!(deserialized_content.body, "Hello World");
93
94        assert!(!post_content.is_amend());
95        assert_eq!(
96            post_content.post_type_str(),
97            "05567c5b-0606-4a6e-a639-25734c06e2a0"
98        );
99
100        // No confirmation on this fixture
101        assert!(!message.confirmed());
102        assert!(message.confirmations.is_empty());
103
104        message.verify_item_hash().unwrap();
105    }
106
107    #[test]
108    fn test_deserialize_amend() {
109        let message: Message = serde_json::from_str(AMEND_FIXTURE).unwrap();
110
111        assert_eq!(
112            message.sender,
113            address!("0xB68B9D4f3771c246233823ed1D3Add451055F9Ef")
114        );
115        assert_eq!(message.chain, Chain::Ethereum);
116        assert_eq!(
117            message.signature,
118            Some(signature!(
119                "0xf4a171d2715f2249c6f78160a83a64fb05c21962acdf3729e373fd4f527ed9f570274dedcc468195ba40a26002be0b72aedf260df74032d4ef5a12cb4ea838831c"
120            ))
121        );
122        assert_matches!(message.message_type, MessageType::Post);
123        assert_matches!(
124            message.content_source,
125            ContentSource::Inline { item_content: _ }
126        );
127        assert_eq!(
128            message.item_hash,
129            item_hash!("203291b2581b379997b8a0fda43d3afe27573489ca695b711d67fd1a6311b3dd")
130        );
131        assert_eq!(message.time, Timestamp::from(1762515432.375));
132        assert_eq!(message.channel, Some(channel!("TEST")));
133
134        // Check content fields
135        assert_eq!(
136            &message.content.address,
137            &address!("0xB68B9D4f3771c246233823ed1D3Add451055F9Ef")
138        );
139        assert_eq!(&message.content.time, &Timestamp::from(1762515432.375));
140        assert_eq!(message.sent_at(), &message.content.time);
141
142        // Check aggregate content fields
143        let post_content = match message.content() {
144            MessageContentEnum::Post(content) => content,
145            other => {
146                panic!("Expected MessageContentEnum::Post, got {:?}", other);
147            }
148        };
149
150        #[derive(Deserialize)]
151        struct ContentStruct {
152            body: String,
153        }
154        let deserialized_content =
155            serde_json::from_value::<ContentStruct>(post_content.content.clone().unwrap()).unwrap();
156        assert_eq!(deserialized_content.body, "New content !");
157
158        assert!(post_content.is_amend());
159        assert_eq!(post_content.post_type_str(), "amend");
160
161        // No confirmation on this fixture
162        assert!(!message.confirmed());
163        assert!(message.confirmations.is_empty());
164
165        message.verify_item_hash().unwrap();
166    }
167}