diff --git a/bindings_wasm/Cargo.toml b/bindings_wasm/Cargo.toml index 2cb631a35..dab1589ef 100644 --- a/bindings_wasm/Cargo.toml +++ b/bindings_wasm/Cargo.toml @@ -21,8 +21,15 @@ xmtp_id = { path = "../xmtp_id" } xmtp_mls = { path = "../xmtp_mls", features = [ "message-history", "test-utils", + "http-api" ] } xmtp_proto = { path = "../xmtp_proto", features = ["proto_full"] } [dev-dependencies] wasm-bindgen-test.workspace = true +xmtp_mls = { path = "../xmtp_mls", features = [ + "message-history", + "test-utils", + "http-api" +] } + diff --git a/bindings_wasm/src/groups.rs b/bindings_wasm/src/groups.rs index 91578677c..7876e27ca 100644 --- a/bindings_wasm/src/groups.rs +++ b/bindings_wasm/src/groups.rs @@ -84,16 +84,13 @@ impl WasmGroup { pub async fn send(&self, encoded_content: WasmEncodedContent) -> Result { let encoded_content: EncodedContent = encoded_content.into(); let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); let message_id = group - .send_message( - encoded_content.encode_to_vec().as_slice(), - &self.inner_client, - ) + .send_message(encoded_content.encode_to_vec().as_slice()) .await .map_err(|e| JsError::new(&format!("{e}")))?; Ok(hex::encode(message_id.clone())) @@ -104,7 +101,7 @@ impl WasmGroup { pub fn send_optimistic(&self, encoded_content: WasmEncodedContent) -> Result { let encoded_content: EncodedContent = encoded_content.into(); let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -120,12 +117,12 @@ impl WasmGroup { #[wasm_bindgen] pub async fn publish_messages(&self) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .publish_messages(&self.inner_client) + .publish_messages() .await .map_err(|e| JsError::new(&format!("{e}")))?; Ok(()) @@ -134,13 +131,13 @@ impl WasmGroup { #[wasm_bindgen] pub async fn sync(&self) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .sync(&self.inner_client) + .sync() .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -163,7 +160,7 @@ impl WasmGroup { }; let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -189,13 +186,13 @@ impl WasmGroup { #[wasm_bindgen] pub async fn list_members(&self) -> Result { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); let members: Vec = group - .members(&self.inner_client) + .members() .await .map_err(|e| JsError::new(&format!("{e}")))? .into_iter() @@ -222,7 +219,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn admin_list(&self) -> Result, JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -241,7 +238,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn super_admin_list(&self) -> Result, JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -272,13 +269,13 @@ impl WasmGroup { #[wasm_bindgen] pub async fn add_members(&self, account_addresses: Vec) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .add_members(&self.inner_client, account_addresses) + .add_members(account_addresses) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -288,12 +285,12 @@ impl WasmGroup { #[wasm_bindgen] pub async fn add_admin(&self, inbox_id: String) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .update_admin_list(&self.inner_client, UpdateAdminListType::Add, inbox_id) + .update_admin_list(UpdateAdminListType::Add, inbox_id) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -303,12 +300,12 @@ impl WasmGroup { #[wasm_bindgen] pub async fn remove_admin(&self, inbox_id: String) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .update_admin_list(&self.inner_client, UpdateAdminListType::Remove, inbox_id) + .update_admin_list(UpdateAdminListType::Remove, inbox_id) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -318,12 +315,12 @@ impl WasmGroup { #[wasm_bindgen] pub async fn add_super_admin(&self, inbox_id: String) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .update_admin_list(&self.inner_client, UpdateAdminListType::AddSuper, inbox_id) + .update_admin_list(UpdateAdminListType::AddSuper, inbox_id) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -333,16 +330,12 @@ impl WasmGroup { #[wasm_bindgen] pub async fn remove_super_admin(&self, inbox_id: String) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .update_admin_list( - &self.inner_client, - UpdateAdminListType::RemoveSuper, - inbox_id, - ) + .update_admin_list(UpdateAdminListType::RemoveSuper, inbox_id) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -352,7 +345,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn group_permissions(&self) -> Result { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -367,13 +360,13 @@ impl WasmGroup { #[wasm_bindgen] pub async fn add_members_by_inbox_id(&self, inbox_ids: Vec) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .add_members_by_inbox_id(&self.inner_client, inbox_ids) + .add_members_by_inbox_id(inbox_ids) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -383,13 +376,13 @@ impl WasmGroup { #[wasm_bindgen] pub async fn remove_members(&self, account_addresses: Vec) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .remove_members(&self.inner_client, account_addresses) + .remove_members(account_addresses) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -399,13 +392,13 @@ impl WasmGroup { #[wasm_bindgen] pub async fn remove_members_by_inbox_id(&self, inbox_ids: Vec) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .remove_members_by_inbox_id(&self.inner_client, inbox_ids) + .remove_members_by_inbox_id(inbox_ids) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -415,13 +408,13 @@ impl WasmGroup { #[wasm_bindgen] pub async fn update_group_name(&self, group_name: String) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .update_group_name(&self.inner_client, group_name) + .update_group_name(group_name) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -431,7 +424,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn group_name(&self) -> Result { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -453,13 +446,13 @@ impl WasmGroup { group_image_url_square: String, ) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .update_group_image_url_square(&self.inner_client, group_image_url_square) + .update_group_image_url_square(group_image_url_square) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -469,7 +462,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn group_image_url_square(&self) -> Result { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -488,13 +481,13 @@ impl WasmGroup { #[wasm_bindgen] pub async fn update_group_description(&self, group_description: String) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .update_group_description(&self.inner_client, group_description) + .update_group_description(group_description) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -504,7 +497,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn group_description(&self) -> Result { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -526,13 +519,13 @@ impl WasmGroup { pinned_frame_url: String, ) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); group - .update_group_pinned_frame_url(&self.inner_client, pinned_frame_url) + .update_group_pinned_frame_url(pinned_frame_url) .await .map_err(|e| JsError::new(&format!("{e}")))?; @@ -542,7 +535,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn group_pinned_frame_url(&self) -> Result { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -566,7 +559,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn is_active(&self) -> Result { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -583,7 +576,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn added_by_inbox_id(&self) -> Result { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -596,7 +589,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn group_metadata(&self) -> Result { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -615,7 +608,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn consent_state(&self) -> Result { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); @@ -630,7 +623,7 @@ impl WasmGroup { #[wasm_bindgen] pub fn update_consent_state(&self, state: WasmConsentState) -> Result<(), JsError> { let group = MlsGroup::new( - self.inner_client.context().clone(), + self.inner_client.clone(), self.group_id.clone(), self.created_at_ns, ); diff --git a/bindings_wasm/src/mls_client.rs b/bindings_wasm/src/mls_client.rs index e396afd69..09f3c343d 100644 --- a/bindings_wasm/src/mls_client.rs +++ b/bindings_wasm/src/mls_client.rs @@ -249,13 +249,7 @@ impl WasmClient { let signature = UnverifiedSignature::new_recoverable_ecdsa(signature_bytes.to_vec()); signature_request - .add_signature( - signature, - self - .inner_client - .smart_contract_signature_verifier() - .as_ref(), - ) + .add_signature(signature, self.inner_client.scw_verifier()) .await .map_err(|e| JsError::new(format!("{}", e).as_str()))?; } else { diff --git a/examples/cli/cli-client.rs b/examples/cli/cli-client.rs index 1bee113aa..4c2b3126f 100755 --- a/examples/cli/cli-client.rs +++ b/examples/cli/cli-client.rs @@ -39,7 +39,7 @@ use xmtp_mls::{ builder::ClientBuilderError, client::ClientError, codecs::{text::TextCodec, ContentCodec}, - groups::{message_history::MessageHistoryUrls, GroupMetadataOptions, MlsGroup}, + groups::{message_history::MessageHistoryUrls, GroupMetadataOptions}, identity::IdentityStrategy, storage::{ group_message::StoredGroupMessage, EncryptedMessageStore, EncryptionKey, StorageError, @@ -50,6 +50,7 @@ use xmtp_mls::{ }; type Client = xmtp_mls::client::Client; type ClientBuilder = xmtp_mls::builder::ClientBuilder; +type MlsGroup = xmtp_mls::groups::MlsGroup; /// A fictional versioning CLI #[derive(Debug, Parser)] // requires `derive` feature @@ -213,12 +214,12 @@ async fn main() { .find_groups(FindGroupParams::default()) .expect("failed to list groups"); for group in group_list.iter() { - group.sync(&client).await.expect("error syncing group"); + group.sync().await.expect("error syncing group"); } let serializable_group_list = group_list .iter() - .map(|g| SerializableGroup::from(g, &client)) + .map(SerializableGroup::from) .collect::>(); let serializable_group_list = join_all(serializable_group_list).await; @@ -239,7 +240,7 @@ async fn main() { let group = get_group(&client, hex::decode(group_id).expect("group id decode")) .await .expect("failed to get group"); - send(group, msg.clone(), &client).await.unwrap(); + send(group, msg.clone()).await.unwrap(); info!("sent message", { command_output: true, group_id: group_id, message: msg }); } Commands::ListGroupMessages { group_id } => { @@ -282,7 +283,7 @@ async fn main() { .expect("failed to get group"); group - .add_members(&client, account_addresses.clone()) + .add_members(account_addresses.clone()) .await .expect("failed to add member"); @@ -304,7 +305,7 @@ async fn main() { .expect("failed to get group"); group - .remove_members(&client, account_addresses.clone()) + .remove_members(account_addresses.clone()) .await .expect("failed to add member"); @@ -340,8 +341,8 @@ async fn main() { let group = &client .group(hex::decode(group_id).expect("bad group id")) .expect("group not found"); - group.sync(&client).await.unwrap(); - let serializable = SerializableGroup::from(group, &client).await; + group.sync().await.unwrap(); + let serializable = SerializableGroup::from(group).await; info!("Group {}", group_id, { command_output: true, group_id: group_id, group_info: make_value(&serializable) }) } Commands::RequestHistorySync {} => { @@ -383,7 +384,7 @@ async fn main() { client.enable_history_sync().await.unwrap(); let group = client.get_sync_group().unwrap(); let group_id_str = hex::encode(group.group_id.clone()); - group.sync(&client).await.unwrap(); + group.sync().await.unwrap(); let messages = group .find_messages(Some(GroupMessageKind::Application), None, None, None, None) .unwrap(); @@ -468,10 +469,7 @@ async fn register(cli: &Cli, maybe_seed_phrase: Option) -> Result<(), Cl let signature = UnverifiedSignature::RecoverableEcdsa(UnverifiedRecoverableEcdsaSignature::new(sig_bytes)); signature_request - .add_signature( - signature, - client.smart_contract_signature_verifier().as_ref(), - ) + .add_signature(signature, client.scw_verifier()) .await .unwrap(); @@ -488,20 +486,20 @@ async fn get_group(client: &Client, group_id: Vec) -> Result Result<(), CliError> { +async fn send(group: MlsGroup, msg: String) -> Result<(), CliError> { let mut buf = Vec::new(); TextCodec::encode(msg.clone()) .unwrap() .encode(&mut buf) .unwrap(); - group.send_message(buf.as_slice(), client).await.unwrap(); + group.send_message(buf.as_slice()).await.unwrap(); Ok(()) } diff --git a/examples/cli/serializable.rs b/examples/cli/serializable.rs index 9153e0345..a8c8d6a6a 100644 --- a/examples/cli/serializable.rs +++ b/examples/cli/serializable.rs @@ -22,13 +22,12 @@ pub struct SerializableGroup { } impl SerializableGroup { - pub async fn from( - group: &MlsGroup, - client: &xmtp_mls::Client, + pub async fn from( + group: &MlsGroup>, ) -> Self { let group_id = hex::encode(group.group_id.clone()); let members = group - .members(client) + .members() .await .expect("could not load members") .into_iter() diff --git a/mls_validation_service/src/handlers.rs b/mls_validation_service/src/handlers.rs index 0d6188a45..b48b1ad7b 100644 --- a/mls_validation_service/src/handlers.rs +++ b/mls_validation_service/src/handlers.rs @@ -62,7 +62,7 @@ pub struct ValidationService { } impl ValidationService { - pub fn new(scw_verifier: impl SmartContractSignatureVerifier) -> Self { + pub fn new(scw_verifier: impl SmartContractSignatureVerifier + 'static) -> Self { Self { scw_verifier: Box::new(scw_verifier), } @@ -125,7 +125,7 @@ impl ValidationApi for ValidationService { new_updates, } = request.into_inner(); - get_association_state(old_updates, new_updates, self.scw_verifier.as_ref()) + get_association_state(old_updates, new_updates, &self.scw_verifier) .await .map(Response::new) .map_err(Into::into) @@ -137,7 +137,7 @@ impl ValidationApi for ValidationService { ) -> Result, Status> { let VerifySmartContractWalletSignaturesRequest { signatures } = request.into_inner(); - verify_smart_contract_wallet_signatures(signatures, self.scw_verifier.as_ref()).await + verify_smart_contract_wallet_signatures(signatures, &self.scw_verifier).await } async fn validate_inbox_id_key_packages( @@ -201,16 +201,17 @@ async fn validate_inbox_id_key_package( async fn verify_smart_contract_wallet_signatures( signatures: Vec, - scw_verifier: &dyn SmartContractSignatureVerifier, + scw_verifier: impl SmartContractSignatureVerifier, ) -> Result, Status> { let mut responses = vec![]; for signature in signatures { + let verifier = &scw_verifier; let handle = async move { let account_id = signature.account_id.try_into().map_err(|_e| { GrpcServerError::Deserialization(DeserializationError::InvalidAccountId) })?; - let response = scw_verifier + let response = verifier .is_valid_signature( account_id, signature.hash.try_into().map_err(|_| { @@ -255,7 +256,7 @@ async fn verify_smart_contract_wallet_signatures( async fn get_association_state( old_updates: Vec, new_updates: Vec, - scw_verifier: &dyn SmartContractSignatureVerifier, + scw_verifier: impl SmartContractSignatureVerifier, ) -> Result { let old_unverified_updates: Vec = try_map_vec(old_updates)?; let new_unverified_updates: Vec = try_map_vec(new_updates)?; @@ -263,13 +264,13 @@ async fn get_association_state( let old_updates = try_join_all( old_unverified_updates .iter() - .map(|u| u.to_verified(scw_verifier)), + .map(|u| u.to_verified(&scw_verifier)), ) .await?; let new_updates = try_join_all( new_unverified_updates .iter() - .map(|u| u.to_verified(scw_verifier)), + .map(|u| u.to_verified(&scw_verifier)), ) .await?; if old_updates.is_empty() { diff --git a/mls_validation_service/src/main.rs b/mls_validation_service/src/main.rs index dedcbc540..5df5db0c1 100644 --- a/mls_validation_service/src/main.rs +++ b/mls_validation_service/src/main.rs @@ -30,7 +30,7 @@ async fn main() -> Result<(), Box> { let health_server = health_check_server(args.health_check_port as u16); - let scw_verifier = MultiSmartContractSignatureVerifier::new_from_file("chain_urls.json"); + let scw_verifier = MultiSmartContractSignatureVerifier::new_from_file("chain_urls.json")?; let grpc_server = Server::builder() .add_service(ValidationApiServer::new(ValidationService::new( diff --git a/xmtp_api_grpc/src/lib.rs b/xmtp_api_grpc/src/lib.rs index 57b1f9413..265f6f107 100644 --- a/xmtp_api_grpc/src/lib.rs +++ b/xmtp_api_grpc/src/lib.rs @@ -10,7 +10,7 @@ pub use grpc_api_helper::{Client, GroupMessageStream, WelcomeMessageStream}; mod utils { #[cfg(feature = "test-utils")] mod test { - use xmtp_proto::api_client::trait_impls::XmtpTestClient; + use xmtp_proto::api_client::XmtpTestClient; impl XmtpTestClient for crate::Client { async fn create_local() -> Self { diff --git a/xmtp_api_http/Cargo.toml b/xmtp_api_http/Cargo.toml index 1becdc165..ff5035fb4 100644 --- a/xmtp_api_http/Cargo.toml +++ b/xmtp_api_http/Cargo.toml @@ -17,6 +17,9 @@ thiserror = "1.0" tokio = { workspace = true, features = ["sync", "rt", "macros"] } xmtp_proto = { path = "../xmtp_proto", features = ["proto_full"] } +[dev-dependencies] +xmtp_proto = { path = "../xmtp_proto", features = ["test-utils"] } + [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] } @@ -25,4 +28,4 @@ tokio = { workspace = true, features = ["macros", "time"] } wasm-bindgen-test.workspace = true [features] -test-utils = [] +test-utils = ["xmtp_proto/test-utils"] diff --git a/xmtp_api_http/src/util.rs b/xmtp_api_http/src/util.rs index 412d602c8..f8d2b3b11 100644 --- a/xmtp_api_http/src/util.rs +++ b/xmtp_api_http/src/util.rs @@ -5,7 +5,7 @@ use futures::{ use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::Deserializer; use std::io::Read; -use xmtp_proto::api_client::{trait_impls::XmtpTestClient, Error, ErrorKind}; +use xmtp_proto::api_client::{Error, ErrorKind}; #[derive(Deserialize, Serialize, Debug)] #[serde(untagged)] @@ -117,7 +117,7 @@ pub fn create_grpc_stream_inner< } #[cfg(feature = "test-utils")] -impl XmtpTestClient for crate::XmtpHttpApiClient { +impl xmtp_proto::api_client::XmtpTestClient for crate::XmtpHttpApiClient { async fn create_local() -> Self { crate::XmtpHttpApiClient::new("http://localhost:5555".into()) .expect("could not create client") diff --git a/xmtp_id/src/lib.rs b/xmtp_id/src/lib.rs index 2a7d7ea09..9c1b7b034 100755 --- a/xmtp_id/src/lib.rs +++ b/xmtp_id/src/lib.rs @@ -60,8 +60,23 @@ impl InboxOwner for LocalWallet { } } +impl InboxOwner for &T +where + T: InboxOwner, +{ + fn get_address(&self) -> String { + (**self).get_address() + } + + fn sign(&self, text: &str) -> Result { + (**self).sign(text) + } +} + #[cfg(test)] mod tests { + #![allow(clippy::unwrap_used)] + use ethers::contract::abigen; #[cfg(target_arch = "wasm32")] diff --git a/xmtp_id/src/scw_verifier/chain_rpc_verifier.rs b/xmtp_id/src/scw_verifier/chain_rpc_verifier.rs index 9c036bedf..d467bead3 100644 --- a/xmtp_id/src/scw_verifier/chain_rpc_verifier.rs +++ b/xmtp_id/src/scw_verifier/chain_rpc_verifier.rs @@ -32,9 +32,9 @@ pub struct RpcSmartContractWalletVerifier { } impl RpcSmartContractWalletVerifier { - pub fn new(url: String) -> Self { - let provider = Arc::new(Provider::::try_from(url).unwrap()); - Self { provider } + pub fn new(url: String) -> Result { + let provider = Arc::new(Provider::::try_from(url)?); + Ok(Self { provider }) } } @@ -55,7 +55,7 @@ impl SmartContractSignatureVerifier for RpcSmartContractWalletVerifier { signature: Bytes, block_number: Option, ) -> Result { - let code = hex::decode(VALIDATE_SIG_OFFCHAIN_BYTECODE).unwrap(); + let code = hex::decode(VALIDATE_SIG_OFFCHAIN_BYTECODE)?; let account_address: Address = signer .account_address .parse() @@ -113,6 +113,7 @@ impl SmartContractSignatureVerifier for RpcSmartContractWalletVerifier { // because its a wrapper over the system-binary #[cfg(all(test, not(target_arch = "wasm32")))] pub(crate) mod tests { + #![allow(clippy::unwrap_used)] use crate::is_smart_contract; use super::*; @@ -227,7 +228,7 @@ pub(crate) mod tests { ); let hash: [u8; 32] = H256::random().into(); let replay_safe_hash = smart_wallet.replay_safe_hash(hash).call().await.unwrap(); - let verifier = RpcSmartContractWalletVerifier::new(anvil.endpoint()); + let verifier = RpcSmartContractWalletVerifier::new(anvil.endpoint()).unwrap(); // verify owner0 is a valid owner let sig0 = owner0.sign_hash(replay_safe_hash.into()).unwrap(); @@ -359,7 +360,7 @@ pub(crate) mod tests { ])]) .into(); - let verifier = RpcSmartContractWalletVerifier::new(anvil.endpoint()); + let verifier = RpcSmartContractWalletVerifier::new(anvil.endpoint()).unwrap(); let account_id = AccountId::new_evm(anvil.chain_id(), format!("{:?}", smart_wallet_address)); @@ -425,7 +426,8 @@ pub(crate) mod tests { let hash = hash_message(hash); let signature = Bytes::from_hex("0x000000000000000000000000bf07a0df119ca234634588fbdb5625594e2a5bca00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000038449c81579000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000004836a472ab1dd406ecb8d0f933a985541ee3921f0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000007a7f00000000000000000000000000000000000000000000000000000000000000017f7f0f292b79d9ce101861526459da50f62368077ae24affe97b792bf4bdd2e171553d602d80604d3d3981f3363d3d373d3d3d363d732a2b85eb1054d6f0c6c2e37da05ed3e5fea684ef5af43d82803e903d91602b57fd5bf300000000000000000000000000000000000000000000000000000000000000000000000002246171d1c9000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000004836a472ab1dd406ecb8d0f933a985541ee3921f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000942f9ce5d9a33a82f88d233aeb3292e6802303480000000000000000000000000000000000000000000000000014c3c6ef1cdc01000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042f2eaaebf45fc0340eb55f11c52a30e2ca7f48539d0a1f1cdc240482210326494545def903e8ed4441bd5438109abe950f1f79baf032f184728ba2d4161dea32e1b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042c0f8db6019888d87a0afc1299e81ef45d3abce64f63072c8d7a6ef00f5f82c1522958ff110afa98b8c0d23b558376db1d2fbab4944e708f8bf6dc7b977ee07201b000000000000000000000000000000000000000000000000000000000000006492649264926492649264926492649264926492649264926492649264926492").unwrap(); - let verifier = RpcSmartContractWalletVerifier::new("https://polygon-rpc.com".to_string()); + let verifier = + RpcSmartContractWalletVerifier::new("https://polygon-rpc.com".to_string()).unwrap(); assert!( verifier .is_valid_signature(AccountId::new_evm(1, signer), hash.into(), signature, None) diff --git a/xmtp_id/src/scw_verifier/mod.rs b/xmtp_id/src/scw_verifier/mod.rs index f11fb59da..83fe780dd 100644 --- a/xmtp_id/src/scw_verifier/mod.rs +++ b/xmtp_id/src/scw_verifier/mod.rs @@ -30,6 +30,12 @@ pub enum VerifierError { Provider(#[from] ethers::providers::ProviderError), #[error(transparent)] ApiClient(#[from] xmtp_proto::api_client::Error), + #[error(transparent)] + Url(#[from] url::ParseError), + #[error(transparent)] + Io(#[from] std::io::Error), + #[error(transparent)] + Serde(#[from] serde_json::Error), } #[cfg(not(target_arch = "wasm32"))] @@ -104,45 +110,38 @@ pub struct MultiSmartContractSignatureVerifier { } impl MultiSmartContractSignatureVerifier { - pub fn new(urls: HashMap) -> Self { + pub fn new(urls: HashMap) -> Result { let verifiers = urls .into_iter() .map(|(chain_id, url)| { - ( + Ok::<_, VerifierError>(( chain_id, - Box::new(RpcSmartContractWalletVerifier::new(url.to_string())) + Box::new(RpcSmartContractWalletVerifier::new(url.to_string())?) as Box, - ) + )) }) - .collect(); + .collect::, _>>()?; - Self { verifiers } + Ok(Self { verifiers }) } - pub fn new_from_file(path: impl AsRef) -> Self { + pub fn new_from_file(path: impl AsRef) -> Result { let path = path.as_ref(); let file_str; let json = if path.exists() { - file_str = fs::read_to_string(path).unwrap_or_else(|_| panic!("{path:?} is missing")); + file_str = fs::read_to_string(path)?; &file_str } else { DEFAULT_CHAIN_URLS }; - let json: HashMap = - serde_json::from_str(json).unwrap_or_else(|_| panic!("{path:?} is malformatted")); + let json: HashMap = serde_json::from_str(json)?; let urls = json .into_iter() - .map(|(id, url)| { - ( - id, - Url::from_str(&url) - .unwrap_or_else(|_| panic!("unable to parse url in {path:?} ({url})")), - ) - }) - .collect(); + .map(|(id, url)| Ok::<_, VerifierError>((id, Url::from_str(&url)?))) + .collect::>()?; Self::new(urls) } diff --git a/xmtp_id/src/scw_verifier/remote_signature_verifier.rs b/xmtp_id/src/scw_verifier/remote_signature_verifier.rs index 0b74947f0..1c0d3fce5 100644 --- a/xmtp_id/src/scw_verifier/remote_signature_verifier.rs +++ b/xmtp_id/src/scw_verifier/remote_signature_verifier.rs @@ -55,7 +55,7 @@ where impl Clone for RemoteSignatureVerifier where - T: Clone + ?Sized, + T: Clone, { fn clone(&self) -> Self { Self { diff --git a/xmtp_mls/Cargo.toml b/xmtp_mls/Cargo.toml index 483894f14..be11c2ac2 100644 --- a/xmtp_mls/Cargo.toml +++ b/xmtp_mls/Cargo.toml @@ -10,7 +10,7 @@ targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown", "aarch64-apple- [features] default = ["grpc-api"] -test-utils = ["xmtp_id/test-utils", "tracing-subscriber", "dep:tracing-wasm", "dep:console_error_panic_hook"] +test-utils = ["tracing-subscriber", "dep:tracing-wasm", "dep:console_error_panic_hook", "xmtp_id/test-utils", "xmtp_proto/test-utils", "xmtp_api_http/test-utils", "xmtp_api_grpc/test-utils"] bench = ["test-utils", "indicatif", "tracing-subscriber", "anyhow", "tracing-flame", "once_cell", "dep:xmtp_api_grpc", "criterion"] update-schema = ["toml"] http-api = ["dep:xmtp_api_http"] @@ -128,7 +128,10 @@ required-features = ["update-schema"] [[bench]] name = "group_limit" harness = false +required-features = ["bench"] [[bench]] name = "crypto" harness = false +required-features = ["bench"] + diff --git a/xmtp_mls/benches/group_limit.rs b/xmtp_mls/benches/group_limit.rs index 7319f5364..d2466a02b 100755 --- a/xmtp_mls/benches/group_limit.rs +++ b/xmtp_mls/benches/group_limit.rs @@ -40,11 +40,11 @@ fn setup() -> (Arc, Vec, Runtime) { tracing::info!("Using Dev GRPC"); Arc::new(ClientBuilder::new_dev_client(&wallet).await) } else { - Arc::new(ClientBuilder::new_test_client(&wallet).await) + Arc::new(ClientBuilder::new_local_client(&wallet).await) }; let identities: Vec = - create_identities_if_dont_exist(MAX_IDENTITIES, &client, is_dev_network).await; + create_identities_if_dont_exist(MAX_IDENTITIES, client.as_ref(), is_dev_network).await; (client, identities) }); @@ -84,7 +84,6 @@ fn add_to_empty_group(c: &mut Criterion) { b.to_async(&runtime).iter_batched( || { ( - client.clone(), client .create_group(None, GroupMetadataOptions::default()) .unwrap(), @@ -92,12 +91,8 @@ fn add_to_empty_group(c: &mut Criterion) { span.clone(), ) }, - |(client, group, addrs, span)| async move { - group - .add_members(&client, addrs) - .instrument(span) - .await - .unwrap(); + |(group, addrs, span)| async move { + group.add_members(addrs).instrument(span).await.unwrap(); }, BatchSize::SmallInput, ); @@ -127,7 +122,6 @@ fn add_to_empty_group_by_inbox_id(c: &mut Criterion) { b.to_async(&runtime).iter_batched( || { ( - client.clone(), client .create_group(None, GroupMetadataOptions::default()) .unwrap(), @@ -135,9 +129,9 @@ fn add_to_empty_group_by_inbox_id(c: &mut Criterion) { ids.clone(), ) }, - |(client, group, span, ids)| async move { + |(group, span, ids)| async move { group - .add_members_by_inbox_id(&client, ids) + .add_members_by_inbox_id(ids) .instrument(span) .await .unwrap(); @@ -176,7 +170,6 @@ fn add_to_100_member_group_by_inbox_id(c: &mut Criterion) { .unwrap(); group .add_members_by_inbox_id( - &client, // it is OK to take from the back for now because we aren't getting // near MAX_IDENTITIES inbox_ids.iter().rev().take(100).cloned().collect(), @@ -184,12 +177,12 @@ fn add_to_100_member_group_by_inbox_id(c: &mut Criterion) { .await .unwrap(); - (client.clone(), group, span.clone(), ids.clone()) + (group, span.clone(), ids.clone()) }) }, - |(client, group, span, ids)| async move { + |(group, span, ids)| async move { group - .add_members_by_inbox_id(&client, ids) + .add_members_by_inbox_id(ids) .instrument(span) .await .unwrap(); @@ -226,16 +219,13 @@ fn remove_all_members_from_group(c: &mut Criterion) { let group = client .create_group(None, GroupMetadataOptions::default()) .unwrap(); - group - .add_members_by_inbox_id(&client, ids.clone()) - .await - .unwrap(); - (client.clone(), group, span.clone(), ids.clone()) + group.add_members_by_inbox_id(ids.clone()).await.unwrap(); + (group, span.clone(), ids.clone()) }) }, - |(client, group, span, ids)| async move { + |(group, span, ids)| async move { group - .remove_members_by_inbox_id(&client, ids) + .remove_members_by_inbox_id(ids) .instrument(span) .await .unwrap(); @@ -272,21 +262,13 @@ fn remove_half_members_from_group(c: &mut Criterion) { let group = client .create_group(None, GroupMetadataOptions::default()) .unwrap(); - group - .add_members_by_inbox_id(&client, ids.clone()) - .await - .unwrap(); - ( - client.clone(), - group, - span.clone(), - ids[0..(size / 2)].into(), - ) + group.add_members_by_inbox_id(ids.clone()).await.unwrap(); + (group, span.clone(), ids[0..(size / 2)].into()) }) }, - |(client, group, span, ids)| async move { + |(group, span, ids)| async move { group - .remove_members_by_inbox_id(&client, ids) + .remove_members_by_inbox_id(ids) .instrument(span) .await .unwrap(); @@ -323,17 +305,14 @@ fn add_1_member_to_group(c: &mut Criterion) { let group = client .create_group(None, GroupMetadataOptions::default()) .unwrap(); - group - .add_members_by_inbox_id(&client, ids.clone()) - .await - .unwrap(); + group.add_members_by_inbox_id(ids.clone()).await.unwrap(); let member = inbox_ids.last().unwrap().clone(); - (client.clone(), group, vec![member], span.clone()) + (group, vec![member], span.clone()) }) }, - |(client, group, member, span)| async move { + |(group, member, span)| async move { group - .add_members_by_inbox_id(&client, member) + .add_members_by_inbox_id(member) .instrument(span) .await .unwrap(); diff --git a/xmtp_mls/src/api/test_utils.rs b/xmtp_mls/src/api/test_utils.rs index d71e97d9d..09e58743a 100644 --- a/xmtp_mls/src/api/test_utils.rs +++ b/xmtp_mls/src/api/test_utils.rs @@ -23,7 +23,7 @@ use xmtp_proto::{ #[cfg(any(feature = "http-api", target_arch = "wasm32"))] use xmtp_proto::xmtp::mls::api::v1::WelcomeMessage; -use crate::XmtpTestClient; +use xmtp_proto::api_client::XmtpTestClient; pub fn build_group_messages(num_messages: usize, group_id: Vec) -> Vec { let mut out: Vec = vec![]; diff --git a/xmtp_mls/src/builder.rs b/xmtp_mls/src/builder.rs index e023c24c1..945033821 100644 --- a/xmtp_mls/src/builder.rs +++ b/xmtp_mls/src/builder.rs @@ -212,6 +212,7 @@ pub(crate) mod tests { use crate::builder::ClientBuilderError; use crate::identity::IdentityError; use crate::retry::Retry; + use crate::utils::test::TestClient; use crate::XmtpApi; use crate::{ api::test_utils::*, identity::Identity, storage::identity::StoredIdentity, @@ -229,6 +230,7 @@ pub(crate) mod tests { use xmtp_id::associations::ValidatedLegacySignedPublicKey; use xmtp_id::associations::{generate_inbox_id, test_utils::rand_u64}; use xmtp_id::scw_verifier::SmartContractSignatureVerifier; + use xmtp_proto::api_client::XmtpTestClient; use xmtp_proto::xmtp::identity::api::v1::{ get_inbox_ids_response::Response as GetInboxIdsResponseItem, GetInboxIdsResponse, }; @@ -409,8 +411,7 @@ pub(crate) mod tests { let result = ClientBuilder::new(test_case.strategy) .temp_store() .await - .local_client() - .await + .api_client(::create_local().await) .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) .build_with_verifier() .await; @@ -450,8 +451,7 @@ pub(crate) mod tests { let client1 = ClientBuilder::new(identity_strategy.clone()) .store(store.clone()) - .local_client() - .await + .api_client(::create_local().await) .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) .build_with_verifier() .await @@ -460,8 +460,7 @@ pub(crate) mod tests { let client2 = ClientBuilder::new(IdentityStrategy::CachedOnly) .store(store.clone()) - .local_client() - .await + .api_client(::create_local().await) .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) .build_with_verifier() .await @@ -477,8 +476,7 @@ pub(crate) mod tests { None, )) .store(store.clone()) - .local_client() - .await + .api_client(::create_local().await) .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) .build_with_verifier() .await @@ -495,8 +493,7 @@ pub(crate) mod tests { )) .temp_store() .await - .local_client() - .await + .api_client(::create_local().await) .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) .build_with_verifier() .await @@ -690,8 +687,7 @@ pub(crate) mod tests { nonce, None, )) - .local_client() - .await + .api_client(::create_local().await) .store(store_a) .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) .build_with_verifier() @@ -715,8 +711,7 @@ pub(crate) mod tests { nonce, None, )) - .local_client() - .await + .api_client(::create_local().await) .store(store_b) .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) .build_with_verifier() @@ -738,8 +733,7 @@ pub(crate) mod tests { // generate_local_wallet().get_address(), // None, // )) - // .local_client() - // .await + // .api_client(::create_local().await) // .store(store_c) // .build() // .await @@ -750,8 +744,7 @@ pub(crate) mod tests { .await .unwrap(); let client_d = Client::builder(IdentityStrategy::CachedOnly) - .local_client() - .await + .api_client(::create_local().await) .store(store_d) .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) .build_with_verifier() diff --git a/xmtp_mls/src/client.rs b/xmtp_mls/src/client.rs index 418de8a07..e208602cc 100644 --- a/xmtp_mls/src/client.rs +++ b/xmtp_mls/src/client.rs @@ -674,14 +674,14 @@ where pub(crate) async fn query_group_messages( &self, - group_id: &Vec, + group_id: &[u8], conn: &DbConnection, ) -> Result, ClientError> { let id_cursor = conn.get_last_cursor_for_id(group_id, EntityKind::Group)?; let welcomes = self .api_client - .query_group_messages(group_id.clone(), Some(id_cursor as u64)) + .query_group_messages(group_id.to_vec(), Some(id_cursor as u64)) .await?; Ok(welcomes) diff --git a/xmtp_mls/src/groups/message_history.rs b/xmtp_mls/src/groups/message_history.rs index 9510d9135..83c7f6573 100644 --- a/xmtp_mls/src/groups/message_history.rs +++ b/xmtp_mls/src/groups/message_history.rs @@ -928,14 +928,14 @@ pub(crate) mod tests { assert_eq!(amal_a_sync_groups.len(), 1); // get the first sync group let amal_a_sync_group = amal_a.group(amal_a_sync_groups[0].id.clone()).unwrap(); - amal_a_sync_group.sync(&amal_a).await.expect("sync"); + amal_a_sync_group.sync().await.expect("sync"); // find the sync group (it should be the same as amal_a's sync group) let amal_b_sync_groups = amal_b.store().conn().unwrap().find_sync_groups().unwrap(); assert_eq!(amal_b_sync_groups.len(), 1); // get the first sync group let amal_b_sync_group = amal_b.group(amal_b_sync_groups[0].id.clone()).unwrap(); - amal_b_sync_group.sync(&amal_b).await.expect("sync"); + amal_b_sync_group.sync().await.expect("sync"); // make sure they are the same group assert_eq!(amal_a_sync_group.group_id, amal_b_sync_group.group_id); @@ -960,7 +960,7 @@ pub(crate) mod tests { assert_eq!(amal_a_sync_groups.len(), 1); // get the first sync group let amal_a_sync_group = amal_a.group(amal_a_sync_groups[0].id.clone()).unwrap(); - amal_a_sync_group.sync(&amal_a).await.expect("sync"); + amal_a_sync_group.sync().await.expect("sync"); let pin_challenge_result = amal_a.verify_pin(&request_id, &pin_code); assert_ok!(pin_challenge_result); @@ -1035,7 +1035,7 @@ pub(crate) mod tests { assert_eq!(amal_a_sync_groups.len(), 1); // get the first sync group let amal_a_sync_group = amal_a.group(amal_a_sync_groups[0].id.clone()).unwrap(); - amal_a_sync_group.sync(&amal_a).await.expect("sync"); + amal_a_sync_group.sync().await.expect("sync"); // amal_a builds and sends a message history reply back let history_reply = HistoryReply::new(&new_request_id(), &history_sync_url, encryption_key); @@ -1044,13 +1044,13 @@ pub(crate) mod tests { .await .expect("send reply"); - amal_a_sync_group.sync(&amal_a).await.expect("sync"); + amal_a_sync_group.sync().await.expect("sync"); // amal_b should have received the reply let amal_b_sync_groups = amal_b.store().conn().unwrap().find_sync_groups().unwrap(); assert_eq!(amal_b_sync_groups.len(), 1); let amal_b_sync_group = amal_b.group(amal_b_sync_groups[0].id.clone()).unwrap(); - amal_b_sync_group.sync(&amal_b).await.expect("sync"); + amal_b_sync_group.sync().await.expect("sync"); let amal_b_conn = amal_b.store().conn().unwrap(); let amal_b_messages = amal_b_conn @@ -1086,10 +1086,10 @@ pub(crate) mod tests { .create_group(None, GroupMetadataOptions::default()) .expect("create group"); - group_a.send_message(b"hi", &amal_a).await.expect("send"); - group_a.send_message(b"hi x2", &amal_a).await.expect("send"); - group_b.send_message(b"hi", &amal_a).await.expect("send"); - group_b.send_message(b"hi x2", &amal_a).await.expect("send"); + group_a.send_message(b"hi").await.expect("send"); + group_a.send_message(b"hi x2").await.expect("send"); + group_b.send_message(b"hi").await.expect("send"); + group_b.send_message(b"hi x2").await.expect("send"); let messages_result = amal_a.prepare_messages_to_sync().await.unwrap(); assert_eq!(messages_result.len(), 4); @@ -1106,10 +1106,10 @@ pub(crate) mod tests { .create_group(None, GroupMetadataOptions::default()) .expect("create group"); - group_a.send_message(b"hi", &amal_a).await.expect("send"); - group_a.send_message(b"hi", &amal_a).await.expect("send"); - group_b.send_message(b"hi", &amal_a).await.expect("send"); - group_b.send_message(b"hi", &amal_a).await.expect("send"); + group_a.send_message(b"hi").await.expect("send"); + group_a.send_message(b"hi").await.expect("send"); + group_b.send_message(b"hi").await.expect("send"); + group_b.send_message(b"hi").await.expect("send"); let groups = amal_a.prepare_groups_to_sync().await.unwrap(); let messages = amal_a.prepare_messages_to_sync().await.unwrap(); @@ -1404,10 +1404,7 @@ pub(crate) mod tests { .create_group(None, GroupMetadataOptions::default()) .expect("create group"); - group_a - .send_message(b"hi", &amal_a) - .await - .expect("send message"); + group_a.send_message(b"hi").await.expect("send message"); let (bundle_path, enc_key) = amal_a .write_history_bundle() @@ -1449,9 +1446,7 @@ pub(crate) mod tests { // try to join amal's sync group let sync_group_id = amal_sync_groups[0].id.clone(); let group = amal.group(sync_group_id).expect("get group"); - let result = group - .add_members(&external_client, vec![external_wallet.get_address()]) - .await; + let result = group.add_members(vec![external_wallet.get_address()]).await; assert!(result.is_err()); } diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index 11403e103..f11dab344 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -40,7 +40,7 @@ pub use self::group_permissions::PreconfiguredPolicies; pub use self::intents::{AddressesOrInstallationIds, IntentError}; #[cfg(feature = "message-history")] use self::message_history::MessageHistoryError; -pub(self) use self::scoped_client::ScopedGroupClient; +use self::scoped_client::ScopedGroupClient; use self::{ group_membership::GroupMembership, group_metadata::{extract_group_metadata, DmMembers}, @@ -1398,7 +1398,7 @@ async fn validate_initial_group_membership( let membership = extract_group_membership(mls_group.extensions())?; let needs_update = conn.filter_inbox_ids_needing_updates(membership.to_filters())?; if !needs_update.is_empty() { - load_identity_updates(&client.api(), conn, needs_update).await?; + load_identity_updates(client.api(), conn, needs_update).await?; } let mut expected_installation_ids = HashSet::>::new(); diff --git a/xmtp_mls/src/groups/scoped_client.rs b/xmtp_mls/src/groups/scoped_client.rs index 1905b380d..10460cffa 100644 --- a/xmtp_mls/src/groups/scoped_client.rs +++ b/xmtp_mls/src/groups/scoped_client.rs @@ -72,7 +72,7 @@ pub trait LocalScopedGroupClient: Send + Sync + Sized { async fn query_group_messages( &self, - group_id: &Vec, + group_id: &[u8], conn: &DbConnection, ) -> Result, ClientError>; } @@ -132,7 +132,7 @@ pub trait ScopedGroupClient: Sized { async fn query_group_messages( &self, - group_id: &Vec, + group_id: &[u8], conn: &DbConnection, ) -> Result, ClientError>; } @@ -210,7 +210,7 @@ where async fn query_group_messages( &self, - group_id: &Vec, + group_id: &[u8], conn: &DbConnection, ) -> Result, ClientError> { crate::Client::::query_group_messages(self, group_id, conn).await @@ -296,7 +296,7 @@ where async fn query_group_messages( &self, - group_id: &Vec, + group_id: &[u8], conn: &DbConnection, ) -> Result, ClientError> { (**self).query_group_messages(group_id, conn).await @@ -382,7 +382,7 @@ where async fn query_group_messages( &self, - group_id: &Vec, + group_id: &[u8], conn: &DbConnection, ) -> Result, ClientError> { (**self).query_group_messages(group_id, conn).await diff --git a/xmtp_mls/src/groups/subscriptions.rs b/xmtp_mls/src/groups/subscriptions.rs index 61df81c5e..6005099db 100644 --- a/xmtp_mls/src/groups/subscriptions.rs +++ b/xmtp_mls/src/groups/subscriptions.rs @@ -107,9 +107,7 @@ impl MlsGroup { message.ok_or(GroupError::MissingMessage) } - pub async fn stream<'a>( - &'a self, - ) -> Result + '_, GroupError> + pub async fn stream(&self) -> Result + '_, GroupError> where ScopedClient: Clone, ::ApiClient: Clone + 'static, diff --git a/xmtp_mls/src/groups/sync.rs b/xmtp_mls/src/groups/sync.rs index 6eac793ab..552f2e1b0 100644 --- a/xmtp_mls/src/groups/sync.rs +++ b/xmtp_mls/src/groups/sync.rs @@ -1004,7 +1004,7 @@ where inbox_ids.extend(inbox_ids_to_add); let conn = provider.conn_ref(); // Load any missing updates from the network - load_identity_updates(&self.client.api(), conn, inbox_ids.clone()).await?; + load_identity_updates(self.client.api(), conn, inbox_ids.clone()).await?; let latest_sequence_id_map = conn.get_latest_sequence_id(&inbox_ids)?; diff --git a/xmtp_mls/src/intents.rs b/xmtp_mls/src/intents.rs index bd5c0b40a..95ed0a371 100644 --- a/xmtp_mls/src/intents.rs +++ b/xmtp_mls/src/intents.rs @@ -1,10 +1,12 @@ -//! an "Intent" can be thought of as a commitment by a user to try and accomplish something -//! in a group chat. Examples of an Intent: -//! - Sending a message -//! - Adding a member -//! - Removing a member -//! Intents are written to local storage, before being published to the delivery service. An -//! intent is fully processed (success or failure) once it +//! an "Intent" can be thought of as a commitment by an individual 'user', which drives +//! the state of a group chat forward. +//! Examples of an Intent: +//! - Sending a message +//! - Adding a member +//! - Removing a member +//! +//! Intents are written to local storage (SQLite), before being published to the delivery service via gRPC. An +//! intent is fully resolved (success or failure) once it use std::{future::Future, sync::Arc}; diff --git a/xmtp_mls/src/storage/encrypted_store/refresh_state.rs b/xmtp_mls/src/storage/encrypted_store/refresh_state.rs index 536d2975d..19b6b28cc 100644 --- a/xmtp_mls/src/storage/encrypted_store/refresh_state.rs +++ b/xmtp_mls/src/storage/encrypted_store/refresh_state.rs @@ -54,7 +54,7 @@ impl_store!(RefreshState, refresh_state); impl_store_or_ignore!(RefreshState, refresh_state); impl DbConnection { - pub fn get_refresh_state>>( + pub fn get_refresh_state>( &self, entity_id: EntityId, entity_kind: EntityKind, @@ -70,7 +70,7 @@ impl DbConnection { Ok(res) } - pub fn get_last_cursor_for_id>>( + pub fn get_last_cursor_for_id>( &self, id: IdType, entity_kind: EntityKind, @@ -80,7 +80,7 @@ impl DbConnection { Some(state) => Ok(state.cursor), None => { let new_state = RefreshState { - entity_id: id.as_ref().clone(), + entity_id: id.as_ref().to_vec(), entity_kind, cursor: 0, }; diff --git a/xmtp_mls/src/utils/bench.rs b/xmtp_mls/src/utils/bench.rs index 99f833cae..3dffb4ba7 100644 --- a/xmtp_mls/src/utils/bench.rs +++ b/xmtp_mls/src/utils/bench.rs @@ -130,7 +130,7 @@ async fn create_identity(is_dev_network: bool) -> Identity { let client = if is_dev_network { ClientBuilder::new_dev_client(&wallet).await } else { - ClientBuilder::new_test_client(&wallet).await + ClientBuilder::new_local_client(&wallet).await }; Identity::new(client.inbox_id(), wallet.get_address()) } diff --git a/xmtp_mls/src/utils/test/mod.rs b/xmtp_mls/src/utils/test/mod.rs index d831197a8..6393d445b 100755 --- a/xmtp_mls/src/utils/test/mod.rs +++ b/xmtp_mls/src/utils/test/mod.rs @@ -1,6 +1,5 @@ #![allow(clippy::unwrap_used)] -use crate::XmtpTestClient; use rand::{ distributions::{Alphanumeric, DistString}, Rng, RngCore, @@ -13,8 +12,9 @@ use xmtp_id::{ test_utils::MockSmartContractSignatureVerifier, unverified::{UnverifiedRecoverableEcdsaSignature, UnverifiedSignature}, }, - scw_verifier::SmartContractSignatureVerifier, + scw_verifier::{RemoteSignatureVerifier, SmartContractSignatureVerifier}, }; +use xmtp_proto::api_client::XmtpTestClient; use crate::{ builder::ClientBuilder, @@ -90,7 +90,7 @@ impl EncryptedMessageStore { pub fn remove_db_files>(_path: P) {} } -impl ClientBuilder { +impl ClientBuilder { pub async fn temp_store(self) -> Self { let tmpdb = tmp_path(); self.store( @@ -102,65 +102,82 @@ impl ClientBuilder { .unwrap(), ) } +} - pub async fn local_client(self) -> Self { - self.api_client(::create_local().await) - } - +impl ClientBuilder { pub async fn new_test_client(owner: &impl InboxOwner) -> FullXmtpClient { - // crate::utils::wasm::init().await; - let nonce = 1; - let inbox_id = generate_inbox_id(&owner.get_address(), &nonce); - - let client = Self::new(IdentityStrategy::CreateIfNotFound( - inbox_id, - owner.get_address(), - nonce, - None, - )) - .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) - .temp_store() - .await - .local_client() - .await - .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) - .build_with_verifier() + let api_client = ::create_local().await; + inner_build( + owner, + &api_client, + MockSmartContractSignatureVerifier::new(true), + ) .await - .unwrap(); - - register_client(&client, owner).await; - - client } - pub async fn new_dev_client( - owner: &impl InboxOwner, + /// A client pointed at the dev network with a Mock verifier (never fail to verify) + pub async fn new_mock_dev_client( + owner: impl InboxOwner, ) -> Client { - let nonce = 1; - let inbox_id = generate_inbox_id(&owner.get_address(), &nonce); - let dev_client = ::create_dev().await; - - let client = Self::new(IdentityStrategy::CreateIfNotFound( - inbox_id, - owner.get_address(), - nonce, - None, - )) - .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) - .temp_store() - .await - .api_client(dev_client) - .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) - .build_with_verifier() + let api_client = ::create_dev().await; + inner_build( + owner, + &api_client, + MockSmartContractSignatureVerifier::new(true), + ) .await - .unwrap(); + } +} - register_client(&client, owner).await; +impl ClientBuilder { + /// Createa client pointed at the local containe with the default remote verifier + pub async fn new_local_client(owner: &impl InboxOwner) -> Client { + let api_client = ::create_local().await; + inner_build( + owner, + &api_client, + RemoteSignatureVerifier::new(api_client.clone()), + ) + .await + } - client + pub async fn new_dev_client(owner: &impl InboxOwner) -> Client { + let api_client = ::create_dev().await; + inner_build( + owner, + &api_client, + RemoteSignatureVerifier::new(api_client.clone()), + ) + .await } } +async fn inner_build(owner: impl InboxOwner, api_client: &A, scw_verifier: V) -> Client +where + A: XmtpApi + Clone, + V: SmartContractSignatureVerifier + Clone, +{ + let nonce = 1; + let inbox_id = generate_inbox_id(&owner.get_address(), &nonce); + + let client = Client::::builder(IdentityStrategy::CreateIfNotFound( + inbox_id, + owner.get_address(), + nonce, + None, + )) + .temp_store() + .await + .api_client(api_client.clone()) + .scw_signature_verifier(scw_verifier) + .build_with_verifier() + .await + .unwrap(); + + register_client(&client, owner).await; + + client +} /// wrapper over a `Notify` with a 60-scond timeout for waiting #[derive(Clone, Default)] pub struct Delivery { @@ -186,7 +203,11 @@ impl Delivery { } } -impl FullXmtpClient { +impl Client +where + ApiClient: XmtpApi + Clone, + V: SmartContractSignatureVerifier + Clone, +{ pub async fn is_registered(&self, address: &String) -> bool { let ids = self .api_client @@ -199,7 +220,7 @@ impl FullXmtpClient { pub async fn register_client( client: &Client, - owner: &impl InboxOwner, + owner: impl InboxOwner, ) { let mut signature_request = client.context.signature_request().unwrap(); let signature_text = signature_request.signature_text(); diff --git a/xmtp_proto/src/api_client.rs b/xmtp_proto/src/api_client.rs index b3bc9562d..2ee341a6a 100644 --- a/xmtp_proto/src/api_client.rs +++ b/xmtp_proto/src/api_client.rs @@ -19,17 +19,20 @@ use crate::xmtp::mls::api::v1::{ SubscribeWelcomeMessagesRequest, UploadKeyPackageRequest, WelcomeMessage, }; +#[cfg(any(test, feature = "test-utils"))] +#[trait_variant::make(XmtpTestClient: Send)] +pub trait LocalXmtpTestClient { + async fn create_local() -> Self; + async fn create_dev() -> Self; +} + /// XMTP Api Super Trait /// Implements all Trait Network APIs for convenience. pub mod trait_impls { - pub use inner::*; - + #[allow(unused)] #[cfg(any(test, feature = "test-utils"))] - #[trait_variant::make(XmtpTestClient: Send)] - pub trait LocalXmtpTestClient { - async fn create_local() -> Self; - async fn create_dev() -> Self; - } + use super::{LocalXmtpTestClient, XmtpTestClient}; + pub use inner::*; // native, release #[cfg(all(not(feature = "test-utils"), not(target_arch = "wasm32")))] @@ -129,7 +132,7 @@ pub mod trait_impls { Self: LocalXmtpMlsClient + LocalXmtpMlsStreams + LocalXmtpIdentityClient - + crate::LocalXmtpTestClient + + super::LocalXmtpTestClient + ClientWithMetadata, { } @@ -138,7 +141,7 @@ pub mod trait_impls { T: LocalXmtpMlsClient + LocalXmtpMlsStreams + LocalXmtpIdentityClient - + crate::LocalXmtpTestClient + + super::LocalXmtpTestClient + ClientWithMetadata + Send + Sync