Skip to main content

xmtp_id/
lib.rs

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
34/// The global InboxID Reference Type.
35pub type InboxIdRef<'a> = &'a str;
36
37/// Global InboxID Owned Type.
38pub 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    /// Get address string of the wallet.
93    fn get_identifier(&self) -> Result<Identifier, IdentifierValidationError>;
94
95    /// Sign text with the wallet.
96    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}