Skip to main content

xmtp_content_types/
membership_change.rs

1use std::collections::HashMap;
2
3use prost::Message;
4
5use xmtp_proto::xmtp::mls::message_contents::{
6    ContentTypeId, EncodedContent, GroupMembershipChanges,
7};
8
9use super::{CodecError, ContentCodec};
10
11pub struct GroupMembershipChangeCodec {}
12
13impl GroupMembershipChangeCodec {
14    const AUTHORITY_ID: &'static str = "xmtp.org";
15    pub const TYPE_ID: &'static str = "group_membership_change";
16    pub const MAJOR_VERSION: u32 = 1;
17    pub const MINOR_VERSION: u32 = 0;
18}
19
20impl ContentCodec<GroupMembershipChanges> for GroupMembershipChangeCodec {
21    fn content_type() -> ContentTypeId {
22        ContentTypeId {
23            authority_id: GroupMembershipChangeCodec::AUTHORITY_ID.to_string(),
24            type_id: GroupMembershipChangeCodec::TYPE_ID.to_string(),
25            version_major: GroupMembershipChangeCodec::MAJOR_VERSION,
26            version_minor: GroupMembershipChangeCodec::MINOR_VERSION,
27        }
28    }
29
30    fn encode(data: GroupMembershipChanges) -> Result<EncodedContent, CodecError> {
31        let mut buf = Vec::new();
32        data.encode(&mut buf)
33            .map_err(|e| CodecError::Encode(e.to_string()))?;
34
35        Ok(EncodedContent {
36            r#type: Some(GroupMembershipChangeCodec::content_type()),
37            parameters: HashMap::new(),
38            fallback: None,
39            compression: None,
40            content: buf,
41        })
42    }
43
44    fn decode(content: EncodedContent) -> Result<GroupMembershipChanges, CodecError> {
45        let decoded = GroupMembershipChanges::decode(content.content.as_slice())
46            .map_err(|e| CodecError::Decode(e.to_string()))?;
47
48        Ok(decoded)
49    }
50
51    fn should_push() -> bool {
52        false
53    }
54}
55
56#[cfg(test)]
57pub(crate) mod tests {
58    use super::*;
59    use xmtp_common::{rand_string, rand_vec};
60    use xmtp_proto::xmtp::mls::message_contents::MembershipChange;
61
62    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
63    #[cfg_attr(not(target_arch = "wasm32"), test)]
64    fn test_encode_decode() {
65        let new_member = MembershipChange {
66            installation_ids: vec![rand_vec::<24>()],
67            account_address: rand_string::<24>(),
68            initiated_by_account_address: "".to_string(),
69        };
70        let data = GroupMembershipChanges {
71            members_added: vec![new_member.clone()],
72            members_removed: vec![],
73            installations_added: vec![],
74            installations_removed: vec![],
75        };
76
77        let encoded = GroupMembershipChangeCodec::encode(data).unwrap();
78        assert_eq!(
79            encoded.clone().r#type.unwrap().type_id,
80            "group_membership_change"
81        );
82        assert!(!encoded.content.is_empty());
83
84        let decoded = GroupMembershipChangeCodec::decode(encoded).unwrap();
85        assert_eq!(decoded.members_added[0], new_member);
86    }
87}