Skip to content

Commit a05b6da

Browse files
committed
feat: NIP-87 federation discovery
1 parent 84c2330 commit a05b6da

File tree

4 files changed

+341
-10
lines changed

4 files changed

+341
-10
lines changed

assets/icons/search.svg

+1
Loading

src/nostr.rs

+52-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
use std::collections::BTreeMap;
1+
use std::collections::{BTreeMap, BTreeSet};
22
use std::fmt::Debug;
3+
use std::str::FromStr;
34
use std::time::Duration;
45

6+
use fedimint_core::config::FederationId;
7+
use fedimint_core::invite_code::InviteCode;
58
use iced::Subscription;
69
use nostr_relay_pool::RelayStatus;
7-
use nostr_sdk::Url;
10+
use nostr_sdk::{Alphabet, EventSource, Filter, Kind, PublicKey, SingleLetterTag, TagKind, Url};
811

912
#[derive(Default, Debug, Clone, PartialEq, Eq)]
1013
pub struct NostrState {
@@ -69,6 +72,53 @@ impl NostrModule {
6972
)
7073
}
7174

75+
pub async fn find_federations(
76+
&self,
77+
) -> Result<
78+
BTreeMap<FederationId, (BTreeSet<PublicKey>, BTreeSet<InviteCode>)>,
79+
nostr_sdk::client::Error,
80+
> {
81+
let fedimint_recommendation_events = self
82+
.client
83+
.get_events_of(
84+
vec![Filter::new()
85+
.kind(Kind::Custom(38_000))
86+
.custom_tag(SingleLetterTag::lowercase(Alphabet::K), vec!["38173"])
87+
.custom_tag(SingleLetterTag::lowercase(Alphabet::N), vec!["mainnet"])],
88+
EventSource::both(None),
89+
)
90+
.await?;
91+
92+
let mut federations = BTreeMap::new();
93+
94+
for recommendation_event in &fedimint_recommendation_events {
95+
for d_tag in recommendation_event.get_tags_content(TagKind::SingleLetter(
96+
SingleLetterTag::lowercase(Alphabet::D),
97+
)) {
98+
if let Ok(federation_id) = FederationId::from_str(d_tag) {
99+
let (recommenders, invite_codes) = federations
100+
.entry(federation_id)
101+
.or_insert_with(|| (BTreeSet::new(), BTreeSet::new()));
102+
103+
recommenders.insert(recommendation_event.pubkey);
104+
for u_tag in recommendation_event.get_tags_content(TagKind::SingleLetter(
105+
SingleLetterTag::lowercase(Alphabet::U),
106+
)) {
107+
if let Ok(invite_code) = InviteCode::from_str(u_tag) {
108+
if invite_code.federation_id() == federation_id {
109+
invite_codes.insert(invite_code);
110+
}
111+
}
112+
}
113+
}
114+
}
115+
}
116+
117+
federations.retain(|_, (_, invite_codes)| !invite_codes.is_empty());
118+
119+
Ok(federations)
120+
}
121+
72122
/// Fetches the current state of the Nostr SDK client.
73123
/// Note: This is async because it's grabbing read locks
74124
/// on the relay `RwLock`s. No network requests are made.

0 commit comments

Comments
 (0)