Skip to content
This repository has been archived by the owner on Feb 3, 2025. It is now read-only.

Commit

Permalink
Merge pull request #1124 from MutinyWallet/rec-fixes
Browse files Browse the repository at this point in the history
Fixes for recommendation events
  • Loading branch information
AnthonyRonning authored Apr 8, 2024
2 parents 49941f0 + af48c61 commit acc48f4
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 11 deletions.
7 changes: 6 additions & 1 deletion mutiny-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1244,7 +1244,12 @@ impl<S: MutinyStorage> MutinyWallet<S> {
Ok(false) => log_debug!(logger, "Got older contact list, ignoring..."),
}
}
kind => log_warn!(logger, "Received unexpected note of kind {kind}")
kind => {
// ignore federation announcement events
if kind.as_u64() != 38000 && kind.as_u64() != 38173 {
log_warn!(logger, "Received unexpected note of kind {kind}");
}
}
}
}
},
Expand Down
75 changes: 65 additions & 10 deletions mutiny-core/src/nostr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1591,12 +1591,12 @@ impl<S: MutinyStorage> NostrManager<S> {
}

/// Creates a recommendation event for a federation
pub async fn recommend_federation(
pub(crate) async fn create_recommend_federation_event(
&self,
invite_code: &InviteCode,
network: Network,
review: Option<&str>,
) -> Result<EventId, MutinyError> {
) -> Result<Event, MutinyError> {
let kind = Kind::from(38000);

// properly tag the event as a federation with the federation id
Expand Down Expand Up @@ -1626,8 +1626,21 @@ impl<S: MutinyStorage> NostrManager<S> {
[d_tag, k_tag, invite_code_tag, n_tag],
);

// send the event
Ok(self.client.send_event_builder(builder).await?)
Ok(self.client.sign_event_builder(builder).await?)
}

/// Creates a recommendation event for a federation
pub async fn recommend_federation(
&self,
invite_code: &InviteCode,
network: Network,
review: Option<&str>,
) -> Result<EventId, MutinyError> {
let event = self
.create_recommend_federation_event(invite_code, network, review)
.await?;
let event_id = self.client.send_event(event).await?;
Ok(event_id)
}

/// Checks if we have recommended the given federation
Expand Down Expand Up @@ -1795,12 +1808,8 @@ impl<S: MutinyStorage> NostrManager<S> {
// add on contact recommendations to mints
for event in events {
// only process federation recommendations
if event.kind != Kind::from(38000)
|| !event.tags.iter().any(|tag| {
tag.kind() == TagKind::Custom("k".to_string())
&& tag.as_vec().get(1).is_some_and(|x| x == "38173")
})
{
if !is_federation_recommendation_event(&event) {
log_warn!(self.logger, "Skipping event: {}", event.id);
continue;
}

Expand Down Expand Up @@ -2065,6 +2074,14 @@ fn parse_invite_code_from_tag(
code.filter(|c| c.federation_id() == *expected_federation_id)
}

fn is_federation_recommendation_event(event: &Event) -> bool {
event.kind == Kind::from(38000)
&& event.tags.iter().any(|tag| {
tag.kind() == TagKind::SingleLetter(SingleLetterTag::lowercase(Alphabet::K))
&& tag.as_vec().get(1).is_some_and(|x| x == "38173")
})
}

#[cfg(not(target_arch = "wasm32"))]
#[cfg(test)]
mod test {
Expand Down Expand Up @@ -2615,4 +2632,42 @@ mod test {

assert_eq!(vec, expected);
}

#[tokio::test]
async fn test_is_federation_recommendation_event() {
let keys = Keys::generate();

// kind 0 is not a recommendation event
let kind0 = EventBuilder::metadata(&Default::default())
.to_event(&keys)
.unwrap();
assert!(!is_federation_recommendation_event(&kind0));

// kind 38000 without k tag is a recommendation event for something else
let no_k = EventBuilder::new(Kind::Custom(38000), "", [])
.to_event(&keys)
.unwrap();
assert!(!is_federation_recommendation_event(&no_k));

// kind 38000 with correct k tag is a recommendation event
let k_tag = Tag::Generic(
TagKind::SingleLetter(SingleLetterTag::lowercase(Alphabet::K)),
vec!["38173".to_string()],
);
let with_k = EventBuilder::new(Kind::Custom(38000), "", [k_tag])
.to_event(&keys)
.unwrap();
assert!(is_federation_recommendation_event(&with_k));

// test nostr manager creates a valid one

let nostr_manager = create_nostr_manager();
let invite_code = InviteCode::from_str("fed11qgqzc2nhwden5te0vejkg6tdd9h8gepwvejkg6tdd9h8garhduhx6at5d9h8jmn9wshxxmmd9uqqzgxg6s3evnr6m9zdxr6hxkdkukexpcs3mn7mj3g5pc5dfh63l4tj6g9zk4er").unwrap();
let event = nostr_manager
.create_recommend_federation_event(&invite_code, Network::Signet, None)
.await
.unwrap();

assert!(is_federation_recommendation_event(&event));
}
}

0 comments on commit acc48f4

Please sign in to comment.