Skip to main content

xmtp_mls/groups/
welcome_pointer.rs

1use super::GroupError;
2use xmtp_common::{Retry, retry_async};
3use xmtp_proto::{
4    types::{DecryptedWelcomePointer, WelcomeMessageType, WelcomeMessageV1},
5    xmtp::mls::message_contents::WelcomeWrapperAlgorithm,
6};
7
8/// Returns none if the welcome pointer is not found
9pub async fn resolve_welcome_pointer<Context: crate::context::XmtpSharedContext>(
10    decrypted_welcome_pointer: &DecryptedWelcomePointer,
11    context: &Context,
12) -> Result<Option<WelcomeMessageV1>, GroupError> {
13    let retry = Retry::default();
14    let mut retries = 0;
15    let time_spent = xmtp_common::time::Instant::now();
16
17    let decrypted_v1 = decrypted_welcome_pointer;
18
19    tracing::debug!(
20        "Resolving welcome pointer for destination {}",
21        decrypted_v1.destination
22    );
23
24    // Can't use retry_async! because we want to return Ok(None) if it isn't resolved.
25    let welcome = loop {
26        let welcome = retry_async!(
27            Retry::default(),
28            (context
29                .api()
30                // TODO: limit this to a single message somehow (maybe an earliest_welcome_message fn)
31                .query_welcome_messages(decrypted_v1.destination.as_slice()))
32        );
33        if let Some(first) = welcome?.into_iter().next() {
34            break first;
35        }
36        retries += 1;
37        if retries <= retry.retries()
38            && let Some(d) = retry.backoff(retries, time_spent)
39        {
40            tracing::info!(
41                "Welcome pointee not found, backing off for {d:?}... (attempt {})",
42                retries
43            );
44            xmtp_common::time::sleep(d).await;
45        } else {
46            return Ok(None);
47        }
48    };
49    // These failure modes are non-retryable and will end up incrementing
50    // the cursor and will prevent the welcome message from being retried.
51    match welcome.variant {
52        // implements: JOIN-056
53        // The envelope decoder already bound installation_key to the destination topic.
54        WelcomeMessageType::V1(v1)
55            if v1.wrapper_algorithm == WelcomeWrapperAlgorithm::SymmetricKey =>
56        {
57            Ok(Some(v1))
58        }
59        WelcomeMessageType::V1(v1) => Err(xmtp_proto::ConversionError::InvalidValue {
60            item: "WelcomePointee.wrapper_algorithm",
61            expected: "SymmetricKey",
62            got: format!("{:?}", v1.wrapper_algorithm),
63        }
64        .into()),
65        WelcomeMessageType::WelcomePointer(_) => {
66            tracing::warn!("Got Another welcome pointer from a welcome pointer. Ignoring.");
67            Err(xmtp_proto::ConversionError::InvalidValue {
68                item: "WelcomeMessage.version",
69                expected: "V1",
70                got: "WelcomePointer".into(),
71            }
72            .into())
73        }
74    }
75}