Skip to main content

xmtp_events/
event.rs

1//! The public event contract. Payloads contain identifiers and small values.
2
3pub use xmtp_common::types::ContentTypeId;
4
5/// The order is the order of the EVENT kind table.
6#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
7pub enum EventKind {
8    ConversationJoined,
9    ConversationRemoved,
10    ConversationMembershipChanged,
11    ConversationMetadataChanged,
12    ConversationPaused,
13    MessageReceived,
14    MessageStatusChanged,
15    MessageDeleted,
16    MessageExpired,
17    ConsentChanged,
18    HmacKeysUpdated,
19    IdentityRegistered,
20    IdentityOwnInstallationAdded,
21    IdentityOwnInstallationRevoked,
22    ClientRejectedByServer,
23    ClientLockoutChanged,
24    ConversationForkDetected,
25    NotificationsFailed,
26    ArchiveRestored,
27    ConnectionStateChanged,
28    AttachmentUploadStarted,
29    AttachmentUploadCompleted,
30    AttachmentUploadFailed,
31    AttachmentDownloadStarted,
32    AttachmentDownloadCompleted,
33    AttachmentDownloadFailed,
34    AttachmentDeleted,
35    HandleChanged,
36    Lagged,
37}
38
39impl EventKind {
40    pub const ALL: [Self; 29] = [
41        Self::ConversationJoined,
42        Self::ConversationRemoved,
43        Self::ConversationMembershipChanged,
44        Self::ConversationMetadataChanged,
45        Self::ConversationPaused,
46        Self::MessageReceived,
47        Self::MessageStatusChanged,
48        Self::MessageDeleted,
49        Self::MessageExpired,
50        Self::ConsentChanged,
51        Self::HmacKeysUpdated,
52        Self::IdentityRegistered,
53        Self::IdentityOwnInstallationAdded,
54        Self::IdentityOwnInstallationRevoked,
55        Self::ClientRejectedByServer,
56        Self::ClientLockoutChanged,
57        Self::ConversationForkDetected,
58        Self::NotificationsFailed,
59        Self::ArchiveRestored,
60        Self::ConnectionStateChanged,
61        Self::AttachmentUploadStarted,
62        Self::AttachmentUploadCompleted,
63        Self::AttachmentUploadFailed,
64        Self::AttachmentDownloadStarted,
65        Self::AttachmentDownloadCompleted,
66        Self::AttachmentDownloadFailed,
67        Self::AttachmentDeleted,
68        Self::HandleChanged,
69        Self::Lagged,
70    ];
71
72    pub const fn name(self) -> &'static str {
73        match self {
74            Self::ConversationJoined => "conversation.joined",
75            Self::ConversationRemoved => "conversation.removed",
76            Self::ConversationMembershipChanged => "conversation.membership_changed",
77            Self::ConversationMetadataChanged => "conversation.metadata_changed",
78            Self::ConversationPaused => "conversation.paused",
79            Self::MessageReceived => "message.received",
80            Self::MessageStatusChanged => "message.status_changed",
81            Self::MessageDeleted => "message.deleted",
82            Self::MessageExpired => "message.expired",
83            Self::ConsentChanged => "consent.changed",
84            Self::HmacKeysUpdated => "hmac_keys.updated",
85            Self::IdentityRegistered => "identity.registered",
86            Self::IdentityOwnInstallationAdded => "identity.own_installation_added",
87            Self::IdentityOwnInstallationRevoked => "identity.own_installation_revoked",
88            Self::ClientRejectedByServer => "client.rejected_by_server",
89            Self::ClientLockoutChanged => "client.lockout_changed",
90            Self::ConversationForkDetected => "conversation.fork_detected",
91            Self::NotificationsFailed => "notifications.failed",
92            Self::ArchiveRestored => "archive.restored",
93            Self::ConnectionStateChanged => "connection.state_changed",
94            Self::AttachmentUploadStarted => "attachment.upload_started",
95            Self::AttachmentUploadCompleted => "attachment.upload_completed",
96            Self::AttachmentUploadFailed => "attachment.upload_failed",
97            Self::AttachmentDownloadStarted => "attachment.download_started",
98            Self::AttachmentDownloadCompleted => "attachment.download_completed",
99            Self::AttachmentDownloadFailed => "attachment.download_failed",
100            Self::AttachmentDeleted => "attachment.deleted",
101            Self::HandleChanged => "handle.changed",
102            Self::Lagged => "lagged",
103        }
104    }
105}
106
107#[derive(Clone, Copy, Debug, PartialEq, Eq)]
108pub enum ConversationType {
109    Group,
110    Dm,
111}
112#[derive(Clone, Copy, Debug, PartialEq, Eq)]
113pub enum JoinOrigin {
114    Created,
115    Welcomed,
116}
117#[derive(Clone, Copy, Debug, PartialEq, Eq)]
118pub enum RemovalCause {
119    Removed,
120    Left,
121}
122#[derive(Clone, Copy, Debug, PartialEq, Eq)]
123pub enum DeletionCause {
124    Deleted,
125    DeletedLocally,
126}
127#[derive(Clone, Copy, Debug, PartialEq, Eq)]
128pub enum MessageStatus {
129    Unpublished,
130    Published,
131    Failed,
132}
133#[derive(Clone, Copy, Debug, PartialEq, Eq)]
134pub enum ConsentEntityKind {
135    Conversation,
136    Inbox,
137}
138#[derive(Clone, Copy, Debug, PartialEq, Eq)]
139pub enum ConsentState {
140    Unknown,
141    Allowed,
142    Denied,
143}
144#[derive(Clone, Copy, Debug, PartialEq, Eq)]
145pub enum RejectionCause {
146    BackendMismatch,
147    VersionTooOld,
148}
149#[derive(Clone, Copy, Debug, PartialEq, Eq)]
150pub enum LockoutChange {
151    Entered,
152    Left,
153}
154
155#[derive(Clone, Debug, PartialEq, Eq)]
156pub struct GroupRef {
157    pub group_id: Vec<u8>,
158}
159#[derive(Clone, Debug, PartialEq, Eq)]
160pub struct MessageRef {
161    pub group_id: Vec<u8>,
162    pub message_id: Vec<u8>,
163}
164#[derive(Clone, Debug, PartialEq, Eq)]
165pub struct ConversationJoined {
166    pub group_id: Vec<u8>,
167    pub conversation_type: ConversationType,
168    pub origin: JoinOrigin,
169    pub adder_inbox_id: Option<String>,
170}
171#[derive(Clone, Debug, PartialEq, Eq)]
172pub struct ConversationRemoved {
173    pub group_id: Vec<u8>,
174    pub cause: RemovalCause,
175}
176#[derive(Clone, Debug, PartialEq, Eq)]
177pub struct MembershipChanged {
178    pub group_id: Vec<u8>,
179    pub added_inbox_ids: Vec<String>,
180    pub removed_inbox_ids: Vec<String>,
181}
182#[derive(Clone, Debug, PartialEq, Eq)]
183pub struct MetadataChanged {
184    pub group_id: Vec<u8>,
185    pub changed: Vec<String>,
186}
187#[derive(Clone, Debug, PartialEq, Eq)]
188pub struct ConversationPaused {
189    pub group_id: Vec<u8>,
190    pub floor: String,
191}
192#[derive(Clone, Debug, PartialEq, Eq)]
193pub struct MessageReceived {
194    pub group_id: Vec<u8>,
195    pub message_id: Vec<u8>,
196    pub content_type: Option<ContentTypeId>,
197    pub sender_inbox_id: String,
198}
199#[derive(Clone, Debug, PartialEq, Eq)]
200pub struct MessageStatusChanged {
201    pub group_id: Vec<u8>,
202    pub message_id: Vec<u8>,
203    pub previous: MessageStatus,
204    pub current: MessageStatus,
205}
206#[derive(Clone, Debug, PartialEq, Eq)]
207pub struct MessageDeleted {
208    pub group_id: Vec<u8>,
209    pub message_id: Vec<u8>,
210    pub cause: DeletionCause,
211}
212#[derive(Clone, Debug, PartialEq, Eq)]
213pub struct ConsentChanged {
214    pub entity_kind: ConsentEntityKind,
215    pub entity: String,
216    pub state: ConsentState,
217}
218#[derive(Clone, Debug, PartialEq, Eq)]
219pub struct HmacKeysUpdated;
220#[derive(Clone, Debug, PartialEq, Eq)]
221pub struct IdentityRegistered {
222    pub inbox_id: String,
223    pub installation_key: Vec<u8>,
224}
225#[derive(Clone, Debug, PartialEq, Eq)]
226pub struct InstallationRef {
227    pub installation_key: Vec<u8>,
228}
229#[derive(Clone, Debug, PartialEq, Eq)]
230pub struct InstallationRevoked {
231    pub installation_key: Vec<u8>,
232    pub is_this_installation: bool,
233}
234#[derive(Clone, Debug, PartialEq, Eq)]
235pub struct ClientRejectedByServer {
236    pub cause: RejectionCause,
237    pub min_libxmtp_version: Option<String>,
238}
239#[derive(Clone, Debug, PartialEq, Eq)]
240pub struct LockoutChanged {
241    pub change: LockoutChange,
242}
243#[derive(Clone, Debug, PartialEq, Eq)]
244pub struct NotificationsFailed {
245    pub cause: String,
246}
247#[derive(Clone, Debug, PartialEq, Eq)]
248pub struct ArchiveRestored {
249    pub complete: bool,
250}
251#[derive(Clone, Copy, Debug, PartialEq, Eq)]
252pub enum ConnectionState {
253    Connecting,
254    Connected,
255    Reconnecting,
256    Failed,
257    Closed,
258}
259#[derive(Clone, Debug, PartialEq, Eq)]
260pub struct ConnectionStateChanged {
261    pub previous: ConnectionState,
262    pub current: ConnectionState,
263}
264#[derive(Clone, PartialEq, Eq)]
265pub struct AttachmentRef {
266    pub attachment_key: String,
267    pub url: String,
268    pub content_digest: String,
269}
270#[derive(Clone, PartialEq, Eq)]
271pub struct AttachmentFailed {
272    pub attachment_key: String,
273    pub url: String,
274    pub content_digest: String,
275    pub cause: String,
276}
277
278impl std::fmt::Debug for AttachmentRef {
279    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
280        f.debug_struct("AttachmentRef")
281            .field("attachment_key", &self.attachment_key)
282            .field("url", &"<redacted>")
283            .field("content_digest", &self.content_digest)
284            .finish()
285    }
286}
287
288impl std::fmt::Debug for AttachmentFailed {
289    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
290        f.debug_struct("AttachmentFailed")
291            .field("attachment_key", &self.attachment_key)
292            .field("url", &"<redacted>")
293            .field("content_digest", &self.content_digest)
294            .field("cause", &self.cause)
295            .finish()
296    }
297}
298
299/// The display handle of an inbox changed.
300#[derive(Clone, Debug, PartialEq, Eq)]
301pub struct HandleChanged {
302    /// The inbox whose display handle changed.
303    pub inbox_id: String,
304    /// The display handle of the stored association state.
305    pub handle: String,
306}
307
308#[derive(Clone, Debug, PartialEq, Eq)]
309pub struct Lagged {
310    pub discarded: u64,
311}
312
313#[derive(Clone, Debug, PartialEq, Eq)]
314pub enum ClientEvent {
315    ConversationJoined(ConversationJoined),
316    ConversationRemoved(ConversationRemoved),
317    ConversationMembershipChanged(MembershipChanged),
318    ConversationMetadataChanged(MetadataChanged),
319    ConversationPaused(ConversationPaused),
320    MessageReceived(MessageReceived),
321    MessageStatusChanged(MessageStatusChanged),
322    MessageDeleted(MessageDeleted),
323    MessageExpired(MessageRef),
324    ConsentChanged(ConsentChanged),
325    HmacKeysUpdated(HmacKeysUpdated),
326    IdentityRegistered(IdentityRegistered),
327    IdentityOwnInstallationAdded(InstallationRef),
328    IdentityOwnInstallationRevoked(InstallationRevoked),
329    ClientRejectedByServer(ClientRejectedByServer),
330    ClientLockoutChanged(LockoutChanged),
331    ConversationForkDetected(GroupRef),
332    NotificationsFailed(NotificationsFailed),
333    ArchiveRestored(ArchiveRestored),
334    ConnectionStateChanged(ConnectionStateChanged),
335    AttachmentUploadStarted(AttachmentRef),
336    AttachmentUploadCompleted(AttachmentRef),
337    AttachmentUploadFailed(AttachmentFailed),
338    AttachmentDownloadStarted(AttachmentRef),
339    AttachmentDownloadCompleted(AttachmentRef),
340    AttachmentDownloadFailed(AttachmentFailed),
341    AttachmentDeleted(AttachmentRef),
342    HandleChanged(HandleChanged),
343    Lagged(Lagged),
344}
345
346impl ClientEvent {
347    pub const fn kind(&self) -> EventKind {
348        match self {
349            Self::ConversationJoined(_) => EventKind::ConversationJoined,
350            Self::ConversationRemoved(_) => EventKind::ConversationRemoved,
351            Self::ConversationMembershipChanged(_) => EventKind::ConversationMembershipChanged,
352            Self::ConversationMetadataChanged(_) => EventKind::ConversationMetadataChanged,
353            Self::ConversationPaused(_) => EventKind::ConversationPaused,
354            Self::MessageReceived(_) => EventKind::MessageReceived,
355            Self::MessageStatusChanged(_) => EventKind::MessageStatusChanged,
356            Self::MessageDeleted(_) => EventKind::MessageDeleted,
357            Self::MessageExpired(_) => EventKind::MessageExpired,
358            Self::ConsentChanged(_) => EventKind::ConsentChanged,
359            Self::HmacKeysUpdated(_) => EventKind::HmacKeysUpdated,
360            Self::IdentityRegistered(_) => EventKind::IdentityRegistered,
361            Self::IdentityOwnInstallationAdded(_) => EventKind::IdentityOwnInstallationAdded,
362            Self::IdentityOwnInstallationRevoked(_) => EventKind::IdentityOwnInstallationRevoked,
363            Self::ClientRejectedByServer(_) => EventKind::ClientRejectedByServer,
364            Self::ClientLockoutChanged(_) => EventKind::ClientLockoutChanged,
365            Self::ConversationForkDetected(_) => EventKind::ConversationForkDetected,
366            Self::NotificationsFailed(_) => EventKind::NotificationsFailed,
367            Self::ArchiveRestored(_) => EventKind::ArchiveRestored,
368            Self::ConnectionStateChanged(_) => EventKind::ConnectionStateChanged,
369            Self::AttachmentUploadStarted(_) => EventKind::AttachmentUploadStarted,
370            Self::AttachmentUploadCompleted(_) => EventKind::AttachmentUploadCompleted,
371            Self::AttachmentUploadFailed(_) => EventKind::AttachmentUploadFailed,
372            Self::AttachmentDownloadStarted(_) => EventKind::AttachmentDownloadStarted,
373            Self::AttachmentDownloadCompleted(_) => EventKind::AttachmentDownloadCompleted,
374            Self::AttachmentDownloadFailed(_) => EventKind::AttachmentDownloadFailed,
375            Self::AttachmentDeleted(_) => EventKind::AttachmentDeleted,
376            Self::HandleChanged(_) => EventKind::HandleChanged,
377            Self::Lagged(_) => EventKind::Lagged,
378        }
379    }
380
381    pub fn group_id(&self) -> Option<&[u8]> {
382        match self {
383            Self::ConversationJoined(v) => Some(&v.group_id),
384            Self::ConversationRemoved(v) => Some(&v.group_id),
385            Self::ConversationMembershipChanged(v) => Some(&v.group_id),
386            Self::ConversationMetadataChanged(v) => Some(&v.group_id),
387            Self::ConversationPaused(v) => Some(&v.group_id),
388            Self::MessageReceived(v) => Some(&v.group_id),
389            Self::MessageStatusChanged(v) => Some(&v.group_id),
390            Self::MessageDeleted(v) => Some(&v.group_id),
391            Self::MessageExpired(v) => Some(&v.group_id),
392            Self::ConversationForkDetected(v) => Some(&v.group_id),
393            _ => None,
394        }
395    }
396}