Skip to main content

xmtp_sys/
bindings.rs

1/* automatically generated by rust-bindgen 0.72.1 */
2
3#[repr(i32)]
4#[non_exhaustive]
5#[doc = " Conversation type."]
6#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
7pub enum XmtpFfiConversationType {
8    XMTP_FFI_CONVERSATION_TYPE_DM = 0,
9    XMTP_FFI_CONVERSATION_TYPE_GROUP = 1,
10    XMTP_FFI_CONVERSATION_TYPE_SYNC = 2,
11    XMTP_FFI_CONVERSATION_TYPE_ONESHOT = 3,
12}
13#[repr(i32)]
14#[non_exhaustive]
15#[doc = " Group permissions preset."]
16#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
17pub enum XmtpFfiGroupPermissionsPreset {
18    XMTP_FFI_GROUP_PERMISSIONS_PRESET_ALL_MEMBERS = 0,
19    XMTP_FFI_GROUP_PERMISSIONS_PRESET_ADMIN_ONLY = 1,
20    XMTP_FFI_GROUP_PERMISSIONS_PRESET_CUSTOM = 2,
21}
22#[repr(i32)]
23#[non_exhaustive]
24#[doc = " Permission policy value."]
25#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
26pub enum XmtpFfiPermissionPolicy {
27    XMTP_FFI_PERMISSION_POLICY_ALLOW = 0,
28    XMTP_FFI_PERMISSION_POLICY_DENY = 1,
29    XMTP_FFI_PERMISSION_POLICY_ADMIN = 2,
30    XMTP_FFI_PERMISSION_POLICY_SUPER_ADMIN = 3,
31    XMTP_FFI_PERMISSION_POLICY_DOES_NOT_EXIST = 4,
32    XMTP_FFI_PERMISSION_POLICY_OTHER = 5,
33}
34#[repr(i32)]
35#[non_exhaustive]
36#[doc = " Message kind."]
37#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
38pub enum XmtpFfiMessageKind {
39    XMTP_FFI_MESSAGE_KIND_APPLICATION = 0,
40    XMTP_FFI_MESSAGE_KIND_MEMBERSHIP_CHANGE = 1,
41}
42#[repr(i32)]
43#[non_exhaustive]
44#[doc = " Message delivery status."]
45#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
46pub enum XmtpFfiDeliveryStatus {
47    XMTP_FFI_DELIVERY_STATUS_UNPUBLISHED = 0,
48    XMTP_FFI_DELIVERY_STATUS_PUBLISHED = 1,
49    XMTP_FFI_DELIVERY_STATUS_FAILED = 2,
50}
51#[repr(i32)]
52#[non_exhaustive]
53#[doc = " Consent entity type."]
54#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
55pub enum XmtpFfiConsentEntityType {
56    XMTP_FFI_CONSENT_ENTITY_TYPE_GROUP_ID = 0,
57    XMTP_FFI_CONSENT_ENTITY_TYPE_INBOX_ID = 1,
58}
59#[repr(i32)]
60#[non_exhaustive]
61#[doc = " Consent state for an entity."]
62#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
63pub enum XmtpFfiConsentState {
64    XMTP_FFI_CONSENT_STATE_UNKNOWN = 0,
65    XMTP_FFI_CONSENT_STATE_ALLOWED = 1,
66    XMTP_FFI_CONSENT_STATE_DENIED = 2,
67}
68#[repr(i32)]
69#[non_exhaustive]
70#[doc = " Preference update kind."]
71#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
72pub enum XmtpFfiPreferenceUpdateKind {
73    XMTP_FFI_PREFERENCE_UPDATE_KIND_CONSENT = 0,
74    XMTP_FFI_PREFERENCE_UPDATE_KIND_HMAC_KEY = 1,
75}
76#[repr(C)]
77#[derive(Debug, Copy, Clone)]
78pub struct XmtpFfiAuthHandle {
79    _unused: [u8; 0],
80}
81#[repr(C)]
82#[derive(Debug, Copy, Clone)]
83pub struct XmtpFfiAvailableArchiveList {
84    _unused: [u8; 0],
85}
86#[repr(C)]
87#[derive(Debug, Copy, Clone)]
88pub struct XmtpFfiClient {
89    _unused: [u8; 0],
90}
91#[repr(C)]
92#[derive(Debug, Copy, Clone)]
93pub struct XmtpFfiConversation {
94    _unused: [u8; 0],
95}
96#[repr(C)]
97#[derive(Debug, Copy, Clone)]
98pub struct XmtpFfiConversationList {
99    _unused: [u8; 0],
100}
101#[repr(C)]
102#[derive(Debug, Copy, Clone)]
103pub struct XmtpFfiEnrichedMessageList {
104    _unused: [u8; 0],
105}
106#[repr(C)]
107#[derive(Debug, Copy, Clone)]
108pub struct XmtpFfiGroupMemberList {
109    _unused: [u8; 0],
110}
111#[repr(C)]
112#[derive(Debug, Copy, Clone)]
113pub struct XmtpFfiHmacKeyMap {
114    _unused: [u8; 0],
115}
116#[repr(C)]
117#[derive(Debug, Copy, Clone)]
118pub struct XmtpFfiInboxStateList {
119    _unused: [u8; 0],
120}
121#[repr(C)]
122#[derive(Debug, Copy, Clone)]
123pub struct XmtpFfiInboxUpdateCountList {
124    _unused: [u8; 0],
125}
126#[repr(C)]
127#[derive(Debug, Copy, Clone)]
128pub struct XmtpFfiKeyPackageStatusList {
129    _unused: [u8; 0],
130}
131#[repr(C)]
132#[derive(Debug, Copy, Clone)]
133pub struct XmtpFfiLastReadTimeList {
134    _unused: [u8; 0],
135}
136#[repr(C)]
137#[derive(Debug, Copy, Clone)]
138pub struct XmtpFfiMessage {
139    _unused: [u8; 0],
140}
141#[repr(C)]
142#[derive(Debug, Copy, Clone)]
143pub struct XmtpFfiMessageList {
144    _unused: [u8; 0],
145}
146#[repr(C)]
147#[derive(Debug, Copy, Clone)]
148pub struct XmtpFfiSignatureRequest {
149    _unused: [u8; 0],
150}
151#[repr(C)]
152#[derive(Debug, Copy, Clone)]
153pub struct XmtpFfiStreamHandle {
154    _unused: [u8; 0],
155}
156#[doc = " Options for creating a client. All string fields are borrowed (not freed by this library)."]
157#[repr(C)]
158#[derive(Debug, Copy, Clone, PartialEq, Eq)]
159pub struct XmtpFfiClientOptions {
160    #[doc = " gRPC v3 host URL (required)."]
161    pub host: *const ::core::ffi::c_char,
162    #[doc = " Gateway host URL for decentralized API (nullable, enables d14n if set)."]
163    pub gateway_host: *const ::core::ffi::c_char,
164    #[doc = " Whether the connection is TLS-secured."]
165    pub is_secure: i32,
166    #[doc = " Path to the SQLite database file. Null = ephemeral."]
167    pub db_path: *const ::core::ffi::c_char,
168    #[doc = " 32-byte encryption key for the database. Null = unencrypted."]
169    pub encryption_key: *const u8,
170    #[doc = " Inbox ID (required)."]
171    pub inbox_id: *const ::core::ffi::c_char,
172    #[doc = " Account identifier string (required)."]
173    pub account_identifier: *const ::core::ffi::c_char,
174    #[doc = " Identifier kind: 0 = Ethereum, 1 = Passkey."]
175    pub identifier_kind: i32,
176    #[doc = " Nonce for identity strategy (default 1 if 0)."]
177    pub nonce: u64,
178    #[doc = " Optional auth handle for gateway authentication. Null = no auth."]
179    pub auth_handle: *const XmtpFfiAuthHandle,
180    #[doc = " Application version string (nullable)."]
181    pub app_version: *const ::core::ffi::c_char,
182    #[doc = " Device sync worker mode: 0 = Enabled (default), 1 = Disabled."]
183    pub device_sync_worker_mode: i32,
184    #[doc = " Allow offline mode. 0 = no (default), 1 = yes."]
185    pub allow_offline: i32,
186    #[doc = " Client mode: 0 = Default, 1 = Notification (read-only)."]
187    pub client_mode: i32,
188    #[doc = " Maximum database connection pool size. 0 = use default."]
189    pub max_db_pool_size: u32,
190    #[doc = " Minimum database connection pool size. 0 = use default."]
191    pub min_db_pool_size: u32,
192}
193#[allow(clippy::unnecessary_operation, clippy::identity_op)]
194const _: () = {
195    ["Size of XmtpFfiClientOptions"][::core::mem::size_of::<XmtpFfiClientOptions>() - 112usize];
196    ["Alignment of XmtpFfiClientOptions"][::core::mem::align_of::<XmtpFfiClientOptions>() - 8usize];
197    ["Offset of field: XmtpFfiClientOptions::host"]
198        [::core::mem::offset_of!(XmtpFfiClientOptions, host) - 0usize];
199    ["Offset of field: XmtpFfiClientOptions::gateway_host"]
200        [::core::mem::offset_of!(XmtpFfiClientOptions, gateway_host) - 8usize];
201    ["Offset of field: XmtpFfiClientOptions::is_secure"]
202        [::core::mem::offset_of!(XmtpFfiClientOptions, is_secure) - 16usize];
203    ["Offset of field: XmtpFfiClientOptions::db_path"]
204        [::core::mem::offset_of!(XmtpFfiClientOptions, db_path) - 24usize];
205    ["Offset of field: XmtpFfiClientOptions::encryption_key"]
206        [::core::mem::offset_of!(XmtpFfiClientOptions, encryption_key) - 32usize];
207    ["Offset of field: XmtpFfiClientOptions::inbox_id"]
208        [::core::mem::offset_of!(XmtpFfiClientOptions, inbox_id) - 40usize];
209    ["Offset of field: XmtpFfiClientOptions::account_identifier"]
210        [::core::mem::offset_of!(XmtpFfiClientOptions, account_identifier) - 48usize];
211    ["Offset of field: XmtpFfiClientOptions::identifier_kind"]
212        [::core::mem::offset_of!(XmtpFfiClientOptions, identifier_kind) - 56usize];
213    ["Offset of field: XmtpFfiClientOptions::nonce"]
214        [::core::mem::offset_of!(XmtpFfiClientOptions, nonce) - 64usize];
215    ["Offset of field: XmtpFfiClientOptions::auth_handle"]
216        [::core::mem::offset_of!(XmtpFfiClientOptions, auth_handle) - 72usize];
217    ["Offset of field: XmtpFfiClientOptions::app_version"]
218        [::core::mem::offset_of!(XmtpFfiClientOptions, app_version) - 80usize];
219    ["Offset of field: XmtpFfiClientOptions::device_sync_worker_mode"]
220        [::core::mem::offset_of!(XmtpFfiClientOptions, device_sync_worker_mode) - 88usize];
221    ["Offset of field: XmtpFfiClientOptions::allow_offline"]
222        [::core::mem::offset_of!(XmtpFfiClientOptions, allow_offline) - 92usize];
223    ["Offset of field: XmtpFfiClientOptions::client_mode"]
224        [::core::mem::offset_of!(XmtpFfiClientOptions, client_mode) - 96usize];
225    ["Offset of field: XmtpFfiClientOptions::max_db_pool_size"]
226        [::core::mem::offset_of!(XmtpFfiClientOptions, max_db_pool_size) - 100usize];
227    ["Offset of field: XmtpFfiClientOptions::min_db_pool_size"]
228        [::core::mem::offset_of!(XmtpFfiClientOptions, min_db_pool_size) - 104usize];
229};
230impl Default for XmtpFfiClientOptions {
231    fn default() -> Self {
232        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
233        unsafe {
234            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
235            s.assume_init()
236        }
237    }
238}
239#[doc = " MLS API call statistics (request counts)."]
240#[repr(C)]
241#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
242pub struct XmtpFfiApiStats {
243    pub upload_key_package: i64,
244    pub fetch_key_package: i64,
245    pub send_group_messages: i64,
246    pub send_welcome_messages: i64,
247    pub query_group_messages: i64,
248    pub query_welcome_messages: i64,
249    pub subscribe_messages: i64,
250    pub subscribe_welcomes: i64,
251    pub publish_commit_log: i64,
252    pub query_commit_log: i64,
253    pub get_newest_group_message: i64,
254}
255#[allow(clippy::unnecessary_operation, clippy::identity_op)]
256const _: () = {
257    ["Size of XmtpFfiApiStats"][::core::mem::size_of::<XmtpFfiApiStats>() - 88usize];
258    ["Alignment of XmtpFfiApiStats"][::core::mem::align_of::<XmtpFfiApiStats>() - 8usize];
259    ["Offset of field: XmtpFfiApiStats::upload_key_package"]
260        [::core::mem::offset_of!(XmtpFfiApiStats, upload_key_package) - 0usize];
261    ["Offset of field: XmtpFfiApiStats::fetch_key_package"]
262        [::core::mem::offset_of!(XmtpFfiApiStats, fetch_key_package) - 8usize];
263    ["Offset of field: XmtpFfiApiStats::send_group_messages"]
264        [::core::mem::offset_of!(XmtpFfiApiStats, send_group_messages) - 16usize];
265    ["Offset of field: XmtpFfiApiStats::send_welcome_messages"]
266        [::core::mem::offset_of!(XmtpFfiApiStats, send_welcome_messages) - 24usize];
267    ["Offset of field: XmtpFfiApiStats::query_group_messages"]
268        [::core::mem::offset_of!(XmtpFfiApiStats, query_group_messages) - 32usize];
269    ["Offset of field: XmtpFfiApiStats::query_welcome_messages"]
270        [::core::mem::offset_of!(XmtpFfiApiStats, query_welcome_messages) - 40usize];
271    ["Offset of field: XmtpFfiApiStats::subscribe_messages"]
272        [::core::mem::offset_of!(XmtpFfiApiStats, subscribe_messages) - 48usize];
273    ["Offset of field: XmtpFfiApiStats::subscribe_welcomes"]
274        [::core::mem::offset_of!(XmtpFfiApiStats, subscribe_welcomes) - 56usize];
275    ["Offset of field: XmtpFfiApiStats::publish_commit_log"]
276        [::core::mem::offset_of!(XmtpFfiApiStats, publish_commit_log) - 64usize];
277    ["Offset of field: XmtpFfiApiStats::query_commit_log"]
278        [::core::mem::offset_of!(XmtpFfiApiStats, query_commit_log) - 72usize];
279    ["Offset of field: XmtpFfiApiStats::get_newest_group_message"]
280        [::core::mem::offset_of!(XmtpFfiApiStats, get_newest_group_message) - 80usize];
281};
282#[doc = " Identity API call statistics (request counts)."]
283#[repr(C)]
284#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
285pub struct XmtpFfiIdentityStats {
286    pub publish_identity_update: i64,
287    pub get_identity_updates_v2: i64,
288    pub get_inbox_ids: i64,
289    pub verify_smart_contract_wallet_signature: i64,
290}
291#[allow(clippy::unnecessary_operation, clippy::identity_op)]
292const _: () = {
293    ["Size of XmtpFfiIdentityStats"][::core::mem::size_of::<XmtpFfiIdentityStats>() - 32usize];
294    ["Alignment of XmtpFfiIdentityStats"][::core::mem::align_of::<XmtpFfiIdentityStats>() - 8usize];
295    ["Offset of field: XmtpFfiIdentityStats::publish_identity_update"]
296        [::core::mem::offset_of!(XmtpFfiIdentityStats, publish_identity_update) - 0usize];
297    ["Offset of field: XmtpFfiIdentityStats::get_identity_updates_v2"]
298        [::core::mem::offset_of!(XmtpFfiIdentityStats, get_identity_updates_v2) - 8usize];
299    ["Offset of field: XmtpFfiIdentityStats::get_inbox_ids"]
300        [::core::mem::offset_of!(XmtpFfiIdentityStats, get_inbox_ids) - 16usize];
301    ["Offset of field: XmtpFfiIdentityStats::verify_smart_contract_wallet_signature"][::core::mem::offset_of!(
302        XmtpFfiIdentityStats,
303        verify_smart_contract_wallet_signature
304    ) - 24usize];
305};
306#[doc = " Inbox update count entry (inbox_id → count)."]
307#[repr(C)]
308#[derive(Debug, Copy, Clone, PartialEq, Eq)]
309pub struct XmtpFfiInboxUpdateCount {
310    pub inbox_id: *mut ::core::ffi::c_char,
311    pub count: u32,
312}
313#[allow(clippy::unnecessary_operation, clippy::identity_op)]
314const _: () = {
315    ["Size of XmtpFfiInboxUpdateCount"]
316        [::core::mem::size_of::<XmtpFfiInboxUpdateCount>() - 16usize];
317    ["Alignment of XmtpFfiInboxUpdateCount"]
318        [::core::mem::align_of::<XmtpFfiInboxUpdateCount>() - 8usize];
319    ["Offset of field: XmtpFfiInboxUpdateCount::inbox_id"]
320        [::core::mem::offset_of!(XmtpFfiInboxUpdateCount, inbox_id) - 0usize];
321    ["Offset of field: XmtpFfiInboxUpdateCount::count"]
322        [::core::mem::offset_of!(XmtpFfiInboxUpdateCount, count) - 8usize];
323};
324impl Default for XmtpFfiInboxUpdateCount {
325    fn default() -> Self {
326        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
327        unsafe {
328            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
329            s.assume_init()
330        }
331    }
332}
333#[doc = " Key package status for an installation."]
334#[repr(C)]
335#[derive(Debug, Copy, Clone, PartialEq, Eq)]
336pub struct XmtpFfiKeyPackageStatus {
337    #[doc = " Installation ID as hex string (owned)."]
338    pub installation_id: *mut ::core::ffi::c_char,
339    #[doc = " 1 if valid, 0 if validation error."]
340    pub valid: i32,
341    #[doc = " not_before timestamp (0 if unavailable)."]
342    pub not_before: u64,
343    #[doc = " not_after timestamp (0 if unavailable)."]
344    pub not_after: u64,
345    #[doc = " Validation error message (null if no error, owned)."]
346    pub validation_error: *mut ::core::ffi::c_char,
347}
348#[allow(clippy::unnecessary_operation, clippy::identity_op)]
349const _: () = {
350    ["Size of XmtpFfiKeyPackageStatus"]
351        [::core::mem::size_of::<XmtpFfiKeyPackageStatus>() - 40usize];
352    ["Alignment of XmtpFfiKeyPackageStatus"]
353        [::core::mem::align_of::<XmtpFfiKeyPackageStatus>() - 8usize];
354    ["Offset of field: XmtpFfiKeyPackageStatus::installation_id"]
355        [::core::mem::offset_of!(XmtpFfiKeyPackageStatus, installation_id) - 0usize];
356    ["Offset of field: XmtpFfiKeyPackageStatus::valid"]
357        [::core::mem::offset_of!(XmtpFfiKeyPackageStatus, valid) - 8usize];
358    ["Offset of field: XmtpFfiKeyPackageStatus::not_before"]
359        [::core::mem::offset_of!(XmtpFfiKeyPackageStatus, not_before) - 16usize];
360    ["Offset of field: XmtpFfiKeyPackageStatus::not_after"]
361        [::core::mem::offset_of!(XmtpFfiKeyPackageStatus, not_after) - 24usize];
362    ["Offset of field: XmtpFfiKeyPackageStatus::validation_error"]
363        [::core::mem::offset_of!(XmtpFfiKeyPackageStatus, validation_error) - 32usize];
364};
365impl Default for XmtpFfiKeyPackageStatus {
366    fn default() -> Self {
367        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
368        unsafe {
369            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
370            s.assume_init()
371        }
372    }
373}
374#[doc = " Options for sending a message."]
375#[repr(C)]
376#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
377pub struct XmtpFfiSendOpts {
378    #[doc = " Whether to send a push notification. 1 = yes (default), 0 = no."]
379    pub should_push: i32,
380}
381#[allow(clippy::unnecessary_operation, clippy::identity_op)]
382const _: () = {
383    ["Size of XmtpFfiSendOpts"][::core::mem::size_of::<XmtpFfiSendOpts>() - 4usize];
384    ["Alignment of XmtpFfiSendOpts"][::core::mem::align_of::<XmtpFfiSendOpts>() - 4usize];
385    ["Offset of field: XmtpFfiSendOpts::should_push"]
386        [::core::mem::offset_of!(XmtpFfiSendOpts, should_push) - 0usize];
387};
388#[doc = " Options for listing messages."]
389#[repr(C)]
390#[derive(Debug, Copy, Clone, PartialEq, Eq)]
391pub struct XmtpFfiListMessagesOptions {
392    #[doc = " Only messages sent after this timestamp (ns). 0 = no filter."]
393    pub sent_after_ns: i64,
394    #[doc = " Only messages sent before this timestamp (ns). 0 = no filter."]
395    pub sent_before_ns: i64,
396    #[doc = " Only messages inserted after this timestamp (ns). 0 = no filter."]
397    pub inserted_after_ns: i64,
398    #[doc = " Only messages inserted before this timestamp (ns). 0 = no filter."]
399    pub inserted_before_ns: i64,
400    #[doc = " Maximum number of messages. 0 = no limit."]
401    pub limit: i64,
402    #[doc = " Filter by delivery status: -1 = all, 0 = Unpublished, 1 = Published, 2 = Failed."]
403    pub delivery_status: i32,
404    #[doc = " Filter by message kind: -1 = all, 0 = Application, 1 = MembershipChange."]
405    pub kind: i32,
406    #[doc = " Sort direction: 0 = Ascending (default), 1 = Descending."]
407    pub direction: i32,
408    #[doc = " Sort by: 0 = SentAt (default), 1 = InsertedAt."]
409    pub sort_by: i32,
410    #[doc = " Include only these content types (nullable). Each element is a ContentType i32 value."]
411    pub content_types: *const i32,
412    #[doc = " Number of elements in `content_types`. 0 = no filter."]
413    pub content_types_count: i32,
414    #[doc = " Exclude these content types (nullable). Each element is a ContentType i32 value."]
415    pub exclude_content_types: *const i32,
416    #[doc = " Number of elements in `exclude_content_types`. 0 = no filter."]
417    pub exclude_content_types_count: i32,
418    #[doc = " Exclude messages from these sender inbox IDs (nullable C string array)."]
419    pub exclude_sender_inbox_ids: *const *const ::core::ffi::c_char,
420    #[doc = " Number of elements in `exclude_sender_inbox_ids`. 0 = no filter."]
421    pub exclude_sender_inbox_ids_count: i32,
422    #[doc = " Whether to exclude disappearing messages. 0 = include (default), 1 = exclude."]
423    pub exclude_disappearing: i32,
424}
425#[allow(clippy::unnecessary_operation, clippy::identity_op)]
426const _: () = {
427    ["Size of XmtpFfiListMessagesOptions"]
428        [::core::mem::size_of::<XmtpFfiListMessagesOptions>() - 104usize];
429    ["Alignment of XmtpFfiListMessagesOptions"]
430        [::core::mem::align_of::<XmtpFfiListMessagesOptions>() - 8usize];
431    ["Offset of field: XmtpFfiListMessagesOptions::sent_after_ns"]
432        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, sent_after_ns) - 0usize];
433    ["Offset of field: XmtpFfiListMessagesOptions::sent_before_ns"]
434        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, sent_before_ns) - 8usize];
435    ["Offset of field: XmtpFfiListMessagesOptions::inserted_after_ns"]
436        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, inserted_after_ns) - 16usize];
437    ["Offset of field: XmtpFfiListMessagesOptions::inserted_before_ns"]
438        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, inserted_before_ns) - 24usize];
439    ["Offset of field: XmtpFfiListMessagesOptions::limit"]
440        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, limit) - 32usize];
441    ["Offset of field: XmtpFfiListMessagesOptions::delivery_status"]
442        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, delivery_status) - 40usize];
443    ["Offset of field: XmtpFfiListMessagesOptions::kind"]
444        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, kind) - 44usize];
445    ["Offset of field: XmtpFfiListMessagesOptions::direction"]
446        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, direction) - 48usize];
447    ["Offset of field: XmtpFfiListMessagesOptions::sort_by"]
448        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, sort_by) - 52usize];
449    ["Offset of field: XmtpFfiListMessagesOptions::content_types"]
450        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, content_types) - 56usize];
451    ["Offset of field: XmtpFfiListMessagesOptions::content_types_count"]
452        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, content_types_count) - 64usize];
453    ["Offset of field: XmtpFfiListMessagesOptions::exclude_content_types"]
454        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, exclude_content_types) - 72usize];
455    ["Offset of field: XmtpFfiListMessagesOptions::exclude_content_types_count"][::core::mem::offset_of!(
456        XmtpFfiListMessagesOptions,
457        exclude_content_types_count
458    ) - 80usize];
459    ["Offset of field: XmtpFfiListMessagesOptions::exclude_sender_inbox_ids"]
460        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, exclude_sender_inbox_ids) - 88usize];
461    ["Offset of field: XmtpFfiListMessagesOptions::exclude_sender_inbox_ids_count"][::core::mem::offset_of!(
462        XmtpFfiListMessagesOptions,
463        exclude_sender_inbox_ids_count
464    ) - 96usize];
465    ["Offset of field: XmtpFfiListMessagesOptions::exclude_disappearing"]
466        [::core::mem::offset_of!(XmtpFfiListMessagesOptions, exclude_disappearing) - 100usize];
467};
468impl Default for XmtpFfiListMessagesOptions {
469    fn default() -> Self {
470        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
471        unsafe {
472            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
473            s.assume_init()
474        }
475    }
476}
477#[doc = " Options for message disappearing settings."]
478#[repr(C)]
479#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
480pub struct XmtpFfiDisappearingSettings {
481    #[doc = " Timestamp (ns) from which messages start disappearing."]
482    pub from_ns: i64,
483    #[doc = " Duration (ns) after which messages disappear."]
484    pub in_ns: i64,
485}
486#[allow(clippy::unnecessary_operation, clippy::identity_op)]
487const _: () = {
488    ["Size of XmtpFfiDisappearingSettings"]
489        [::core::mem::size_of::<XmtpFfiDisappearingSettings>() - 16usize];
490    ["Alignment of XmtpFfiDisappearingSettings"]
491        [::core::mem::align_of::<XmtpFfiDisappearingSettings>() - 8usize];
492    ["Offset of field: XmtpFfiDisappearingSettings::from_ns"]
493        [::core::mem::offset_of!(XmtpFfiDisappearingSettings, from_ns) - 0usize];
494    ["Offset of field: XmtpFfiDisappearingSettings::in_ns"]
495        [::core::mem::offset_of!(XmtpFfiDisappearingSettings, in_ns) - 8usize];
496};
497#[doc = " A single cursor entry (originator + sequence)."]
498#[repr(C)]
499#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
500pub struct XmtpFfiCursor {
501    pub originator_id: u32,
502    pub sequence_id: u64,
503}
504#[allow(clippy::unnecessary_operation, clippy::identity_op)]
505const _: () = {
506    ["Size of XmtpFfiCursor"][::core::mem::size_of::<XmtpFfiCursor>() - 16usize];
507    ["Alignment of XmtpFfiCursor"][::core::mem::align_of::<XmtpFfiCursor>() - 8usize];
508    ["Offset of field: XmtpFfiCursor::originator_id"]
509        [::core::mem::offset_of!(XmtpFfiCursor, originator_id) - 0usize];
510    ["Offset of field: XmtpFfiCursor::sequence_id"]
511        [::core::mem::offset_of!(XmtpFfiCursor, sequence_id) - 8usize];
512};
513#[doc = " Conversation debug info (epoch, fork status, commit logs, cursors)."]
514#[repr(C)]
515#[derive(Debug, Copy, Clone, PartialEq, Eq)]
516pub struct XmtpFfiConversationDebugInfo {
517    pub epoch: u64,
518    pub maybe_forked: i32,
519    pub fork_details: *mut ::core::ffi::c_char,
520    #[doc = " -1 = unknown, 0 = no, 1 = yes"]
521    pub is_commit_log_forked: i32,
522    pub local_commit_log: *mut ::core::ffi::c_char,
523    pub remote_commit_log: *mut ::core::ffi::c_char,
524    #[doc = " Heap-allocated cursor array. Free with the debug_info_free function."]
525    pub cursors: *mut XmtpFfiCursor,
526    pub cursors_count: i32,
527}
528#[allow(clippy::unnecessary_operation, clippy::identity_op)]
529const _: () = {
530    ["Size of XmtpFfiConversationDebugInfo"]
531        [::core::mem::size_of::<XmtpFfiConversationDebugInfo>() - 64usize];
532    ["Alignment of XmtpFfiConversationDebugInfo"]
533        [::core::mem::align_of::<XmtpFfiConversationDebugInfo>() - 8usize];
534    ["Offset of field: XmtpFfiConversationDebugInfo::epoch"]
535        [::core::mem::offset_of!(XmtpFfiConversationDebugInfo, epoch) - 0usize];
536    ["Offset of field: XmtpFfiConversationDebugInfo::maybe_forked"]
537        [::core::mem::offset_of!(XmtpFfiConversationDebugInfo, maybe_forked) - 8usize];
538    ["Offset of field: XmtpFfiConversationDebugInfo::fork_details"]
539        [::core::mem::offset_of!(XmtpFfiConversationDebugInfo, fork_details) - 16usize];
540    ["Offset of field: XmtpFfiConversationDebugInfo::is_commit_log_forked"]
541        [::core::mem::offset_of!(XmtpFfiConversationDebugInfo, is_commit_log_forked) - 24usize];
542    ["Offset of field: XmtpFfiConversationDebugInfo::local_commit_log"]
543        [::core::mem::offset_of!(XmtpFfiConversationDebugInfo, local_commit_log) - 32usize];
544    ["Offset of field: XmtpFfiConversationDebugInfo::remote_commit_log"]
545        [::core::mem::offset_of!(XmtpFfiConversationDebugInfo, remote_commit_log) - 40usize];
546    ["Offset of field: XmtpFfiConversationDebugInfo::cursors"]
547        [::core::mem::offset_of!(XmtpFfiConversationDebugInfo, cursors) - 48usize];
548    ["Offset of field: XmtpFfiConversationDebugInfo::cursors_count"]
549        [::core::mem::offset_of!(XmtpFfiConversationDebugInfo, cursors_count) - 56usize];
550};
551impl Default for XmtpFfiConversationDebugInfo {
552    fn default() -> Self {
553        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
554        unsafe {
555            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
556            s.assume_init()
557        }
558    }
559}
560#[doc = " A single HMAC key (42-byte key + epoch)."]
561#[repr(C)]
562#[derive(Debug, Copy, Clone, PartialEq, Eq)]
563pub struct XmtpFfiHmacKey {
564    pub key: *mut u8,
565    pub key_len: i32,
566    pub epoch: i64,
567}
568#[allow(clippy::unnecessary_operation, clippy::identity_op)]
569const _: () = {
570    ["Size of XmtpFfiHmacKey"][::core::mem::size_of::<XmtpFfiHmacKey>() - 24usize];
571    ["Alignment of XmtpFfiHmacKey"][::core::mem::align_of::<XmtpFfiHmacKey>() - 8usize];
572    ["Offset of field: XmtpFfiHmacKey::key"][::core::mem::offset_of!(XmtpFfiHmacKey, key) - 0usize];
573    ["Offset of field: XmtpFfiHmacKey::key_len"]
574        [::core::mem::offset_of!(XmtpFfiHmacKey, key_len) - 8usize];
575    ["Offset of field: XmtpFfiHmacKey::epoch"]
576        [::core::mem::offset_of!(XmtpFfiHmacKey, epoch) - 16usize];
577};
578impl Default for XmtpFfiHmacKey {
579    fn default() -> Self {
580        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
581        unsafe {
582            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
583            s.assume_init()
584        }
585    }
586}
587#[doc = " Group metadata (creator + conversation type)."]
588#[repr(C)]
589#[derive(Debug, Copy, Clone, PartialEq, Eq)]
590pub struct XmtpFfiGroupMetadata {
591    #[doc = " Creator inbox ID (owned string)."]
592    pub creator_inbox_id: *mut ::core::ffi::c_char,
593    pub conversation_type: XmtpFfiConversationType,
594}
595#[allow(clippy::unnecessary_operation, clippy::identity_op)]
596const _: () = {
597    ["Size of XmtpFfiGroupMetadata"][::core::mem::size_of::<XmtpFfiGroupMetadata>() - 16usize];
598    ["Alignment of XmtpFfiGroupMetadata"][::core::mem::align_of::<XmtpFfiGroupMetadata>() - 8usize];
599    ["Offset of field: XmtpFfiGroupMetadata::creator_inbox_id"]
600        [::core::mem::offset_of!(XmtpFfiGroupMetadata, creator_inbox_id) - 0usize];
601    ["Offset of field: XmtpFfiGroupMetadata::conversation_type"]
602        [::core::mem::offset_of!(XmtpFfiGroupMetadata, conversation_type) - 8usize];
603};
604impl Default for XmtpFfiGroupMetadata {
605    fn default() -> Self {
606        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
607        unsafe {
608            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
609            s.assume_init()
610        }
611    }
612}
613#[doc = " Permission policy set for a conversation."]
614#[repr(C)]
615#[derive(Debug, Copy, Clone, PartialEq, Eq)]
616pub struct XmtpFfiPermissionPolicySet {
617    pub add_member_policy: XmtpFfiPermissionPolicy,
618    pub remove_member_policy: XmtpFfiPermissionPolicy,
619    pub add_admin_policy: XmtpFfiPermissionPolicy,
620    pub remove_admin_policy: XmtpFfiPermissionPolicy,
621    pub update_group_name_policy: XmtpFfiPermissionPolicy,
622    pub update_group_description_policy: XmtpFfiPermissionPolicy,
623    pub update_group_image_url_square_policy: XmtpFfiPermissionPolicy,
624    pub update_message_disappearing_policy: XmtpFfiPermissionPolicy,
625    pub update_app_data_policy: XmtpFfiPermissionPolicy,
626}
627#[allow(clippy::unnecessary_operation, clippy::identity_op)]
628const _: () = {
629    ["Size of XmtpFfiPermissionPolicySet"]
630        [::core::mem::size_of::<XmtpFfiPermissionPolicySet>() - 36usize];
631    ["Alignment of XmtpFfiPermissionPolicySet"]
632        [::core::mem::align_of::<XmtpFfiPermissionPolicySet>() - 4usize];
633    ["Offset of field: XmtpFfiPermissionPolicySet::add_member_policy"]
634        [::core::mem::offset_of!(XmtpFfiPermissionPolicySet, add_member_policy) - 0usize];
635    ["Offset of field: XmtpFfiPermissionPolicySet::remove_member_policy"]
636        [::core::mem::offset_of!(XmtpFfiPermissionPolicySet, remove_member_policy) - 4usize];
637    ["Offset of field: XmtpFfiPermissionPolicySet::add_admin_policy"]
638        [::core::mem::offset_of!(XmtpFfiPermissionPolicySet, add_admin_policy) - 8usize];
639    ["Offset of field: XmtpFfiPermissionPolicySet::remove_admin_policy"]
640        [::core::mem::offset_of!(XmtpFfiPermissionPolicySet, remove_admin_policy) - 12usize];
641    ["Offset of field: XmtpFfiPermissionPolicySet::update_group_name_policy"]
642        [::core::mem::offset_of!(XmtpFfiPermissionPolicySet, update_group_name_policy) - 16usize];
643    ["Offset of field: XmtpFfiPermissionPolicySet::update_group_description_policy"][::core::mem::offset_of!(
644        XmtpFfiPermissionPolicySet,
645        update_group_description_policy
646    ) - 20usize];
647    ["Offset of field: XmtpFfiPermissionPolicySet::update_group_image_url_square_policy"][::core::mem::offset_of!(
648        XmtpFfiPermissionPolicySet,
649        update_group_image_url_square_policy
650    )
651        - 24usize];
652    ["Offset of field: XmtpFfiPermissionPolicySet::update_message_disappearing_policy"][::core::mem::offset_of!(
653        XmtpFfiPermissionPolicySet,
654        update_message_disappearing_policy
655    )
656        - 28usize];
657    ["Offset of field: XmtpFfiPermissionPolicySet::update_app_data_policy"]
658        [::core::mem::offset_of!(XmtpFfiPermissionPolicySet, update_app_data_policy) - 32usize];
659};
660impl Default for XmtpFfiPermissionPolicySet {
661    fn default() -> Self {
662        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
663        unsafe {
664            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
665            s.assume_init()
666        }
667    }
668}
669#[doc = " Group permissions (policy type + policy set)."]
670#[repr(C)]
671#[derive(Debug, Copy, Clone, PartialEq, Eq)]
672pub struct XmtpFfiGroupPermissions {
673    pub policy_type: XmtpFfiGroupPermissionsPreset,
674    pub policy_set: XmtpFfiPermissionPolicySet,
675}
676#[allow(clippy::unnecessary_operation, clippy::identity_op)]
677const _: () = {
678    ["Size of XmtpFfiGroupPermissions"]
679        [::core::mem::size_of::<XmtpFfiGroupPermissions>() - 40usize];
680    ["Alignment of XmtpFfiGroupPermissions"]
681        [::core::mem::align_of::<XmtpFfiGroupPermissions>() - 4usize];
682    ["Offset of field: XmtpFfiGroupPermissions::policy_type"]
683        [::core::mem::offset_of!(XmtpFfiGroupPermissions, policy_type) - 0usize];
684    ["Offset of field: XmtpFfiGroupPermissions::policy_set"]
685        [::core::mem::offset_of!(XmtpFfiGroupPermissions, policy_set) - 4usize];
686};
687impl Default for XmtpFfiGroupPermissions {
688    fn default() -> Self {
689        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
690        unsafe {
691            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
692            s.assume_init()
693        }
694    }
695}
696#[doc = " An enriched (decoded) message exposed to C.\n Contains metadata + the original encoded content bytes for upper-layer decoding."]
697#[repr(C)]
698#[derive(Debug, Copy, Clone, PartialEq, Eq)]
699pub struct XmtpFfiEnrichedMessage {
700    #[doc = " Message ID (hex string, owned)."]
701    pub id: *mut ::core::ffi::c_char,
702    #[doc = " Group ID (hex string, owned)."]
703    pub group_id: *mut ::core::ffi::c_char,
704    #[doc = " Sender inbox ID (owned string)."]
705    pub sender_inbox_id: *mut ::core::ffi::c_char,
706    #[doc = " Sender installation ID (hex string, owned)."]
707    pub sender_installation_id: *mut ::core::ffi::c_char,
708    #[doc = " Sent timestamp in nanoseconds."]
709    pub sent_at_ns: i64,
710    #[doc = " Inserted-into-DB timestamp in nanoseconds."]
711    pub inserted_at_ns: i64,
712    pub kind: XmtpFfiMessageKind,
713    pub delivery_status: XmtpFfiDeliveryStatus,
714    #[doc = " Content type ID string (e.g. \"xmtp.org/text:1.0\", owned)."]
715    pub content_type: *mut ::core::ffi::c_char,
716    #[doc = " Fallback text (nullable, owned)."]
717    pub fallback_text: *mut ::core::ffi::c_char,
718    #[doc = " Expiration timestamp in nanoseconds (0 = no expiration)."]
719    pub expires_at_ns: i64,
720    #[doc = " Number of reactions."]
721    pub num_reactions: i32,
722    #[doc = " Number of replies."]
723    pub num_replies: i32,
724    #[doc = " Raw decrypted content bytes (protobuf-encoded EncodedContent, owned)."]
725    pub content_bytes: *mut u8,
726    #[doc = " Length of `content_bytes`. 0 if unavailable."]
727    pub content_bytes_len: i32,
728}
729#[allow(clippy::unnecessary_operation, clippy::identity_op)]
730const _: () = {
731    ["Size of XmtpFfiEnrichedMessage"][::core::mem::size_of::<XmtpFfiEnrichedMessage>() - 104usize];
732    ["Alignment of XmtpFfiEnrichedMessage"]
733        [::core::mem::align_of::<XmtpFfiEnrichedMessage>() - 8usize];
734    ["Offset of field: XmtpFfiEnrichedMessage::id"]
735        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, id) - 0usize];
736    ["Offset of field: XmtpFfiEnrichedMessage::group_id"]
737        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, group_id) - 8usize];
738    ["Offset of field: XmtpFfiEnrichedMessage::sender_inbox_id"]
739        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, sender_inbox_id) - 16usize];
740    ["Offset of field: XmtpFfiEnrichedMessage::sender_installation_id"]
741        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, sender_installation_id) - 24usize];
742    ["Offset of field: XmtpFfiEnrichedMessage::sent_at_ns"]
743        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, sent_at_ns) - 32usize];
744    ["Offset of field: XmtpFfiEnrichedMessage::inserted_at_ns"]
745        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, inserted_at_ns) - 40usize];
746    ["Offset of field: XmtpFfiEnrichedMessage::kind"]
747        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, kind) - 48usize];
748    ["Offset of field: XmtpFfiEnrichedMessage::delivery_status"]
749        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, delivery_status) - 52usize];
750    ["Offset of field: XmtpFfiEnrichedMessage::content_type"]
751        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, content_type) - 56usize];
752    ["Offset of field: XmtpFfiEnrichedMessage::fallback_text"]
753        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, fallback_text) - 64usize];
754    ["Offset of field: XmtpFfiEnrichedMessage::expires_at_ns"]
755        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, expires_at_ns) - 72usize];
756    ["Offset of field: XmtpFfiEnrichedMessage::num_reactions"]
757        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, num_reactions) - 80usize];
758    ["Offset of field: XmtpFfiEnrichedMessage::num_replies"]
759        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, num_replies) - 84usize];
760    ["Offset of field: XmtpFfiEnrichedMessage::content_bytes"]
761        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, content_bytes) - 88usize];
762    ["Offset of field: XmtpFfiEnrichedMessage::content_bytes_len"]
763        [::core::mem::offset_of!(XmtpFfiEnrichedMessage, content_bytes_len) - 96usize];
764};
765impl Default for XmtpFfiEnrichedMessage {
766    fn default() -> Self {
767        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
768        unsafe {
769            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
770            s.assume_init()
771        }
772    }
773}
774#[doc = " Last-read-time entry (inbox_id → timestamp_ns)."]
775#[repr(C)]
776#[derive(Debug, Copy, Clone, PartialEq, Eq)]
777pub struct XmtpFfiLastReadTimeEntry {
778    pub inbox_id: *mut ::core::ffi::c_char,
779    pub timestamp_ns: i64,
780}
781#[allow(clippy::unnecessary_operation, clippy::identity_op)]
782const _: () = {
783    ["Size of XmtpFfiLastReadTimeEntry"]
784        [::core::mem::size_of::<XmtpFfiLastReadTimeEntry>() - 16usize];
785    ["Alignment of XmtpFfiLastReadTimeEntry"]
786        [::core::mem::align_of::<XmtpFfiLastReadTimeEntry>() - 8usize];
787    ["Offset of field: XmtpFfiLastReadTimeEntry::inbox_id"]
788        [::core::mem::offset_of!(XmtpFfiLastReadTimeEntry, inbox_id) - 0usize];
789    ["Offset of field: XmtpFfiLastReadTimeEntry::timestamp_ns"]
790        [::core::mem::offset_of!(XmtpFfiLastReadTimeEntry, timestamp_ns) - 8usize];
791};
792impl Default for XmtpFfiLastReadTimeEntry {
793    fn default() -> Self {
794        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
795        unsafe {
796            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
797            s.assume_init()
798        }
799    }
800}
801#[doc = " Options for creating a new group conversation."]
802#[repr(C)]
803#[derive(Debug, Copy, Clone, PartialEq, Eq)]
804pub struct XmtpFfiCreateGroupOptions {
805    #[doc = " Permission preset: 0 = AllMembers (default), 1 = AdminOnly."]
806    pub permissions: i32,
807    #[doc = " Group name (nullable)."]
808    pub name: *const ::core::ffi::c_char,
809    #[doc = " Group description (nullable)."]
810    pub description: *const ::core::ffi::c_char,
811    #[doc = " Group image URL (nullable)."]
812    pub image_url: *const ::core::ffi::c_char,
813    #[doc = " Custom app data string (nullable)."]
814    pub app_data: *const ::core::ffi::c_char,
815    #[doc = " Message disappearing \"from\" timestamp in ns. 0 = not set."]
816    pub message_disappear_from_ns: i64,
817    #[doc = " Message disappearing \"in\" duration in ns. 0 = not set."]
818    pub message_disappear_in_ns: i64,
819}
820#[allow(clippy::unnecessary_operation, clippy::identity_op)]
821const _: () = {
822    ["Size of XmtpFfiCreateGroupOptions"]
823        [::core::mem::size_of::<XmtpFfiCreateGroupOptions>() - 56usize];
824    ["Alignment of XmtpFfiCreateGroupOptions"]
825        [::core::mem::align_of::<XmtpFfiCreateGroupOptions>() - 8usize];
826    ["Offset of field: XmtpFfiCreateGroupOptions::permissions"]
827        [::core::mem::offset_of!(XmtpFfiCreateGroupOptions, permissions) - 0usize];
828    ["Offset of field: XmtpFfiCreateGroupOptions::name"]
829        [::core::mem::offset_of!(XmtpFfiCreateGroupOptions, name) - 8usize];
830    ["Offset of field: XmtpFfiCreateGroupOptions::description"]
831        [::core::mem::offset_of!(XmtpFfiCreateGroupOptions, description) - 16usize];
832    ["Offset of field: XmtpFfiCreateGroupOptions::image_url"]
833        [::core::mem::offset_of!(XmtpFfiCreateGroupOptions, image_url) - 24usize];
834    ["Offset of field: XmtpFfiCreateGroupOptions::app_data"]
835        [::core::mem::offset_of!(XmtpFfiCreateGroupOptions, app_data) - 32usize];
836    ["Offset of field: XmtpFfiCreateGroupOptions::message_disappear_from_ns"]
837        [::core::mem::offset_of!(XmtpFfiCreateGroupOptions, message_disappear_from_ns) - 40usize];
838    ["Offset of field: XmtpFfiCreateGroupOptions::message_disappear_in_ns"]
839        [::core::mem::offset_of!(XmtpFfiCreateGroupOptions, message_disappear_in_ns) - 48usize];
840};
841impl Default for XmtpFfiCreateGroupOptions {
842    fn default() -> Self {
843        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
844        unsafe {
845            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
846            s.assume_init()
847        }
848    }
849}
850#[doc = " Options for listing conversations."]
851#[repr(C)]
852#[derive(Debug, Copy, Clone, PartialEq, Eq)]
853pub struct XmtpFfiListConversationsOptions {
854    #[doc = " Conversation type filter: -1 = all, 0 = DM, 1 = Group."]
855    pub conversation_type: i32,
856    #[doc = " Maximum number of conversations to return. 0 = no limit."]
857    pub limit: i64,
858    #[doc = " Only include conversations created after this timestamp (ns). 0 = no filter."]
859    pub created_after_ns: i64,
860    #[doc = " Only include conversations created before this timestamp (ns). 0 = no filter."]
861    pub created_before_ns: i64,
862    #[doc = " Only include conversations with last activity after this timestamp (ns). 0 = no filter."]
863    pub last_activity_after_ns: i64,
864    #[doc = " Only include conversations with last activity before this timestamp (ns). 0 = no filter."]
865    pub last_activity_before_ns: i64,
866    #[doc = " Consent state filter (parallel array with `consent_states_count`).\n Values: 0 = Unknown, 1 = Allowed, 2 = Denied."]
867    pub consent_states: *const i32,
868    #[doc = " Number of consent states in the filter. 0 = no filter."]
869    pub consent_states_count: i32,
870    #[doc = " Order by: 0 = CreatedAt (default), 1 = LastActivity."]
871    pub order_by: i32,
872    #[doc = " Whether to include duplicate DMs. 0 = no (default), 1 = yes."]
873    pub include_duplicate_dms: i32,
874}
875#[allow(clippy::unnecessary_operation, clippy::identity_op)]
876const _: () = {
877    ["Size of XmtpFfiListConversationsOptions"]
878        [::core::mem::size_of::<XmtpFfiListConversationsOptions>() - 72usize];
879    ["Alignment of XmtpFfiListConversationsOptions"]
880        [::core::mem::align_of::<XmtpFfiListConversationsOptions>() - 8usize];
881    ["Offset of field: XmtpFfiListConversationsOptions::conversation_type"]
882        [::core::mem::offset_of!(XmtpFfiListConversationsOptions, conversation_type) - 0usize];
883    ["Offset of field: XmtpFfiListConversationsOptions::limit"]
884        [::core::mem::offset_of!(XmtpFfiListConversationsOptions, limit) - 8usize];
885    ["Offset of field: XmtpFfiListConversationsOptions::created_after_ns"]
886        [::core::mem::offset_of!(XmtpFfiListConversationsOptions, created_after_ns) - 16usize];
887    ["Offset of field: XmtpFfiListConversationsOptions::created_before_ns"]
888        [::core::mem::offset_of!(XmtpFfiListConversationsOptions, created_before_ns) - 24usize];
889    ["Offset of field: XmtpFfiListConversationsOptions::last_activity_after_ns"][::core::mem::offset_of!(
890        XmtpFfiListConversationsOptions,
891        last_activity_after_ns
892    ) - 32usize];
893    ["Offset of field: XmtpFfiListConversationsOptions::last_activity_before_ns"][::core::mem::offset_of!(
894        XmtpFfiListConversationsOptions,
895        last_activity_before_ns
896    ) - 40usize];
897    ["Offset of field: XmtpFfiListConversationsOptions::consent_states"]
898        [::core::mem::offset_of!(XmtpFfiListConversationsOptions, consent_states) - 48usize];
899    ["Offset of field: XmtpFfiListConversationsOptions::consent_states_count"]
900        [::core::mem::offset_of!(XmtpFfiListConversationsOptions, consent_states_count) - 56usize];
901    ["Offset of field: XmtpFfiListConversationsOptions::order_by"]
902        [::core::mem::offset_of!(XmtpFfiListConversationsOptions, order_by) - 60usize];
903    ["Offset of field: XmtpFfiListConversationsOptions::include_duplicate_dms"]
904        [::core::mem::offset_of!(XmtpFfiListConversationsOptions, include_duplicate_dms) - 64usize];
905};
906impl Default for XmtpFfiListConversationsOptions {
907    fn default() -> Self {
908        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
909        unsafe {
910            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
911            s.assume_init()
912        }
913    }
914}
915#[doc = " Options for device sync archive operations."]
916#[repr(C)]
917#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
918pub struct XmtpFfiArchiveOptions {
919    #[doc = " Bitmask of element selections: bit 0 = Messages, bit 1 = Consent."]
920    pub elements: i32,
921    #[doc = " Start timestamp filter (ns). 0 = no filter."]
922    pub start_ns: i64,
923    #[doc = " End timestamp filter (ns). 0 = no filter."]
924    pub end_ns: i64,
925    #[doc = " Whether to exclude disappearing messages. 0 = include, 1 = exclude."]
926    pub exclude_disappearing_messages: i32,
927}
928#[allow(clippy::unnecessary_operation, clippy::identity_op)]
929const _: () = {
930    ["Size of XmtpFfiArchiveOptions"][::core::mem::size_of::<XmtpFfiArchiveOptions>() - 32usize];
931    ["Alignment of XmtpFfiArchiveOptions"]
932        [::core::mem::align_of::<XmtpFfiArchiveOptions>() - 8usize];
933    ["Offset of field: XmtpFfiArchiveOptions::elements"]
934        [::core::mem::offset_of!(XmtpFfiArchiveOptions, elements) - 0usize];
935    ["Offset of field: XmtpFfiArchiveOptions::start_ns"]
936        [::core::mem::offset_of!(XmtpFfiArchiveOptions, start_ns) - 8usize];
937    ["Offset of field: XmtpFfiArchiveOptions::end_ns"]
938        [::core::mem::offset_of!(XmtpFfiArchiveOptions, end_ns) - 16usize];
939    ["Offset of field: XmtpFfiArchiveOptions::exclude_disappearing_messages"]
940        [::core::mem::offset_of!(XmtpFfiArchiveOptions, exclude_disappearing_messages) - 24usize];
941};
942#[doc = " Callback for conversation stream events."]
943pub type XmtpFnConversationCallback = ::core::option::Option<
944    unsafe extern "C" fn(conversation: *mut XmtpFfiConversation, context: *mut ::core::ffi::c_void),
945>;
946#[doc = " Callback for message stream events."]
947pub type XmtpFnMessageCallback = ::core::option::Option<
948    unsafe extern "C" fn(message: *mut XmtpFfiMessage, context: *mut ::core::ffi::c_void),
949>;
950#[doc = " A consent record exposed to C."]
951#[repr(C)]
952#[derive(Debug, Copy, Clone, PartialEq, Eq)]
953pub struct XmtpFfiConsentRecord {
954    pub entity_type: XmtpFfiConsentEntityType,
955    pub state: XmtpFfiConsentState,
956    #[doc = " Entity identifier string."]
957    pub entity: *mut ::core::ffi::c_char,
958}
959#[allow(clippy::unnecessary_operation, clippy::identity_op)]
960const _: () = {
961    ["Size of XmtpFfiConsentRecord"][::core::mem::size_of::<XmtpFfiConsentRecord>() - 16usize];
962    ["Alignment of XmtpFfiConsentRecord"][::core::mem::align_of::<XmtpFfiConsentRecord>() - 8usize];
963    ["Offset of field: XmtpFfiConsentRecord::entity_type"]
964        [::core::mem::offset_of!(XmtpFfiConsentRecord, entity_type) - 0usize];
965    ["Offset of field: XmtpFfiConsentRecord::state"]
966        [::core::mem::offset_of!(XmtpFfiConsentRecord, state) - 4usize];
967    ["Offset of field: XmtpFfiConsentRecord::entity"]
968        [::core::mem::offset_of!(XmtpFfiConsentRecord, entity) - 8usize];
969};
970impl Default for XmtpFfiConsentRecord {
971    fn default() -> Self {
972        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
973        unsafe {
974            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
975            s.assume_init()
976        }
977    }
978}
979#[doc = " Callback for consent stream events.\n `records` is borrowed — valid only during the callback invocation."]
980pub type XmtpFnConsentCallback = ::core::option::Option<
981    unsafe extern "C" fn(
982        records: *const XmtpFfiConsentRecord,
983        count: i32,
984        context: *mut ::core::ffi::c_void,
985    ),
986>;
987#[doc = " A preference update exposed to C."]
988#[repr(C)]
989#[derive(Debug, Copy, Clone, PartialEq, Eq)]
990pub struct XmtpFfiPreferenceUpdate {
991    pub kind: XmtpFfiPreferenceUpdateKind,
992    #[doc = " For Consent: the consent record. For HmacKey: zeroed."]
993    pub consent: XmtpFfiConsentRecord,
994    #[doc = " For HmacKey: the key bytes. For Consent: null/0."]
995    pub hmac_key: *mut u8,
996    pub hmac_key_len: i32,
997}
998#[allow(clippy::unnecessary_operation, clippy::identity_op)]
999const _: () = {
1000    ["Size of XmtpFfiPreferenceUpdate"]
1001        [::core::mem::size_of::<XmtpFfiPreferenceUpdate>() - 40usize];
1002    ["Alignment of XmtpFfiPreferenceUpdate"]
1003        [::core::mem::align_of::<XmtpFfiPreferenceUpdate>() - 8usize];
1004    ["Offset of field: XmtpFfiPreferenceUpdate::kind"]
1005        [::core::mem::offset_of!(XmtpFfiPreferenceUpdate, kind) - 0usize];
1006    ["Offset of field: XmtpFfiPreferenceUpdate::consent"]
1007        [::core::mem::offset_of!(XmtpFfiPreferenceUpdate, consent) - 8usize];
1008    ["Offset of field: XmtpFfiPreferenceUpdate::hmac_key"]
1009        [::core::mem::offset_of!(XmtpFfiPreferenceUpdate, hmac_key) - 24usize];
1010    ["Offset of field: XmtpFfiPreferenceUpdate::hmac_key_len"]
1011        [::core::mem::offset_of!(XmtpFfiPreferenceUpdate, hmac_key_len) - 32usize];
1012};
1013impl Default for XmtpFfiPreferenceUpdate {
1014    fn default() -> Self {
1015        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
1016        unsafe {
1017            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1018            s.assume_init()
1019        }
1020    }
1021}
1022#[doc = " Callback for preference stream events.\n `updates` is borrowed — valid only during the callback invocation."]
1023pub type XmtpFnPreferenceCallback = ::core::option::Option<
1024    unsafe extern "C" fn(
1025        updates: *const XmtpFfiPreferenceUpdate,
1026        count: i32,
1027        context: *mut ::core::ffi::c_void,
1028    ),
1029>;
1030#[doc = " Callback for message deletion stream events.\n `message_id` is a borrowed hex string — valid only during the callback."]
1031pub type XmtpFnMessageDeletionCallback = ::core::option::Option<
1032    unsafe extern "C" fn(message_id: *const ::core::ffi::c_char, context: *mut ::core::ffi::c_void),
1033>;
1034unsafe extern "C" {
1035    #[doc = " Get the length of the last error message (including NUL terminator).\n Returns 0 if no error."]
1036    pub fn xmtp_last_error_length() -> i32;
1037}
1038unsafe extern "C" {
1039    #[doc = " Copy the last error message into `buf`. Returns bytes written (excluding NUL),\n or -1 if `buf` is null or too small."]
1040    pub fn xmtp_last_error_message(buf: *mut ::core::ffi::c_char, buf_len: i32) -> i32;
1041}
1042unsafe extern "C" {
1043    #[doc = " Free a string previously returned by this library."]
1044    pub fn xmtp_free_string(s: *mut ::core::ffi::c_char);
1045}
1046unsafe extern "C" {
1047    #[doc = " Free a byte buffer previously returned by this library."]
1048    pub fn xmtp_free_bytes(ptr: *mut u8, len: i32);
1049}
1050unsafe extern "C" {
1051    #[doc = " Free a string array returned by this library."]
1052    pub fn xmtp_free_string_array(arr: *mut *mut ::core::ffi::c_char, count: i32);
1053}
1054unsafe extern "C" {
1055    #[doc = " Initialize the tracing logger. Call at most once. `level` is a C string like\n \"debug\", \"info\", \"warn\", \"error\", or \"off\". Pass null for default (\"info\").\n Returns 0 on success."]
1056    pub fn xmtp_init_logger(level: *const ::core::ffi::c_char) -> i32;
1057}
1058unsafe extern "C" {
1059    #[doc = " Create a new XMTP client. Caller must free with [`xmtp_client_free`]."]
1060    pub fn xmtp_client_create(
1061        opts: *const XmtpFfiClientOptions,
1062        out: *mut *mut XmtpFfiClient,
1063    ) -> i32;
1064}
1065unsafe extern "C" {
1066    pub fn xmtp_client_free(ptr: *mut XmtpFfiClient);
1067}
1068unsafe extern "C" {
1069    #[doc = " Get the client's inbox ID. Caller must free with [`xmtp_free_string`]."]
1070    pub fn xmtp_client_inbox_id(client: *const XmtpFfiClient) -> *mut ::core::ffi::c_char;
1071}
1072unsafe extern "C" {
1073    #[doc = " Get the client's installation ID (hex). Caller must free with [`xmtp_free_string`]."]
1074    pub fn xmtp_client_installation_id(client: *const XmtpFfiClient) -> *mut ::core::ffi::c_char;
1075}
1076unsafe extern "C" {
1077    #[doc = " Check if the client identity is registered. Returns 1 = yes, 0 = no, -1 = error."]
1078    pub fn xmtp_client_is_registered(client: *const XmtpFfiClient) -> i32;
1079}
1080unsafe extern "C" {
1081    #[doc = " Register the client identity with an optional signature request.\n Pass null for `sig_req` if no external signature is needed."]
1082    pub fn xmtp_client_register_identity(
1083        client: *const XmtpFfiClient,
1084        sig_req: *const XmtpFfiSignatureRequest,
1085    ) -> i32;
1086}
1087unsafe extern "C" {
1088    #[doc = " Check which identifiers can receive messages.\n `identifiers` is an array of C strings, `kinds` is a parallel array of identifier kinds.\n Results are written to `out_results` (1 = can message, 0 = cannot)."]
1089    pub fn xmtp_client_can_message(
1090        client: *const XmtpFfiClient,
1091        identifiers: *const *const ::core::ffi::c_char,
1092        kinds: *const i32,
1093        count: i32,
1094        out_results: *mut i32,
1095    ) -> i32;
1096}
1097unsafe extern "C" {
1098    #[doc = " Release the database connection pool."]
1099    pub fn xmtp_client_release_db_connection(client: *const XmtpFfiClient) -> i32;
1100}
1101unsafe extern "C" {
1102    #[doc = " Reconnect to the database."]
1103    pub fn xmtp_client_reconnect_db(client: *const XmtpFfiClient) -> i32;
1104}
1105unsafe extern "C" {
1106    #[doc = " Set consent states for multiple entities.\n `entity_types`: 0 = GroupId, 1 = InboxId.\n `states`: 0 = Unknown, 1 = Allowed, 2 = Denied."]
1107    pub fn xmtp_client_set_consent_states(
1108        client: *const XmtpFfiClient,
1109        entity_types: *const i32,
1110        states: *const i32,
1111        entities: *const *const ::core::ffi::c_char,
1112        count: i32,
1113    ) -> i32;
1114}
1115unsafe extern "C" {
1116    #[doc = " Get consent state for a single entity. Result written to `out_state`."]
1117    pub fn xmtp_client_get_consent_state(
1118        client: *const XmtpFfiClient,
1119        entity_type: i32,
1120        entity: *const ::core::ffi::c_char,
1121        out_state: *mut i32,
1122    ) -> i32;
1123}
1124unsafe extern "C" {
1125    #[doc = " Get the inbox state for this client as a single-element list.\n Caller must free with [`xmtp_inbox_state_list_free`]."]
1126    pub fn xmtp_client_inbox_state(
1127        client: *const XmtpFfiClient,
1128        refresh: i32,
1129        out: *mut *mut XmtpFfiInboxStateList,
1130    ) -> i32;
1131}
1132unsafe extern "C" {
1133    #[doc = " Get the client's installation ID as raw bytes.\n Writes length to `out_len`. Caller must free with [`xmtp_free_bytes`]."]
1134    pub fn xmtp_client_installation_id_bytes(
1135        client: *const XmtpFfiClient,
1136        out_len: *mut i32,
1137    ) -> *mut u8;
1138}
1139unsafe extern "C" {
1140    #[doc = " Verify a signature produced by `xmtp_client_sign_with_installation_key`.\n Returns 0 on success (valid), -1 on error (invalid or bad args)."]
1141    pub fn xmtp_client_verify_signed_with_installation_key(
1142        client: *const XmtpFfiClient,
1143        text: *const ::core::ffi::c_char,
1144        signature_bytes: *const u8,
1145        signature_len: i32,
1146    ) -> i32;
1147}
1148unsafe extern "C" {
1149    #[doc = " Get a message by its hex-encoded ID. Caller must free with [`xmtp_message_free`]."]
1150    pub fn xmtp_client_get_message_by_id(
1151        client: *const XmtpFfiClient,
1152        message_id_hex: *const ::core::ffi::c_char,
1153        out: *mut *mut XmtpFfiMessage,
1154    ) -> i32;
1155}
1156unsafe extern "C" {
1157    #[doc = " Delete a message by its hex-encoded ID. Returns the number of deleted rows."]
1158    pub fn xmtp_client_delete_message_by_id(
1159        client: *const XmtpFfiClient,
1160        message_id_hex: *const ::core::ffi::c_char,
1161    ) -> i32;
1162}
1163unsafe extern "C" {
1164    #[doc = " Get the libxmtp version string. Caller must free with [`xmtp_free_string`]."]
1165    pub fn xmtp_libxmtp_version() -> *mut ::core::ffi::c_char;
1166}
1167unsafe extern "C" {
1168    #[doc = " Get MLS API call statistics. Writes to `out`."]
1169    pub fn xmtp_client_api_statistics(
1170        client: *const XmtpFfiClient,
1171        out: *mut XmtpFfiApiStats,
1172    ) -> i32;
1173}
1174unsafe extern "C" {
1175    #[doc = " Get identity API call statistics. Writes to `out`."]
1176    pub fn xmtp_client_api_identity_statistics(
1177        client: *const XmtpFfiClient,
1178        out: *mut XmtpFfiIdentityStats,
1179    ) -> i32;
1180}
1181unsafe extern "C" {
1182    #[doc = " Get aggregate statistics as a debug string. Caller must free with [`xmtp_free_string`]."]
1183    pub fn xmtp_client_api_aggregate_statistics(
1184        client: *const XmtpFfiClient,
1185    ) -> *mut ::core::ffi::c_char;
1186}
1187unsafe extern "C" {
1188    #[doc = " Clear all API call statistics."]
1189    pub fn xmtp_client_clear_all_statistics(client: *const XmtpFfiClient) -> i32;
1190}
1191unsafe extern "C" {
1192    #[doc = " Look up an inbox ID by account identifier using the client's connection.\n `identifier_kind`: 0 = Ethereum, 1 = Passkey.\n Returns null if not found. Caller must free with [`xmtp_free_string`]."]
1193    pub fn xmtp_client_get_inbox_id_by_identifier(
1194        client: *const XmtpFfiClient,
1195        identifier: *const ::core::ffi::c_char,
1196        identifier_kind: i32,
1197        out: *mut *mut ::core::ffi::c_char,
1198    ) -> i32;
1199}
1200unsafe extern "C" {
1201    #[doc = " Fetch inbox states for multiple inbox IDs.\n `inbox_ids` is a null-terminated array of C strings with `count` elements.\n Returns an opaque `FfiInboxStateList` via `out`. Caller must free with [`xmtp_inbox_state_list_free`]."]
1202    pub fn xmtp_client_fetch_inbox_states(
1203        client: *const XmtpFfiClient,
1204        inbox_ids: *const *const ::core::ffi::c_char,
1205        count: i32,
1206        refresh_from_network: i32,
1207        out: *mut *mut XmtpFfiInboxStateList,
1208    ) -> i32;
1209}
1210unsafe extern "C" {
1211    pub fn xmtp_inbox_state_list_len(list: *const XmtpFfiInboxStateList) -> i32;
1212}
1213unsafe extern "C" {
1214    #[doc = " Get inbox ID at index. Caller must free with [`xmtp_free_string`]."]
1215    pub fn xmtp_inbox_state_inbox_id(
1216        list: *const XmtpFfiInboxStateList,
1217        index: i32,
1218    ) -> *mut ::core::ffi::c_char;
1219}
1220unsafe extern "C" {
1221    #[doc = " Get recovery identifier at index. Caller must free with [`xmtp_free_string`]."]
1222    pub fn xmtp_inbox_state_recovery_identifier(
1223        list: *const XmtpFfiInboxStateList,
1224        index: i32,
1225    ) -> *mut ::core::ffi::c_char;
1226}
1227unsafe extern "C" {
1228    #[doc = " Get identifiers array at index. Returns a borrowed pointer; do NOT free."]
1229    pub fn xmtp_inbox_state_identifiers(
1230        list: *const XmtpFfiInboxStateList,
1231        index: i32,
1232        out_count: *mut i32,
1233    ) -> *const *mut ::core::ffi::c_char;
1234}
1235unsafe extern "C" {
1236    #[doc = " Get installation IDs (hex) at index. Returns a borrowed pointer; do NOT free."]
1237    pub fn xmtp_inbox_state_installation_ids(
1238        list: *const XmtpFfiInboxStateList,
1239        index: i32,
1240        out_count: *mut i32,
1241    ) -> *const *mut ::core::ffi::c_char;
1242}
1243unsafe extern "C" {
1244    #[doc = " Free an inbox state list."]
1245    pub fn xmtp_inbox_state_list_free(list: *mut XmtpFfiInboxStateList);
1246}
1247unsafe extern "C" {
1248    #[doc = " Create a new gateway auth handle. Caller must free with [`xmtp_auth_handle_free`]."]
1249    pub fn xmtp_auth_handle_create(out: *mut *mut XmtpFfiAuthHandle) -> i32;
1250}
1251unsafe extern "C" {
1252    #[doc = " Set a credential on an auth handle.\n `name` is an optional HTTP header name (null = \"authorization\").\n `value` is the header value (required).\n `expires_at_seconds` is the Unix timestamp when the credential expires."]
1253    pub fn xmtp_auth_handle_set(
1254        handle: *const XmtpFfiAuthHandle,
1255        name: *const ::core::ffi::c_char,
1256        value: *const ::core::ffi::c_char,
1257        expires_at_seconds: i64,
1258    ) -> i32;
1259}
1260unsafe extern "C" {
1261    #[doc = " Get the unique ID of an auth handle."]
1262    pub fn xmtp_auth_handle_id(handle: *const XmtpFfiAuthHandle) -> usize;
1263}
1264unsafe extern "C" {
1265    pub fn xmtp_auth_handle_free(ptr: *mut XmtpFfiAuthHandle);
1266}
1267unsafe extern "C" {
1268    #[doc = " Fetch the number of identity updates for multiple inbox IDs.\n Caller must free the result with [`xmtp_inbox_update_count_list_free`]."]
1269    pub fn xmtp_client_fetch_inbox_updates_count(
1270        client: *const XmtpFfiClient,
1271        inbox_ids: *const *const ::core::ffi::c_char,
1272        inbox_ids_count: i32,
1273        refresh: i32,
1274        out: *mut *mut XmtpFfiInboxUpdateCountList,
1275    ) -> i32;
1276}
1277unsafe extern "C" {
1278    #[doc = " Fetch the number of identity updates for the client's own inbox."]
1279    pub fn xmtp_client_fetch_own_inbox_updates_count(
1280        client: *const XmtpFfiClient,
1281        refresh: i32,
1282        out: *mut u32,
1283    ) -> i32;
1284}
1285unsafe extern "C" {
1286    pub fn xmtp_inbox_update_count_list_len(list: *const XmtpFfiInboxUpdateCountList) -> i32;
1287}
1288unsafe extern "C" {
1289    pub fn xmtp_inbox_update_count_list_get(
1290        list: *const XmtpFfiInboxUpdateCountList,
1291        index: i32,
1292    ) -> *const XmtpFfiInboxUpdateCount;
1293}
1294unsafe extern "C" {
1295    #[doc = " Free an inbox update count list."]
1296    pub fn xmtp_inbox_update_count_list_free(list: *mut XmtpFfiInboxUpdateCountList);
1297}
1298unsafe extern "C" {
1299    #[doc = " Fetch key package statuses for a list of installation IDs (hex-encoded).\n Caller must free with [`xmtp_key_package_status_list_free`]."]
1300    pub fn xmtp_client_fetch_key_package_statuses(
1301        client: *const XmtpFfiClient,
1302        installation_ids: *const *const ::core::ffi::c_char,
1303        installation_ids_count: i32,
1304        out: *mut *mut XmtpFfiKeyPackageStatusList,
1305    ) -> i32;
1306}
1307unsafe extern "C" {
1308    pub fn xmtp_key_package_status_list_len(list: *const XmtpFfiKeyPackageStatusList) -> i32;
1309}
1310unsafe extern "C" {
1311    pub fn xmtp_key_package_status_list_get(
1312        list: *const XmtpFfiKeyPackageStatusList,
1313        index: i32,
1314    ) -> *const XmtpFfiKeyPackageStatus;
1315}
1316unsafe extern "C" {
1317    #[doc = " Free a key package status list."]
1318    pub fn xmtp_key_package_status_list_free(list: *mut XmtpFfiKeyPackageStatusList);
1319}
1320unsafe extern "C" {
1321    #[doc = " Get the account identifier string used to create this client.\n Caller must free with [`xmtp_free_string`]."]
1322    pub fn xmtp_client_account_identifier(client: *const XmtpFfiClient)
1323    -> *mut ::core::ffi::c_char;
1324}
1325unsafe extern "C" {
1326    #[doc = " Get the app version string set during client creation.\n Returns null if no app version was set. Caller must free with [`xmtp_free_string`]."]
1327    pub fn xmtp_client_app_version(client: *const XmtpFfiClient) -> *mut ::core::ffi::c_char;
1328}
1329unsafe extern "C" {
1330    pub fn xmtp_conversation_free(ptr: *mut XmtpFfiConversation);
1331}
1332unsafe extern "C" {
1333    #[doc = " Get the conversation's hex-encoded group ID. Caller must free with [`xmtp_free_string`]."]
1334    pub fn xmtp_conversation_id(conv: *const XmtpFfiConversation) -> *mut ::core::ffi::c_char;
1335}
1336unsafe extern "C" {
1337    #[doc = " Get the conversation created-at timestamp in nanoseconds."]
1338    pub fn xmtp_conversation_created_at_ns(conv: *const XmtpFfiConversation) -> i64;
1339}
1340unsafe extern "C" {
1341    #[doc = " Get the conversation type. Returns `FfiConversationType` value, or -1 on error."]
1342    pub fn xmtp_conversation_type(conv: *const XmtpFfiConversation) -> i32;
1343}
1344unsafe extern "C" {
1345    #[doc = " Get the DM peer's inbox ID. Caller must free with [`xmtp_free_string`].\n Returns null if not a DM or on error."]
1346    pub fn xmtp_conversation_dm_peer_inbox_id(
1347        conv: *const XmtpFfiConversation,
1348    ) -> *mut ::core::ffi::c_char;
1349}
1350unsafe extern "C" {
1351    #[doc = " Sync this conversation with the network."]
1352    pub fn xmtp_conversation_sync(conv: *const XmtpFfiConversation) -> i32;
1353}
1354unsafe extern "C" {
1355    #[doc = " Send raw encoded content bytes. Returns the message ID (hex) via `out_id`.\n Caller must free `out_id` with [`xmtp_free_string`].\n Pass null for `opts` to use defaults (should_push = true)."]
1356    pub fn xmtp_conversation_send(
1357        conv: *const XmtpFfiConversation,
1358        content_bytes: *const u8,
1359        content_len: i32,
1360        opts: *const XmtpFfiSendOpts,
1361        out_id: *mut *mut ::core::ffi::c_char,
1362    ) -> i32;
1363}
1364unsafe extern "C" {
1365    #[doc = " Send raw encoded content bytes optimistically (returns immediately, publishes in background).\n Returns the message ID (hex) via `out_id`. Caller must free with [`xmtp_free_string`]."]
1366    pub fn xmtp_conversation_send_optimistic(
1367        conv: *const XmtpFfiConversation,
1368        content_bytes: *const u8,
1369        content_len: i32,
1370        opts: *const XmtpFfiSendOpts,
1371        out_id: *mut *mut ::core::ffi::c_char,
1372    ) -> i32;
1373}
1374unsafe extern "C" {
1375    #[doc = " Publish all queued (unpublished) messages in this conversation."]
1376    pub fn xmtp_conversation_publish_messages(conv: *const XmtpFfiConversation) -> i32;
1377}
1378unsafe extern "C" {
1379    #[doc = " Prepare a message for later publishing (optimistic send workflow).\n Stores the message locally without publishing. Returns message ID (hex) via `out_id`.\n Caller must free `out_id` with [`xmtp_free_string`]."]
1380    pub fn xmtp_conversation_prepare_message(
1381        conv: *const XmtpFfiConversation,
1382        content_bytes: *const u8,
1383        content_len: i32,
1384        should_push: i32,
1385        out_id: *mut *mut ::core::ffi::c_char,
1386    ) -> i32;
1387}
1388unsafe extern "C" {
1389    #[doc = " Publish a previously prepared message by its hex-encoded ID."]
1390    pub fn xmtp_conversation_publish_stored_message(
1391        conv: *const XmtpFfiConversation,
1392        message_id_hex: *const ::core::ffi::c_char,
1393    ) -> i32;
1394}
1395unsafe extern "C" {
1396    #[doc = " List messages in this conversation. Caller must free with [`xmtp_message_list_free`]."]
1397    pub fn xmtp_conversation_list_messages(
1398        conv: *const XmtpFfiConversation,
1399        opts: *const XmtpFfiListMessagesOptions,
1400        out: *mut *mut XmtpFfiMessageList,
1401    ) -> i32;
1402}
1403unsafe extern "C" {
1404    #[doc = " Count messages matching the given filter options.\n Pass null for `opts` to count all messages."]
1405    pub fn xmtp_conversation_count_messages(
1406        conv: *const XmtpFfiConversation,
1407        opts: *const XmtpFfiListMessagesOptions,
1408    ) -> i64;
1409}
1410unsafe extern "C" {
1411    pub fn xmtp_message_list_len(list: *const XmtpFfiMessageList) -> i32;
1412}
1413unsafe extern "C" {
1414    #[doc = " Get message ID (hex) at index. Caller must free with [`xmtp_free_string`]."]
1415    pub fn xmtp_message_id(list: *const XmtpFfiMessageList, index: i32)
1416    -> *mut ::core::ffi::c_char;
1417}
1418unsafe extern "C" {
1419    #[doc = " Get sender inbox ID at index. Caller must free with [`xmtp_free_string`]."]
1420    pub fn xmtp_message_sender_inbox_id(
1421        list: *const XmtpFfiMessageList,
1422        index: i32,
1423    ) -> *mut ::core::ffi::c_char;
1424}
1425unsafe extern "C" {
1426    #[doc = " Get sent-at timestamp (ns) at index."]
1427    pub fn xmtp_message_sent_at_ns(list: *const XmtpFfiMessageList, index: i32) -> i64;
1428}
1429unsafe extern "C" {
1430    #[doc = " Get message kind at index: 0=Application, 1=MembershipChange, -1=error."]
1431    pub fn xmtp_message_kind(list: *const XmtpFfiMessageList, index: i32) -> i32;
1432}
1433unsafe extern "C" {
1434    #[doc = " Get delivery status at index: 0=Unpublished, 1=Published, 2=Failed, -1=error."]
1435    pub fn xmtp_message_delivery_status(list: *const XmtpFfiMessageList, index: i32) -> i32;
1436}
1437unsafe extern "C" {
1438    #[doc = " Get raw decrypted content bytes at index. Writes length to `out_len`.\n The returned pointer is borrowed from the list — do NOT free it."]
1439    pub fn xmtp_message_content_bytes(
1440        list: *const XmtpFfiMessageList,
1441        index: i32,
1442        out_len: *mut i32,
1443    ) -> *const u8;
1444}
1445unsafe extern "C" {
1446    pub fn xmtp_message_list_free(ptr: *mut XmtpFfiMessageList);
1447}
1448unsafe extern "C" {
1449    pub fn xmtp_message_free(ptr: *mut XmtpFfiMessage);
1450}
1451unsafe extern "C" {
1452    #[doc = " Get the message ID (hex) from a single message handle.\n Caller must free with [`xmtp_free_string`]."]
1453    pub fn xmtp_single_message_id(msg: *const XmtpFfiMessage) -> *mut ::core::ffi::c_char;
1454}
1455unsafe extern "C" {
1456    #[doc = " Get the group ID (hex) from a single message handle.\n Caller must free with [`xmtp_free_string`]."]
1457    pub fn xmtp_single_message_group_id(msg: *const XmtpFfiMessage) -> *mut ::core::ffi::c_char;
1458}
1459unsafe extern "C" {
1460    #[doc = " Get the sender inbox ID from a single message handle.\n Caller must free with [`xmtp_free_string`]."]
1461    pub fn xmtp_single_message_sender_inbox_id(
1462        msg: *const XmtpFfiMessage,
1463    ) -> *mut ::core::ffi::c_char;
1464}
1465unsafe extern "C" {
1466    #[doc = " Get the sent-at timestamp (ns) from a single message handle."]
1467    pub fn xmtp_single_message_sent_at_ns(msg: *const XmtpFfiMessage) -> i64;
1468}
1469unsafe extern "C" {
1470    #[doc = " Get raw content bytes from a single message handle.\n The returned pointer is borrowed — valid only while the message handle is alive."]
1471    pub fn xmtp_single_message_content_bytes(
1472        msg: *const XmtpFfiMessage,
1473        out_len: *mut i32,
1474    ) -> *const u8;
1475}
1476unsafe extern "C" {
1477    #[doc = " List group members. Caller must free with [`xmtp_group_member_list_free`]."]
1478    pub fn xmtp_conversation_list_members(
1479        conv: *const XmtpFfiConversation,
1480        out: *mut *mut XmtpFfiGroupMemberList,
1481    ) -> i32;
1482}
1483unsafe extern "C" {
1484    pub fn xmtp_group_member_list_len(list: *const XmtpFfiGroupMemberList) -> i32;
1485}
1486unsafe extern "C" {
1487    #[doc = " Get member inbox ID at index. Caller must free with [`xmtp_free_string`]."]
1488    pub fn xmtp_group_member_inbox_id(
1489        list: *const XmtpFfiGroupMemberList,
1490        index: i32,
1491    ) -> *mut ::core::ffi::c_char;
1492}
1493unsafe extern "C" {
1494    #[doc = " Get member permission level at index: 0=Member, 1=Admin, 2=SuperAdmin, -1=error."]
1495    pub fn xmtp_group_member_permission_level(
1496        list: *const XmtpFfiGroupMemberList,
1497        index: i32,
1498    ) -> i32;
1499}
1500unsafe extern "C" {
1501    #[doc = " Get member consent state at index: 0=Unknown, 1=Allowed, 2=Denied, -1=error."]
1502    pub fn xmtp_group_member_consent_state(list: *const XmtpFfiGroupMemberList, index: i32) -> i32;
1503}
1504unsafe extern "C" {
1505    #[doc = " Get member account identifiers at index.\n Returns a borrowed pointer to the internal string array. Do NOT free individual strings.\n Use `out_count` to get the number of identifiers."]
1506    pub fn xmtp_group_member_account_identifiers(
1507        list: *const XmtpFfiGroupMemberList,
1508        index: i32,
1509        out_count: *mut i32,
1510    ) -> *const *mut ::core::ffi::c_char;
1511}
1512unsafe extern "C" {
1513    #[doc = " Get member installation IDs (hex) at index.\n Returns a borrowed pointer to the internal string array."]
1514    pub fn xmtp_group_member_installation_ids(
1515        list: *const XmtpFfiGroupMemberList,
1516        index: i32,
1517        out_count: *mut i32,
1518    ) -> *const *mut ::core::ffi::c_char;
1519}
1520unsafe extern "C" {
1521    #[doc = " Free a group member list."]
1522    pub fn xmtp_group_member_list_free(list: *mut XmtpFfiGroupMemberList);
1523}
1524unsafe extern "C" {
1525    #[doc = " Add members by inbox IDs."]
1526    pub fn xmtp_conversation_add_members(
1527        conv: *const XmtpFfiConversation,
1528        inbox_ids: *const *const ::core::ffi::c_char,
1529        count: i32,
1530    ) -> i32;
1531}
1532unsafe extern "C" {
1533    #[doc = " Remove members by inbox IDs."]
1534    pub fn xmtp_conversation_remove_members(
1535        conv: *const XmtpFfiConversation,
1536        inbox_ids: *const *const ::core::ffi::c_char,
1537        count: i32,
1538    ) -> i32;
1539}
1540unsafe extern "C" {
1541    #[doc = " Leave the group."]
1542    pub fn xmtp_conversation_leave(conv: *const XmtpFfiConversation) -> i32;
1543}
1544unsafe extern "C" {
1545    #[doc = " Add/remove admin or super admin. `action`: 0=AddAdmin, 1=RemoveAdmin, 2=AddSuperAdmin, 3=RemoveSuperAdmin."]
1546    pub fn xmtp_conversation_update_admin_list(
1547        conv: *const XmtpFfiConversation,
1548        inbox_id: *const ::core::ffi::c_char,
1549        action: i32,
1550    ) -> i32;
1551}
1552unsafe extern "C" {
1553    pub fn xmtp_conversation_group_name(
1554        conv: *const XmtpFfiConversation,
1555    ) -> *mut ::core::ffi::c_char;
1556}
1557unsafe extern "C" {
1558    pub fn xmtp_conversation_update_group_name(
1559        conv: *const XmtpFfiConversation,
1560        value: *const ::core::ffi::c_char,
1561    ) -> i32;
1562}
1563unsafe extern "C" {
1564    pub fn xmtp_conversation_group_description(
1565        conv: *const XmtpFfiConversation,
1566    ) -> *mut ::core::ffi::c_char;
1567}
1568unsafe extern "C" {
1569    pub fn xmtp_conversation_update_group_description(
1570        conv: *const XmtpFfiConversation,
1571        value: *const ::core::ffi::c_char,
1572    ) -> i32;
1573}
1574unsafe extern "C" {
1575    pub fn xmtp_conversation_group_image_url(
1576        conv: *const XmtpFfiConversation,
1577    ) -> *mut ::core::ffi::c_char;
1578}
1579unsafe extern "C" {
1580    pub fn xmtp_conversation_update_group_image_url(
1581        conv: *const XmtpFfiConversation,
1582        value: *const ::core::ffi::c_char,
1583    ) -> i32;
1584}
1585unsafe extern "C" {
1586    #[doc = " Get conversation consent state. Writes to `out_state` (0=Unknown, 1=Allowed, 2=Denied)."]
1587    pub fn xmtp_conversation_consent_state(
1588        conv: *const XmtpFfiConversation,
1589        out_state: *mut i32,
1590    ) -> i32;
1591}
1592unsafe extern "C" {
1593    #[doc = " Update conversation consent state."]
1594    pub fn xmtp_conversation_update_consent_state(
1595        conv: *const XmtpFfiConversation,
1596        state: i32,
1597    ) -> i32;
1598}
1599unsafe extern "C" {
1600    #[doc = " Update a permission policy on this conversation.\n `update_type`: 1=AddMember, 2=RemoveMember, 3=AddAdmin, 4=RemoveAdmin, 5=UpdateMetadata.\n `policy`: 1=Allow, 2=Deny, 3=AdminOnly, 4=SuperAdminOnly.\n `metadata_field_name`: Only used when update_type=5 (e.g. \"group_name\"). Pass null otherwise."]
1601    pub fn xmtp_conversation_update_permission_policy(
1602        conv: *const XmtpFfiConversation,
1603        update_type: i32,
1604        policy: i32,
1605        metadata_field_name: *const ::core::ffi::c_char,
1606    ) -> i32;
1607}
1608unsafe extern "C" {
1609    #[doc = " Check if the conversation is active. Returns 1=active, 0=inactive, -1=error."]
1610    pub fn xmtp_conversation_is_active(conv: *const XmtpFfiConversation) -> i32;
1611}
1612unsafe extern "C" {
1613    #[doc = " Get the membership state of the current user in this conversation.\n 0=Allowed, 1=Rejected, 2=Pending, 3=Restored, 4=PendingRemove, -1=error."]
1614    pub fn xmtp_conversation_membership_state(conv: *const XmtpFfiConversation) -> i32;
1615}
1616unsafe extern "C" {
1617    pub fn xmtp_conversation_added_by_inbox_id(
1618        conv: *const XmtpFfiConversation,
1619    ) -> *mut ::core::ffi::c_char;
1620}
1621unsafe extern "C" {
1622    pub fn xmtp_conversation_list_admins(
1623        conv: *const XmtpFfiConversation,
1624        out_count: *mut i32,
1625    ) -> *mut *mut ::core::ffi::c_char;
1626}
1627unsafe extern "C" {
1628    pub fn xmtp_conversation_list_super_admins(
1629        conv: *const XmtpFfiConversation,
1630        out_count: *mut i32,
1631    ) -> *mut *mut ::core::ffi::c_char;
1632}
1633unsafe extern "C" {
1634    pub fn xmtp_conversation_is_admin(
1635        conv: *const XmtpFfiConversation,
1636        inbox_id: *const ::core::ffi::c_char,
1637    ) -> i32;
1638}
1639unsafe extern "C" {
1640    pub fn xmtp_conversation_is_super_admin(
1641        conv: *const XmtpFfiConversation,
1642        inbox_id: *const ::core::ffi::c_char,
1643    ) -> i32;
1644}
1645unsafe extern "C" {
1646    #[doc = " Add members by external identifiers (address/passkey).\n `identifiers` and `kinds` are parallel arrays of length `count`."]
1647    pub fn xmtp_conversation_add_members_by_identity(
1648        conv: *const XmtpFfiConversation,
1649        identifiers: *const *const ::core::ffi::c_char,
1650        kinds: *const i32,
1651        count: i32,
1652    ) -> i32;
1653}
1654unsafe extern "C" {
1655    #[doc = " Remove members by external identifiers (address/passkey)."]
1656    pub fn xmtp_conversation_remove_members_by_identity(
1657        conv: *const XmtpFfiConversation,
1658        identifiers: *const *const ::core::ffi::c_char,
1659        kinds: *const i32,
1660        count: i32,
1661    ) -> i32;
1662}
1663unsafe extern "C" {
1664    #[doc = " Update the message disappearing settings for this conversation."]
1665    pub fn xmtp_conversation_update_disappearing_settings(
1666        conv: *const XmtpFfiConversation,
1667        settings: *const XmtpFfiDisappearingSettings,
1668    ) -> i32;
1669}
1670unsafe extern "C" {
1671    #[doc = " Remove (disable) message disappearing settings for this conversation."]
1672    pub fn xmtp_conversation_remove_disappearing_settings(conv: *const XmtpFfiConversation) -> i32;
1673}
1674unsafe extern "C" {
1675    #[doc = " Get the current message disappearing settings.\n Returns 0 on success (writes to `out`), -1 if not set or on error."]
1676    pub fn xmtp_conversation_disappearing_settings(
1677        conv: *const XmtpFfiConversation,
1678        out: *mut XmtpFfiDisappearingSettings,
1679    ) -> i32;
1680}
1681unsafe extern "C" {
1682    #[doc = " Check if message disappearing is enabled.\n Returns 1=enabled, 0=disabled, -1=error."]
1683    pub fn xmtp_conversation_is_disappearing_enabled(conv: *const XmtpFfiConversation) -> i32;
1684}
1685unsafe extern "C" {
1686    pub fn xmtp_conversation_app_data(conv: *const XmtpFfiConversation)
1687    -> *mut ::core::ffi::c_char;
1688}
1689unsafe extern "C" {
1690    pub fn xmtp_conversation_update_app_data(
1691        conv: *const XmtpFfiConversation,
1692        value: *const ::core::ffi::c_char,
1693    ) -> i32;
1694}
1695unsafe extern "C" {
1696    #[doc = " Find duplicate DM conversations for this DM.\n Returns a conversation list. Caller must free with [`xmtp_conversation_list_free`]."]
1697    pub fn xmtp_conversation_duplicate_dms(
1698        conv: *const XmtpFfiConversation,
1699        out: *mut *mut XmtpFfiConversationList,
1700    ) -> i32;
1701}
1702unsafe extern "C" {
1703    #[doc = " Check if the conversation is paused for a version upgrade.\n Writes the version string to `out` if paused, or null if not paused.\n Caller must free `out` with [`xmtp_free_string`].\n Returns 0 on success, -1 on error."]
1704    pub fn xmtp_conversation_paused_for_version(
1705        conv: *const XmtpFfiConversation,
1706        out: *mut *mut ::core::ffi::c_char,
1707    ) -> i32;
1708}
1709unsafe extern "C" {
1710    #[doc = " Get debug info for this conversation.\n Caller must free string fields with [`xmtp_free_string`]."]
1711    pub fn xmtp_conversation_debug_info(
1712        conv: *const XmtpFfiConversation,
1713        out: *mut XmtpFfiConversationDebugInfo,
1714    ) -> i32;
1715}
1716unsafe extern "C" {
1717    #[doc = " Free a conversation debug info struct (its string fields and cursor array)."]
1718    pub fn xmtp_conversation_debug_info_free(info: *mut XmtpFfiConversationDebugInfo);
1719}
1720unsafe extern "C" {
1721    #[doc = " Get HMAC keys for this conversation (including duplicate DMs).\n Returns a map via `out`. Caller must free with [`xmtp_hmac_key_map_free`]."]
1722    pub fn xmtp_conversation_hmac_keys(
1723        conv: *const XmtpFfiConversation,
1724        out: *mut *mut XmtpFfiHmacKeyMap,
1725    ) -> i32;
1726}
1727unsafe extern "C" {
1728    #[doc = " Get the number of entries in an HMAC key map."]
1729    pub fn xmtp_hmac_key_map_len(map: *const XmtpFfiHmacKeyMap) -> i32;
1730}
1731unsafe extern "C" {
1732    #[doc = " Get the group ID (hex) at index. Returns a borrowed pointer; do NOT free."]
1733    pub fn xmtp_hmac_key_map_group_id(
1734        map: *const XmtpFfiHmacKeyMap,
1735        index: i32,
1736    ) -> *const ::core::ffi::c_char;
1737}
1738unsafe extern "C" {
1739    #[doc = " Get the HMAC keys at index. Writes count to `out_count`.\n Returns a borrowed pointer to the key array; do NOT free individual keys."]
1740    pub fn xmtp_hmac_key_map_keys(
1741        map: *const XmtpFfiHmacKeyMap,
1742        index: i32,
1743        out_count: *mut i32,
1744    ) -> *const XmtpFfiHmacKey;
1745}
1746unsafe extern "C" {
1747    #[doc = " Process a raw group message received via push notification.\n Returns a list of stored messages. Caller must free with [`xmtp_message_list_free`]."]
1748    pub fn xmtp_conversation_process_streamed_group_message(
1749        conversation: *const XmtpFfiConversation,
1750        envelope_bytes: *const u8,
1751        envelope_bytes_len: i32,
1752        out: *mut *mut XmtpFfiMessageList,
1753    ) -> i32;
1754}
1755unsafe extern "C" {
1756    #[doc = " Get the full group metadata (creator inbox ID + conversation type).\n Caller must free with [`xmtp_group_metadata_free`]."]
1757    pub fn xmtp_conversation_group_metadata(
1758        conversation: *const XmtpFfiConversation,
1759        out: *mut *mut XmtpFfiGroupMetadata,
1760    ) -> i32;
1761}
1762unsafe extern "C" {
1763    #[doc = " Free a group metadata struct."]
1764    pub fn xmtp_group_metadata_free(meta: *mut XmtpFfiGroupMetadata);
1765}
1766unsafe extern "C" {
1767    #[doc = " Get the group permissions (policy type + full policy set).\n Caller must free with [`xmtp_group_permissions_free`]."]
1768    pub fn xmtp_conversation_group_permissions(
1769        conversation: *const XmtpFfiConversation,
1770        out: *mut *mut XmtpFfiGroupPermissions,
1771    ) -> i32;
1772}
1773unsafe extern "C" {
1774    pub fn xmtp_group_permissions_free(ptr: *mut XmtpFfiGroupPermissions);
1775}
1776unsafe extern "C" {
1777    #[doc = " List enriched (decoded) messages for a conversation.\n Fetches both enriched metadata and raw content bytes in a single call.\n Caller must free with [`xmtp_enriched_message_list_free`]."]
1778    pub fn xmtp_conversation_list_enriched_messages(
1779        conversation: *const XmtpFfiConversation,
1780        opts: *const XmtpFfiListMessagesOptions,
1781        out: *mut *mut XmtpFfiEnrichedMessageList,
1782    ) -> i32;
1783}
1784unsafe extern "C" {
1785    pub fn xmtp_enriched_message_list_len(list: *const XmtpFfiEnrichedMessageList) -> i32;
1786}
1787unsafe extern "C" {
1788    pub fn xmtp_enriched_message_list_get(
1789        list: *const XmtpFfiEnrichedMessageList,
1790        index: i32,
1791    ) -> *const XmtpFfiEnrichedMessage;
1792}
1793unsafe extern "C" {
1794    #[doc = " Free an enriched message list (including owned strings and content bytes)."]
1795    pub fn xmtp_enriched_message_list_free(list: *mut XmtpFfiEnrichedMessageList);
1796}
1797unsafe extern "C" {
1798    #[doc = " Get per-inbox last read times for a conversation.\n Caller must free with [`xmtp_last_read_time_list_free`]."]
1799    pub fn xmtp_conversation_last_read_times(
1800        conversation: *const XmtpFfiConversation,
1801        out: *mut *mut XmtpFfiLastReadTimeList,
1802    ) -> i32;
1803}
1804unsafe extern "C" {
1805    pub fn xmtp_last_read_time_list_len(list: *const XmtpFfiLastReadTimeList) -> i32;
1806}
1807unsafe extern "C" {
1808    pub fn xmtp_last_read_time_list_get(
1809        list: *const XmtpFfiLastReadTimeList,
1810        index: i32,
1811    ) -> *const XmtpFfiLastReadTimeEntry;
1812}
1813unsafe extern "C" {
1814    pub fn xmtp_last_read_time_list_free(list: *mut XmtpFfiLastReadTimeList);
1815}
1816unsafe extern "C" {
1817    #[doc = " Free an HMAC key map (including all owned data)."]
1818    pub fn xmtp_hmac_key_map_free(map: *mut XmtpFfiHmacKeyMap);
1819}
1820unsafe extern "C" {
1821    #[doc = " Create a new group conversation, optionally adding members by inbox ID.\n Pass null/0 for `member_inbox_ids`/`member_count` to create an empty group.\n Caller must free result with [`xmtp_conversation_free`]."]
1822    pub fn xmtp_client_create_group(
1823        client: *const XmtpFfiClient,
1824        opts: *const XmtpFfiCreateGroupOptions,
1825        member_inbox_ids: *const *const ::core::ffi::c_char,
1826        member_count: i32,
1827        out: *mut *mut XmtpFfiConversation,
1828    ) -> i32;
1829}
1830unsafe extern "C" {
1831    #[doc = " Create a new group, adding members by identity (address/passkey).\n `identifiers` and `kinds` are parallel arrays of length `count`.\n Caller must free result with [`xmtp_conversation_free`]."]
1832    pub fn xmtp_client_create_group_by_identity(
1833        client: *const XmtpFfiClient,
1834        opts: *const XmtpFfiCreateGroupOptions,
1835        identifiers: *const *const ::core::ffi::c_char,
1836        kinds: *const i32,
1837        count: i32,
1838        out: *mut *mut XmtpFfiConversation,
1839    ) -> i32;
1840}
1841unsafe extern "C" {
1842    #[doc = " Find or create a DM by identifier. Caller must free result with [`xmtp_conversation_free`]."]
1843    pub fn xmtp_client_create_dm(
1844        client: *const XmtpFfiClient,
1845        identifier: *const ::core::ffi::c_char,
1846        identifier_kind: i32,
1847        disappear_from_ns: i64,
1848        disappear_in_ns: i64,
1849        out: *mut *mut XmtpFfiConversation,
1850    ) -> i32;
1851}
1852unsafe extern "C" {
1853    #[doc = " Find or create a DM by inbox ID. Caller must free result with [`xmtp_conversation_free`]."]
1854    pub fn xmtp_client_find_dm_by_inbox_id(
1855        client: *const XmtpFfiClient,
1856        inbox_id: *const ::core::ffi::c_char,
1857        out: *mut *mut XmtpFfiConversation,
1858    ) -> i32;
1859}
1860unsafe extern "C" {
1861    #[doc = " Create a DM by target inbox ID. Caller must free result with [`xmtp_conversation_free`]."]
1862    pub fn xmtp_client_create_dm_by_inbox_id(
1863        client: *const XmtpFfiClient,
1864        inbox_id: *const ::core::ffi::c_char,
1865        disappear_from_ns: i64,
1866        disappear_in_ns: i64,
1867        out: *mut *mut XmtpFfiConversation,
1868    ) -> i32;
1869}
1870unsafe extern "C" {
1871    #[doc = " Get a conversation by hex-encoded group ID.\n Caller must free result with [`xmtp_conversation_free`]."]
1872    pub fn xmtp_client_get_conversation_by_id(
1873        client: *const XmtpFfiClient,
1874        hex_id: *const ::core::ffi::c_char,
1875        out: *mut *mut XmtpFfiConversation,
1876    ) -> i32;
1877}
1878unsafe extern "C" {
1879    #[doc = " List conversations. Caller must free result with [`xmtp_conversation_list_free`]."]
1880    pub fn xmtp_client_list_conversations(
1881        client: *const XmtpFfiClient,
1882        opts: *const XmtpFfiListConversationsOptions,
1883        out: *mut *mut XmtpFfiConversationList,
1884    ) -> i32;
1885}
1886unsafe extern "C" {
1887    pub fn xmtp_conversation_list_len(list: *const XmtpFfiConversationList) -> i32;
1888}
1889unsafe extern "C" {
1890    #[doc = " Get a conversation from a list by index. Caller must free with [`xmtp_conversation_free`]."]
1891    pub fn xmtp_conversation_list_get(
1892        list: *const XmtpFfiConversationList,
1893        index: i32,
1894        out: *mut *mut XmtpFfiConversation,
1895    ) -> i32;
1896}
1897unsafe extern "C" {
1898    pub fn xmtp_conversation_list_free(ptr: *mut XmtpFfiConversationList);
1899}
1900unsafe extern "C" {
1901    #[doc = " Get the sent_at_ns of the last message for a conversation list item.\n Returns 0 if no last message exists, or -1 on error."]
1902    pub fn xmtp_conversation_list_last_message_sent_at_ns(
1903        list: *const XmtpFfiConversationList,
1904        index: i32,
1905    ) -> i64;
1906}
1907unsafe extern "C" {
1908    #[doc = " Get the last message for a conversation list item as an opaque FfiMessage handle.\n Returns 0 on success (writes to `out`), -1 on error or if no last message exists.\n Caller must free with `xmtp_message_free`."]
1909    pub fn xmtp_conversation_list_last_message(
1910        list: *const XmtpFfiConversationList,
1911        index: i32,
1912        out: *mut *mut XmtpFfiMessage,
1913    ) -> i32;
1914}
1915unsafe extern "C" {
1916    #[doc = " Get the commit log fork status for a conversation list item.\n Returns -1=unknown/error, 0=not forked, 1=forked."]
1917    pub fn xmtp_conversation_list_is_commit_log_forked(
1918        list: *const XmtpFfiConversationList,
1919        index: i32,
1920    ) -> i32;
1921}
1922unsafe extern "C" {
1923    #[doc = " Sync welcomes (process new group invitations)."]
1924    pub fn xmtp_client_sync_welcomes(client: *const XmtpFfiClient) -> i32;
1925}
1926unsafe extern "C" {
1927    #[doc = " Sync all conversations, optionally filtering by consent states.\n `consent_states` is a parallel array of consent state values (0=Unknown, 1=Allowed, 2=Denied).\n Pass null and 0 to sync all."]
1928    pub fn xmtp_client_sync_all(
1929        client: *const XmtpFfiClient,
1930        consent_states: *const i32,
1931        consent_states_count: i32,
1932        out_synced: *mut i32,
1933        out_eligible: *mut i32,
1934    ) -> i32;
1935}
1936unsafe extern "C" {
1937    #[doc = " Sync preferences (device sync groups only)."]
1938    pub fn xmtp_client_sync_preferences(
1939        client: *const XmtpFfiClient,
1940        out_synced: *mut i32,
1941        out_eligible: *mut i32,
1942    ) -> i32;
1943}
1944unsafe extern "C" {
1945    #[doc = " Get HMAC keys for all conversations (including duplicate DMs).\n Returns a map via `out`. Caller must free with [`xmtp_hmac_key_map_free`]."]
1946    pub fn xmtp_client_hmac_keys(
1947        client: *const XmtpFfiClient,
1948        out: *mut *mut XmtpFfiHmacKeyMap,
1949    ) -> i32;
1950}
1951unsafe extern "C" {
1952    #[doc = " Process a raw welcome message received via push notification.\n Returns a list of conversation handles. Caller must free with [`xmtp_conversation_list_free`]."]
1953    pub fn xmtp_client_process_streamed_welcome_message(
1954        client: *const XmtpFfiClient,
1955        envelope_bytes: *const u8,
1956        envelope_bytes_len: i32,
1957        out: *mut *mut XmtpFfiConversationList,
1958    ) -> i32;
1959}
1960unsafe extern "C" {
1961    #[doc = " Get an enriched (decoded) message by its hex-encoded ID.\n Caller must free with [`xmtp_enriched_message_list_free`] (single-item list)."]
1962    pub fn xmtp_client_get_enriched_message_by_id(
1963        client: *const XmtpFfiClient,
1964        message_id: *const ::core::ffi::c_char,
1965        out: *mut *mut XmtpFfiEnrichedMessageList,
1966    ) -> i32;
1967}
1968unsafe extern "C" {
1969    #[doc = " Create a group without syncing members (optimistic / offline-capable).\n Caller must free with [`xmtp_conversation_free`]."]
1970    pub fn xmtp_client_create_group_optimistic(
1971        client: *const XmtpFfiClient,
1972        opts: *const XmtpFfiCreateGroupOptions,
1973        out: *mut *mut XmtpFfiConversation,
1974    ) -> i32;
1975}
1976unsafe extern "C" {
1977    #[doc = " Send a device sync request to retrieve records from another installation."]
1978    pub fn xmtp_device_sync_send_request(
1979        client: *const XmtpFfiClient,
1980        opts: *const XmtpFfiArchiveOptions,
1981        server_url: *const ::core::ffi::c_char,
1982    ) -> i32;
1983}
1984unsafe extern "C" {
1985    #[doc = " Send a sync archive to the sync group with the given pin."]
1986    pub fn xmtp_device_sync_send_archive(
1987        client: *const XmtpFfiClient,
1988        opts: *const XmtpFfiArchiveOptions,
1989        server_url: *const ::core::ffi::c_char,
1990        pin: *const ::core::ffi::c_char,
1991    ) -> i32;
1992}
1993unsafe extern "C" {
1994    #[doc = " Process a sync archive matching the given pin.\n Pass null for `pin` to process the latest archive."]
1995    pub fn xmtp_device_sync_process_archive(
1996        client: *const XmtpFfiClient,
1997        pin: *const ::core::ffi::c_char,
1998    ) -> i32;
1999}
2000unsafe extern "C" {
2001    #[doc = " List archives available for import in the sync group.\n `days_cutoff` limits how far back to look.\n Caller must free with [`xmtp_available_archive_list_free`]."]
2002    pub fn xmtp_device_sync_list_available_archives(
2003        client: *const XmtpFfiClient,
2004        days_cutoff: i64,
2005        out: *mut *mut XmtpFfiAvailableArchiveList,
2006    ) -> i32;
2007}
2008unsafe extern "C" {
2009    pub fn xmtp_available_archive_list_len(list: *const XmtpFfiAvailableArchiveList) -> i32;
2010}
2011unsafe extern "C" {
2012    #[doc = " Get the pin string at index. Returns a borrowed pointer; do NOT free."]
2013    pub fn xmtp_available_archive_pin(
2014        list: *const XmtpFfiAvailableArchiveList,
2015        index: i32,
2016    ) -> *const ::core::ffi::c_char;
2017}
2018unsafe extern "C" {
2019    #[doc = " Get the exported_at_ns at index."]
2020    pub fn xmtp_available_archive_exported_at_ns(
2021        list: *const XmtpFfiAvailableArchiveList,
2022        index: i32,
2023    ) -> i64;
2024}
2025unsafe extern "C" {
2026    #[doc = " Free an available archive list."]
2027    pub fn xmtp_available_archive_list_free(list: *mut XmtpFfiAvailableArchiveList);
2028}
2029unsafe extern "C" {
2030    #[doc = " Export an archive to a local file.\n `key` must be at least 32 bytes (encryption key)."]
2031    pub fn xmtp_device_sync_create_archive(
2032        client: *const XmtpFfiClient,
2033        path: *const ::core::ffi::c_char,
2034        opts: *const XmtpFfiArchiveOptions,
2035        key: *const u8,
2036        key_len: i32,
2037    ) -> i32;
2038}
2039unsafe extern "C" {
2040    #[doc = " Import a previously exported archive from a file.\n `key` must be at least 32 bytes (encryption key)."]
2041    pub fn xmtp_device_sync_import_archive(
2042        client: *const XmtpFfiClient,
2043        path: *const ::core::ffi::c_char,
2044        key: *const u8,
2045        key_len: i32,
2046    ) -> i32;
2047}
2048unsafe extern "C" {
2049    #[doc = " Read metadata from an archive file without loading its full contents.\n `out_elements` is a bitmask: bit 0 = Messages, bit 1 = Consent.\n `out_start_ns` / `out_end_ns` are 0 if not set. All output pointers are nullable."]
2050    pub fn xmtp_device_sync_archive_metadata(
2051        path: *const ::core::ffi::c_char,
2052        key: *const u8,
2053        key_len: i32,
2054        out_version: *mut u16,
2055        out_exported_at_ns: *mut i64,
2056        out_elements: *mut i32,
2057        out_start_ns: *mut i64,
2058        out_end_ns: *mut i64,
2059    ) -> i32;
2060}
2061unsafe extern "C" {
2062    #[doc = " Manually sync all device sync groups.\n Writes the number of synced/eligible groups to the output pointers."]
2063    pub fn xmtp_device_sync_sync_all(
2064        client: *const XmtpFfiClient,
2065        out_synced: *mut i32,
2066        out_eligible: *mut i32,
2067    ) -> i32;
2068}
2069unsafe extern "C" {
2070    #[doc = " Generate an inbox ID from an identifier. Caller must free with [`xmtp_free_string`].\n `nonce` defaults to 1 if 0 is passed."]
2071    pub fn xmtp_generate_inbox_id(
2072        identifier: *const ::core::ffi::c_char,
2073        identifier_kind: i32,
2074        nonce: u64,
2075    ) -> *mut ::core::ffi::c_char;
2076}
2077unsafe extern "C" {
2078    #[doc = " Check whether an installation (by its public key bytes) belongs to an inbox.\n Returns 1 = authorized, 0 = not authorized. Sets last error on failure."]
2079    pub fn xmtp_is_installation_authorized(
2080        api_url: *const ::core::ffi::c_char,
2081        is_secure: i32,
2082        inbox_id: *const ::core::ffi::c_char,
2083        installation_id: *const u8,
2084        installation_id_len: i32,
2085        out: *mut i32,
2086    ) -> i32;
2087}
2088unsafe extern "C" {
2089    #[doc = " Check whether an Ethereum address belongs to an inbox.\n Returns 1 = authorized, 0 = not authorized. Sets last error on failure."]
2090    pub fn xmtp_is_address_authorized(
2091        api_url: *const ::core::ffi::c_char,
2092        is_secure: i32,
2093        inbox_id: *const ::core::ffi::c_char,
2094        address: *const ::core::ffi::c_char,
2095        out: *mut i32,
2096    ) -> i32;
2097}
2098unsafe extern "C" {
2099    #[doc = " Get the inbox ID for an identifier by querying the network.\n `api_url` is the gRPC host, `is_secure` controls TLS.\n Writes the inbox ID to `out` (caller must free with [`xmtp_free_string`]).\n Writes null to `out` if no inbox ID is found."]
2100    pub fn xmtp_get_inbox_id_for_identifier(
2101        api_url: *const ::core::ffi::c_char,
2102        is_secure: i32,
2103        identifier: *const ::core::ffi::c_char,
2104        identifier_kind: i32,
2105        out: *mut *mut ::core::ffi::c_char,
2106    ) -> i32;
2107}
2108unsafe extern "C" {
2109    #[doc = " Create an inbox registration signature request (if needed).\n Returns null via `out` if no signature is needed.\n Caller must free with [`xmtp_signature_request_free`]."]
2110    pub fn xmtp_client_create_inbox_signature_request(
2111        client: *const XmtpFfiClient,
2112        out: *mut *mut XmtpFfiSignatureRequest,
2113    ) -> i32;
2114}
2115unsafe extern "C" {
2116    #[doc = " Create a signature request to add a new identifier.\n Caller must free with [`xmtp_signature_request_free`]."]
2117    pub fn xmtp_client_add_identifier_signature_request(
2118        client: *const XmtpFfiClient,
2119        identifier: *const ::core::ffi::c_char,
2120        identifier_kind: i32,
2121        out: *mut *mut XmtpFfiSignatureRequest,
2122    ) -> i32;
2123}
2124unsafe extern "C" {
2125    #[doc = " Create a signature request to revoke an identifier.\n Caller must free with [`xmtp_signature_request_free`]."]
2126    pub fn xmtp_client_revoke_identifier_signature_request(
2127        client: *const XmtpFfiClient,
2128        identifier: *const ::core::ffi::c_char,
2129        identifier_kind: i32,
2130        out: *mut *mut XmtpFfiSignatureRequest,
2131    ) -> i32;
2132}
2133unsafe extern "C" {
2134    #[doc = " Create a signature request to revoke all other installations.\n Returns null via `out` if there are no other installations.\n Caller must free with [`xmtp_signature_request_free`]."]
2135    pub fn xmtp_client_revoke_all_other_installations(
2136        client: *const XmtpFfiClient,
2137        out: *mut *mut XmtpFfiSignatureRequest,
2138    ) -> i32;
2139}
2140unsafe extern "C" {
2141    #[doc = " Get the human-readable signature text. Caller must free with [`xmtp_free_string`]."]
2142    pub fn xmtp_signature_request_text(
2143        req: *const XmtpFfiSignatureRequest,
2144    ) -> *mut ::core::ffi::c_char;
2145}
2146unsafe extern "C" {
2147    #[doc = " Add an ECDSA signature to the request."]
2148    pub fn xmtp_signature_request_add_ecdsa(
2149        req: *const XmtpFfiSignatureRequest,
2150        signature_bytes: *const u8,
2151        signature_len: i32,
2152    ) -> i32;
2153}
2154unsafe extern "C" {
2155    #[doc = " Add a passkey signature to the request.\n All four byte arrays are required and must not be null."]
2156    pub fn xmtp_signature_request_add_passkey(
2157        req: *const XmtpFfiSignatureRequest,
2158        public_key: *const u8,
2159        public_key_len: i32,
2160        signature: *const u8,
2161        signature_len: i32,
2162        authenticator_data: *const u8,
2163        authenticator_data_len: i32,
2164        client_data_json: *const u8,
2165        client_data_json_len: i32,
2166    ) -> i32;
2167}
2168unsafe extern "C" {
2169    #[doc = " Add a smart contract wallet (SCW) signature to the request.\n `account_address` is the EVM account address (hex string).\n `chain_id` is the EVM chain ID (e.g. 1 for mainnet).\n `block_number` is optional; pass 0 to omit."]
2170    pub fn xmtp_signature_request_add_scw(
2171        req: *const XmtpFfiSignatureRequest,
2172        account_address: *const ::core::ffi::c_char,
2173        signature_bytes: *const u8,
2174        signature_len: i32,
2175        chain_id: u64,
2176        block_number: u64,
2177    ) -> i32;
2178}
2179unsafe extern "C" {
2180    #[doc = " Apply a signature request to the client."]
2181    pub fn xmtp_client_apply_signature_request(
2182        client: *const XmtpFfiClient,
2183        req: *const XmtpFfiSignatureRequest,
2184    ) -> i32;
2185}
2186unsafe extern "C" {
2187    pub fn xmtp_signature_request_free(ptr: *mut XmtpFfiSignatureRequest);
2188}
2189unsafe extern "C" {
2190    #[doc = " Create a signature request to revoke specific installations by their IDs.\n `installation_ids` is an array of byte arrays, each `id_len` bytes long.\n Caller must free with [`xmtp_signature_request_free`]."]
2191    pub fn xmtp_client_revoke_installations_signature_request(
2192        client: *const XmtpFfiClient,
2193        installation_ids: *const *const u8,
2194        id_lengths: *const i32,
2195        count: i32,
2196        out: *mut *mut XmtpFfiSignatureRequest,
2197    ) -> i32;
2198}
2199unsafe extern "C" {
2200    #[doc = " Create a signature request to change the recovery identifier.\n Caller must free with [`xmtp_signature_request_free`]."]
2201    pub fn xmtp_client_change_recovery_identifier_signature_request(
2202        client: *const XmtpFfiClient,
2203        new_identifier: *const ::core::ffi::c_char,
2204        identifier_kind: i32,
2205        out: *mut *mut XmtpFfiSignatureRequest,
2206    ) -> i32;
2207}
2208unsafe extern "C" {
2209    #[doc = " Sign text with the client's installation key.\n Writes signature bytes to `out` and length to `out_len`.\n Caller must free `out` with [`xmtp_free_bytes`]."]
2210    pub fn xmtp_client_sign_with_installation_key(
2211        client: *const XmtpFfiClient,
2212        text: *const ::core::ffi::c_char,
2213        out: *mut *mut u8,
2214        out_len: *mut i32,
2215    ) -> i32;
2216}
2217unsafe extern "C" {
2218    #[doc = " Verify a signature produced by `sign_with_installation_key` using an\n arbitrary public key. Does not require a client handle.\n `signature_bytes` must be exactly 64 bytes, `public_key` must be exactly 32 bytes."]
2219    pub fn xmtp_verify_signed_with_public_key(
2220        signature_text: *const ::core::ffi::c_char,
2221        signature_bytes: *const u8,
2222        signature_len: i32,
2223        public_key: *const u8,
2224        public_key_len: i32,
2225    ) -> i32;
2226}
2227unsafe extern "C" {
2228    #[doc = " Stream new conversations. Callback receives owned `*mut FfiConversation` (caller must free).\n `on_close(error, ctx)`: null error = normal close; non-null = borrowed error string.\n Caller must end with `xmtp_stream_end` and free with `xmtp_stream_free`."]
2229    pub fn xmtp_stream_conversations(
2230        client: *const XmtpFfiClient,
2231        conversation_type: i32,
2232        callback: XmtpFnConversationCallback,
2233        on_close: ::core::option::Option<
2234            unsafe extern "C" fn(arg1: *const ::core::ffi::c_char, arg2: *mut ::core::ffi::c_void),
2235        >,
2236        context: *mut ::core::ffi::c_void,
2237        out: *mut *mut XmtpFfiStreamHandle,
2238    ) -> i32;
2239}
2240unsafe extern "C" {
2241    #[doc = " Stream all messages across conversations. Callback receives owned `*mut FfiMessage`.\n `consent_states` / `consent_states_count`: optional filter (null/0 = all)."]
2242    pub fn xmtp_stream_all_messages(
2243        client: *const XmtpFfiClient,
2244        conversation_type: i32,
2245        consent_states: *const i32,
2246        consent_states_count: i32,
2247        callback: XmtpFnMessageCallback,
2248        on_close: ::core::option::Option<
2249            unsafe extern "C" fn(arg1: *const ::core::ffi::c_char, arg2: *mut ::core::ffi::c_void),
2250        >,
2251        context: *mut ::core::ffi::c_void,
2252        out: *mut *mut XmtpFfiStreamHandle,
2253    ) -> i32;
2254}
2255unsafe extern "C" {
2256    #[doc = " Stream messages for a single conversation. Callback receives owned `*mut FfiMessage`."]
2257    pub fn xmtp_conversation_stream_messages(
2258        conv: *const XmtpFfiConversation,
2259        callback: XmtpFnMessageCallback,
2260        on_close: ::core::option::Option<
2261            unsafe extern "C" fn(arg1: *const ::core::ffi::c_char, arg2: *mut ::core::ffi::c_void),
2262        >,
2263        context: *mut ::core::ffi::c_void,
2264        out: *mut *mut XmtpFfiStreamHandle,
2265    ) -> i32;
2266}
2267unsafe extern "C" {
2268    #[doc = " Stream consent state changes. Callback receives a borrowed array of consent records\n (`*const FfiConsentRecord`) — valid only during the callback invocation."]
2269    pub fn xmtp_stream_consent(
2270        client: *const XmtpFfiClient,
2271        callback: XmtpFnConsentCallback,
2272        on_close: ::core::option::Option<
2273            unsafe extern "C" fn(arg1: *const ::core::ffi::c_char, arg2: *mut ::core::ffi::c_void),
2274        >,
2275        context: *mut ::core::ffi::c_void,
2276        out: *mut *mut XmtpFfiStreamHandle,
2277    ) -> i32;
2278}
2279unsafe extern "C" {
2280    #[doc = " Stream preference updates (consent changes + HMAC key rotations).\n Callback receives a borrowed array (`*const FfiPreferenceUpdate`) — valid only during callback."]
2281    pub fn xmtp_stream_preferences(
2282        client: *const XmtpFfiClient,
2283        callback: XmtpFnPreferenceCallback,
2284        on_close: ::core::option::Option<
2285            unsafe extern "C" fn(arg1: *const ::core::ffi::c_char, arg2: *mut ::core::ffi::c_void),
2286        >,
2287        context: *mut ::core::ffi::c_void,
2288        out: *mut *mut XmtpFfiStreamHandle,
2289    ) -> i32;
2290}
2291unsafe extern "C" {
2292    #[doc = " Stream message deletion events. Callback receives a borrowed hex message ID\n (`*const c_char`) — valid only during the callback invocation.\n Now includes `on_close` for API consistency with other stream functions."]
2293    pub fn xmtp_stream_message_deletions(
2294        client: *const XmtpFfiClient,
2295        callback: XmtpFnMessageDeletionCallback,
2296        on_close: ::core::option::Option<
2297            unsafe extern "C" fn(arg1: *const ::core::ffi::c_char, arg2: *mut ::core::ffi::c_void),
2298        >,
2299        context: *mut ::core::ffi::c_void,
2300        out: *mut *mut XmtpFfiStreamHandle,
2301    ) -> i32;
2302}
2303unsafe extern "C" {
2304    #[doc = " Signal a stream to stop. Does NOT free the handle — call `xmtp_stream_free` afterwards.\n Safe to call multiple times."]
2305    pub fn xmtp_stream_end(handle: *const XmtpFfiStreamHandle);
2306}
2307unsafe extern "C" {
2308    #[doc = " Check if a stream has finished. Returns 1 if closed, 0 if active."]
2309    pub fn xmtp_stream_is_closed(handle: *const XmtpFfiStreamHandle) -> i32;
2310}
2311unsafe extern "C" {
2312    #[doc = " Free a stream handle. Must be called after `xmtp_stream_end`.\n Calling this on an active (non-ended) stream will also end it."]
2313    pub fn xmtp_stream_free(handle: *mut XmtpFfiStreamHandle);
2314}