1#![warn(clippy::unwrap_used)]
2
3pub mod associations;
4pub mod constants;
5pub mod key_package;
6pub mod scw_verifier;
7pub mod utils;
8
9pub use alloy::primitives::{BlockNumber, Bytes};
10use alloy::{signers::SignerSync, signers::local::PrivateKeySigner};
11use associations::{
12 Identifier,
13 unverified::{UnverifiedRecoverableEcdsaSignature, UnverifiedSignature},
14};
15use openmls_traits::types::CryptoError;
16use thiserror::Error;
17use xmtp_common::{MaybeSend, MaybeSync};
18use xmtp_cryptography::signature::{IdentifierValidationError, SignatureError, h160addr_to_string};
19
20#[derive(Debug, Error)]
21pub enum IdentityError {
22 #[error("generating key-pairs: {0}")]
23 KeyGenerationError(#[from] CryptoError),
24 #[error("uninitialized identity")]
25 UninitializedIdentity,
26 #[error("protobuf deserialization: {0}")]
27 Deserialization(#[from] prost::DecodeError),
28 #[error(transparent)]
29 UrlParseError(#[from] url::ParseError),
30 #[error("MLS signer error {0}")]
31 Signing(#[from] xmtp_cryptography::SignerError),
32}
33
34pub type InboxIdRef<'a> = &'a str;
36
37pub type InboxId = String;
39
40pub type WalletAddress = String;
41
42use crate::associations::unverified::UnverifiedIdentityUpdate;
43use xmtp_proto::ConversionError;
44use xmtp_proto::xmtp::identity::api::v1::get_identity_updates_response::IdentityUpdateLog;
45
46#[derive(Clone, Debug)]
47pub struct InboxUpdate {
48 pub sequence_id: u64,
49 pub server_timestamp_ns: u64,
50 pub update: UnverifiedIdentityUpdate,
51}
52
53impl TryFrom<IdentityUpdateLog> for InboxUpdate {
54 type Error = ConversionError;
55
56 fn try_from(update: IdentityUpdateLog) -> Result<Self, Self::Error> {
57 Ok(Self {
58 sequence_id: update.sequence_id,
59 server_timestamp_ns: update.server_timestamp_ns,
60 update: update
61 .update
62 .ok_or(ConversionError::Missing {
63 item: "update",
64 r#type: std::any::type_name::<IdentityUpdateLog>(),
65 })?
66 .try_into()?,
67 })
68 }
69}
70
71pub trait AsIdRef: MaybeSend + MaybeSync {
72 fn as_ref(&'_ self) -> InboxIdRef<'_>;
73}
74
75impl AsIdRef for InboxId {
76 fn as_ref(&self) -> InboxIdRef<'_> {
77 self
78 }
79}
80impl AsIdRef for &InboxId {
81 fn as_ref(&self) -> InboxIdRef<'_> {
82 self
83 }
84}
85impl AsIdRef for InboxIdRef<'_> {
86 fn as_ref(&self) -> InboxIdRef<'_> {
87 self
88 }
89}
90
91pub trait InboxOwner {
92 fn get_identifier(&self) -> Result<Identifier, IdentifierValidationError>;
94
95 fn sign(&self, text: &str) -> Result<UnverifiedSignature, SignatureError>;
97}
98
99impl InboxOwner for PrivateKeySigner {
100 fn get_identifier(&self) -> Result<Identifier, IdentifierValidationError> {
101 Identifier::eth(h160addr_to_string(self.address()))
102 }
103
104 fn sign(&self, text: &str) -> Result<UnverifiedSignature, SignatureError> {
105 let signature_bytes = self.sign_message_sync(text.as_bytes())?;
106 let sig = UnverifiedSignature::RecoverableEcdsa(UnverifiedRecoverableEcdsaSignature {
107 signature_bytes: signature_bytes.into(),
108 });
109 Ok(sig)
110 }
111}
112
113impl<T> InboxOwner for &T
114where
115 T: InboxOwner,
116{
117 fn get_identifier(&self) -> Result<Identifier, IdentifierValidationError> {
118 (**self).get_identifier()
119 }
120
121 fn sign(&self, text: &str) -> Result<UnverifiedSignature, SignatureError> {
122 (**self).sign(text)
123 }
124}