Skip to main content

aleph_types/message/
post.rs

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