Skip to content

Commit

Permalink
WASM bindings update (#1643)
Browse files Browse the repository at this point in the history
* Update lint:clippy command

* Update ListConversationsOptions

* Add consent option to sync_all_conversations

* Add get_sync_group

* Add find_or_create_dm_by_inbox_id

* Add create_group_by_inbox_ids

* Return ConversationListItem from list methods

* Remove get_sync_group

* Refactor MessageDisappearingSettings

* Clippy fix

* Update version and changelog
  • Loading branch information
rygine authored Feb 18, 2025
1 parent c598672 commit fedd32e
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 37 deletions.
13 changes: 13 additions & 0 deletions bindings_wasm/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# @xmtp/wasm-bindings

## 0.0.15

- Added `consent_states`, `include_sync_groups`, and `include_duplicate_dms` to `ListConversationsOptions`
- Added `allowed_states` to `GroupQueryArgs`
- Refactored `MessageDisappearingSettings` struct
- Added `consent_states` options to `sync_all_conversations`
- Added `create_group_by_inbox_ids` method to `Conversations`
- Added `find_or_create_dm_by_inbox_id` method to `Conversations`
- Added `ConversationListItem` struct
- Updated `Conversations.list()` method to return `Vec<ConversationListItem>`
- Fixed invalid key package issues
- Fixed rate limiting issues

## 0.0.14

- Removed group pinned frame URL
Expand Down
4 changes: 2 additions & 2 deletions bindings_wasm/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@xmtp/wasm-bindings",
"version": "0.0.14",
"version": "0.0.15",
"type": "module",
"license": "MIT",
"description": "WASM bindings for the libXMTP rust library",
Expand Down Expand Up @@ -30,7 +30,7 @@
"clean:release": "rm -f ./dist/package.json",
"clean": "rm -rf ./dist",
"lint": "yarn lint:clippy && yarn lint:fmt",
"lint:clippy": "cargo clippy --all-features --target wasm32-unknown-unknown --no-deps -- -Dwarnings",
"lint:clippy": "cargo clippy --locked --all-features --target wasm32-unknown-unknown --no-deps -- -D warnings",
"lint:fmt": "cargo fmt --check",
"prepublishOnly": "yarn build",
"test": "wasm-pack test --chrome --headless"
Expand Down
18 changes: 1 addition & 17 deletions bindings_wasm/src/conversation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,12 @@ use xmtp_mls::storage::group_message::{GroupMessageKind as XmtpGroupMessageKind,
use xmtp_proto::xmtp::mls::message_contents::EncodedContent as XmtpEncodedContent;

use prost::Message as ProstMessage;
use xmtp_mls::groups::group_mutable_metadata::MessageDisappearingSettings as XmtpMessageDisappearingSettings;

#[wasm_bindgen]
pub struct GroupMetadata {
inner: XmtpGroupMetadata,
}

#[wasm_bindgen]
#[derive(Clone)]
pub struct MessageDisappearingSettings {
#[allow(dead_code)]
inner: XmtpMessageDisappearingSettings,
}

impl From<MessageDisappearingSettings> for XmtpMessageDisappearingSettings {
fn from(value: MessageDisappearingSettings) -> Self {
Self {
from_ns: value.inner.from_ns,
in_ns: value.inner.in_ns,
}
}
}

#[wasm_bindgen]
impl GroupMetadata {
#[wasm_bindgen(js_name = creatorInboxId)]
Expand Down Expand Up @@ -108,6 +91,7 @@ impl GroupMember {
}

#[wasm_bindgen]
#[derive(Clone)]
pub struct Conversation {
inner_client: Arc<RustXmtpClient>,
group_id: Vec<u8>,
Expand Down
187 changes: 169 additions & 18 deletions bindings_wasm/src/conversations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ use wasm_bindgen::{JsError, JsValue};
use xmtp_mls::groups::{
DMMetadataOptions, GroupMetadataOptions, HmacKey as XmtpHmacKey, PreconfiguredPolicies,
};
use xmtp_mls::storage::consent_record::ConsentState as XmtpConsentState;
use xmtp_mls::storage::group::ConversationType as XmtpConversationType;
use xmtp_mls::storage::group::GroupMembershipState as XmtpGroupMembershipState;
use xmtp_mls::storage::group::GroupQueryArgs;

use crate::conversation::MessageDisappearingSettings;
use crate::consent_state::ConsentState;
use crate::messages::Message;
use crate::permissions::{GroupPermissionsOptions, PermissionPolicySet};
use crate::streams::{StreamCallback, StreamCloser};
use crate::{client::RustXmtpClient, conversation::Conversation};

use xmtp_mls::groups::group_mutable_metadata::MessageDisappearingSettings as XmtpMessageDisappearingSettings;

#[wasm_bindgen]
#[derive(Debug, Clone)]
pub enum ConversationType {
Expand Down Expand Up @@ -76,50 +79,91 @@ impl From<GroupMembershipState> for XmtpGroupMembershipState {
pub struct ListConversationsOptions {
#[wasm_bindgen(js_name = allowedStates)]
pub allowed_states: Option<Vec<GroupMembershipState>>,
#[wasm_bindgen(js_name = consentStates)]
pub consent_states: Option<Vec<ConsentState>>,
#[wasm_bindgen(js_name = conversationType)]
pub conversation_type: Option<ConversationType>,
#[wasm_bindgen(js_name = createdAfterNs)]
pub created_after_ns: Option<i64>,
#[wasm_bindgen(js_name = createdBeforeNs)]
pub created_before_ns: Option<i64>,
#[wasm_bindgen(js_name = includeDuplicateDms)]
pub include_duplicate_dms: bool,
#[wasm_bindgen(js_name = includeSyncGroups)]
pub include_sync_groups: bool,
pub limit: Option<i64>,
}

impl From<ListConversationsOptions> for GroupQueryArgs {
fn from(opts: ListConversationsOptions) -> GroupQueryArgs {
GroupQueryArgs::default()
.maybe_allowed_states(
opts
.allowed_states
.map(|states| states.into_iter().map(From::from).collect()),
)
.maybe_conversation_type(opts.conversation_type.map(Into::into))
.maybe_created_after_ns(opts.created_after_ns)
.maybe_created_before_ns(opts.created_before_ns)
.maybe_limit(opts.limit)
GroupQueryArgs {
allowed_states: opts
.allowed_states
.map(|states| states.into_iter().map(From::from).collect()),
consent_states: opts
.consent_states
.map(|states| states.into_iter().map(From::from).collect()),
conversation_type: opts.conversation_type.map(Into::into),
created_after_ns: opts.created_after_ns,
created_before_ns: opts.created_before_ns,
include_duplicate_dms: opts.include_duplicate_dms,
include_sync_groups: opts.include_sync_groups,
limit: opts.limit,
}
}
}

#[wasm_bindgen]
impl ListConversationsOptions {
#[wasm_bindgen(constructor)]
#[allow(clippy::too_many_arguments)]
pub fn new(
allowed_states: Option<Vec<GroupMembershipState>>,
consent_states: Option<Vec<ConsentState>>,
conversation_type: Option<ConversationType>,
created_after_ns: Option<i64>,
created_before_ns: Option<i64>,
include_duplicate_dms: bool,
include_sync_groups: bool,
limit: Option<i64>,
) -> Self {
Self {
allowed_states,
consent_states,
conversation_type,
created_after_ns,
created_before_ns,
include_duplicate_dms,
include_sync_groups,
limit,
}
}
}

#[wasm_bindgen(getter_with_clone)]
#[derive(Clone)]
pub struct MessageDisappearingSettings {
pub from_ns: i64,
pub in_ns: i64,
}

impl From<MessageDisappearingSettings> for XmtpMessageDisappearingSettings {
fn from(value: MessageDisappearingSettings) -> Self {
Self {
from_ns: value.from_ns,
in_ns: value.in_ns,
}
}
}

#[wasm_bindgen]
impl MessageDisappearingSettings {
#[wasm_bindgen(constructor)]
pub fn new(from_ns: i64, in_ns: i64) -> Self {
Self { from_ns, in_ns }
}
}

#[wasm_bindgen(getter_with_clone)]
#[derive(Clone)]
pub struct CreateGroupOptions {
Expand Down Expand Up @@ -216,6 +260,24 @@ impl From<XmtpHmacKey> for HmacKey {
}
}

#[wasm_bindgen(getter_with_clone)]
pub struct ConversationListItem {
pub conversation: Conversation,
#[wasm_bindgen(js_name = lastMessage)]
pub last_message: Option<Message>,
}

#[wasm_bindgen]
impl ConversationListItem {
#[wasm_bindgen(constructor)]
pub fn new(conversation: Conversation, last_message: Option<Message>) -> Self {
Self {
conversation,
last_message,
}
}
}

#[wasm_bindgen]
pub struct Conversations {
inner_client: Arc<RustXmtpClient>,
Expand Down Expand Up @@ -296,6 +358,73 @@ impl Conversations {
Ok(convo.into())
}

#[wasm_bindgen(js_name = createGroupByInboxIds)]
pub async fn create_group_by_inbox_ids(
&self,
inbox_ids: Vec<String>,
options: Option<CreateGroupOptions>,
) -> Result<Conversation, JsError> {
let options = options.unwrap_or(CreateGroupOptions {
permissions: None,
group_name: None,
group_image_url_square: None,
group_description: None,
custom_permission_policy_set: None,
message_disappearing_settings: None,
});

if let Some(GroupPermissionsOptions::CustomPolicy) = options.permissions {
if options.custom_permission_policy_set.is_none() {
return Err(JsError::new("CustomPolicy must include policy set"));
}
} else if options.custom_permission_policy_set.is_some() {
return Err(JsError::new("Only CustomPolicy may specify a policy set"));
}

let metadata_options = options.clone().into_group_metadata_options();

let group_permissions = match options.permissions {
Some(GroupPermissionsOptions::Default) => {
Some(PreconfiguredPolicies::Default.to_policy_set())
}
Some(GroupPermissionsOptions::AdminOnly) => {
Some(PreconfiguredPolicies::AdminsOnly.to_policy_set())
}
Some(GroupPermissionsOptions::CustomPolicy) => {
if let Some(policy_set) = options.custom_permission_policy_set {
Some(
policy_set
.try_into()
.map_err(|e| JsError::new(format!("{}", e).as_str()))?,
)
} else {
None
}
}
_ => None,
};

let convo = if inbox_ids.is_empty() {
let group = self
.inner_client
.create_group(group_permissions, metadata_options)
.map_err(|e| JsError::new(format!("{}", e).as_str()))?;
group
.sync()
.await
.map_err(|e| JsError::new(format!("{}", e).as_str()))?;
group
} else {
self
.inner_client
.create_group_with_inbox_ids(&inbox_ids, group_permissions, metadata_options)
.await
.map_err(|e| JsError::new(format!("{}", e).as_str()))?
};

Ok(convo.into())
}

#[wasm_bindgen(js_name = createDm)]
pub async fn find_or_create_dm(
&self,
Expand All @@ -314,6 +443,24 @@ impl Conversations {
Ok(convo.into())
}

#[wasm_bindgen(js_name = createDmByInboxId)]
pub async fn find_or_create_dm_by_inbox_id(
&self,
inbox_id: String,
options: Option<CreateDMOptions>,
) -> Result<Conversation, JsError> {
let convo = self
.inner_client
.find_or_create_dm_by_inbox_id(
inbox_id,
options.unwrap_or_default().into_dm_metadata_options(),
)
.await
.map_err(|e| JsError::new(format!("{}", e).as_str()))?;

Ok(convo.into())
}

#[wasm_bindgen(js_name = findGroupById)]
pub fn find_group_by_id(&self, group_id: String) -> Result<Conversation, JsError> {
let group_id = hex::decode(group_id).map_err(|e| JsError::new(format!("{}", e).as_str()))?;
Expand Down Expand Up @@ -368,15 +515,20 @@ impl Conversations {
}

#[wasm_bindgen(js_name = syncAllConversations)]
pub async fn sync_all_conversations(&self) -> Result<usize, JsError> {
pub async fn sync_all_conversations(
&self,
consent_states: Option<Vec<ConsentState>>,
) -> Result<usize, JsError> {
let provider = self
.inner_client
.mls_provider()
.map_err(|e| JsError::new(format!("{}", e).as_str()))?;
let consents: Option<Vec<XmtpConsentState>> =
consent_states.map(|states| states.into_iter().map(|state| state.into()).collect());

let num_groups_synced = self
.inner_client
.sync_all_welcomes_and_groups(&provider, None)
.sync_all_welcomes_and_groups(&provider, consents)
.await
.map_err(|e| JsError::new(format!("{}", e).as_str()))?;

Expand All @@ -387,14 +539,13 @@ impl Conversations {
pub fn list(&self, opts: Option<ListConversationsOptions>) -> Result<js_sys::Array, JsError> {
let convo_list: js_sys::Array = self
.inner_client
.find_groups(opts.unwrap_or_default().into())
.list_conversations(opts.unwrap_or_default().into())
.map_err(|e| JsError::new(format!("{}", e).as_str()))?
.into_iter()
.map(|group| {
JsValue::from(Conversation::new(
self.inner_client.clone(),
group.group_id,
group.created_at_ns,
JsValue::from(ConversationListItem::new(
group.group.into(),
group.last_message.map(|m| m.into()),
))
})
.collect();
Expand Down

0 comments on commit fedd32e

Please sign in to comment.