Skip to content

Commit

Permalink
feat: NIP-87 federation discovery
Browse files Browse the repository at this point in the history
  • Loading branch information
tvolk131 committed Oct 13, 2024
1 parent 84c2330 commit 51555b8
Show file tree
Hide file tree
Showing 4 changed files with 346 additions and 10 deletions.
1 change: 1 addition & 0 deletions assets/icons/search.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 57 additions & 2 deletions src/nostr.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::Debug;
use std::str::FromStr;
use std::time::Duration;

use fedimint_core::config::FederationId;
use fedimint_core::invite_code::InviteCode;
use iced::Subscription;
use nostr_relay_pool::RelayStatus;
use nostr_sdk::Url;
use nostr_sdk::{Alphabet, EventSource, Filter, Kind, PublicKey, SingleLetterTag, TagKind, Url};

const D_TAG: TagKind = TagKind::SingleLetter(SingleLetterTag::lowercase(Alphabet::D));
const U_TAG: TagKind = TagKind::SingleLetter(SingleLetterTag::lowercase(Alphabet::U));

#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct NostrState {
Expand Down Expand Up @@ -69,6 +75,55 @@ impl NostrModule {
)
}

pub async fn find_federations(
&self,
) -> Result<
BTreeMap<FederationId, (BTreeSet<PublicKey>, BTreeSet<InviteCode>)>,
nostr_sdk::client::Error,
> {
let fedimint_recommendation_events = self
.client
.get_events_of(
vec![Filter::new()
.kind(Kind::Custom(38_000))
.custom_tag(SingleLetterTag::lowercase(Alphabet::K), vec!["38173"])
.custom_tag(SingleLetterTag::lowercase(Alphabet::N), vec!["mainnet"])],
EventSource::both(None),
)
.await?;

let mut federations = BTreeMap::new();

for recommendation_event in &fedimint_recommendation_events {
for d_tag in recommendation_event.get_tags_content(D_TAG) {
let Ok(federation_id) = FederationId::from_str(d_tag) else {
continue;
};

let (recommenders, invite_codes) = federations
.entry(federation_id)
.or_insert_with(|| (BTreeSet::new(), BTreeSet::new()));

recommenders.insert(recommendation_event.pubkey);

for u_tag in recommendation_event.get_tags_content(U_TAG) {
if let Ok(invite_code) = InviteCode::from_str(u_tag) {
if invite_code.federation_id() == federation_id {
invite_codes.insert(invite_code);
}
}
}
}
}

// It's possible for a user to recommend a federation without providing any invite codes.
// If a federation has no recommendations that include any invite codes, we don't want to
// include it in the list of federations since it's not possible to join it.
federations.retain(|_, (_, invite_codes)| !invite_codes.is_empty());

Ok(federations)
}

/// Fetches the current state of the Nostr SDK client.
/// Note: This is async because it's grabbing read locks
/// on the relay `RwLock`s. No network requests are made.
Expand Down
Loading

0 comments on commit 51555b8

Please sign in to comment.