upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/lib/client.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-04-01 14:31:34 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2025-04-01 14:35:50 +0100
commit948fe972eb2bddf187b79f2673a091b6331cfd90 (patch)
treeec1c538d28108b104b5a00afd673631538f9aa00 /src/lib/client.rs
parent70966d571fce16f707725c6b0af0fd585bfce607 (diff)
chore: bump rust-nostr v0.37 ~> v0.40
and fix all of the breaking changes
Diffstat (limited to 'src/lib/client.rs')
-rw-r--r--src/lib/client.rs223
1 files changed, 138 insertions, 85 deletions
diff --git a/src/lib/client.rs b/src/lib/client.rs
index 59ec583..142df64 100644
--- a/src/lib/client.rs
+++ b/src/lib/client.rs
@@ -29,9 +29,14 @@ use futures::{
29use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressState, ProgressStyle}; 29use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressState, ProgressStyle};
30#[cfg(test)] 30#[cfg(test)]
31use mockall::*; 31use mockall::*;
32use nostr::{Event, nips::nip01::Coordinate, signer::SignerBackend}; 32use nostr::{
33use nostr_database::NostrEventsDatabase; 33 Event,
34 nips::{nip01::Coordinate, nip19::Nip19Coordinate},
35 signer::SignerBackend,
36};
37use nostr_database::{NostrEventsDatabase, SaveEventStatus};
34use nostr_lmdb::NostrLMDB; 38use nostr_lmdb::NostrLMDB;
39use nostr_relay_pool::relay::ReqExitPolicy;
35use nostr_sdk::{ 40use nostr_sdk::{
36 EventBuilder, EventId, Kind, NostrSigner, Options, PublicKey, RelayUrl, SingleLetterTag, 41 EventBuilder, EventId, Kind, NostrSigner, Options, PublicKey, RelayUrl, SingleLetterTag,
37 Timestamp, prelude::RelayLimits, 42 Timestamp, prelude::RelayLimits,
@@ -89,7 +94,7 @@ pub trait Connect {
89 async fn fetch_all<'a>( 94 async fn fetch_all<'a>(
90 &self, 95 &self,
91 git_repo_path: Option<&'a Path>, 96 git_repo_path: Option<&'a Path>,
92 repo_coordinates: Option<&'a Coordinate>, 97 repo_coordinates: Option<&'a Nip19Coordinate>,
93 user_profiles: &HashSet<PublicKey>, 98 user_profiles: &HashSet<PublicKey>,
94 ) -> Result<(Vec<Result<FetchReport>>, MultiProgress)>; 99 ) -> Result<(Vec<Result<FetchReport>>, MultiProgress)>;
95 async fn fetch_all_from_relay<'a>( 100 async fn fetch_all_from_relay<'a>(
@@ -182,8 +187,8 @@ impl Connect for Client {
182 187
183 if !relay.is_connected() { 188 if !relay.is_connected() {
184 #[allow(clippy::large_futures)] 189 #[allow(clippy::large_futures)]
185 relay 190 let _ = relay
186 .connect(Some(std::time::Duration::from_secs(CONNECTION_TIMEOUT))) 191 .try_connect(std::time::Duration::from_secs(CONNECTION_TIMEOUT))
187 .await; 192 .await;
188 } 193 }
189 194
@@ -194,7 +199,7 @@ impl Connect for Client {
194 } 199 }
195 200
196 async fn disconnect(&self) -> Result<()> { 201 async fn disconnect(&self) -> Result<()> {
197 self.client.disconnect().await?; 202 self.client.disconnect().await;
198 Ok(()) 203 Ok(())
199 } 204 }
200 205
@@ -223,11 +228,7 @@ impl Connect for Client {
223 self.client.add_relay(url).await?; 228 self.client.add_relay(url).await?;
224 #[allow(clippy::large_futures)] 229 #[allow(clippy::large_futures)]
225 self.client.connect_relay(url).await?; 230 self.client.connect_relay(url).await?;
226 self.client 231 self.client.relay(url).await?.send_event(&event).await?;
227 .relay(url)
228 .await?
229 .send_event(event.clone())
230 .await?;
231 if let Some(git_repo_path) = git_repo_path { 232 if let Some(git_repo_path) = git_repo_path {
232 save_event_in_local_cache(git_repo_path, &event).await?; 233 save_event_in_local_cache(git_repo_path, &event).await?;
233 } 234 }
@@ -329,7 +330,7 @@ impl Connect for Client {
329 async fn fetch_all<'a>( 330 async fn fetch_all<'a>(
330 &self, 331 &self,
331 git_repo_path: Option<&'a Path>, 332 git_repo_path: Option<&'a Path>,
332 trusted_maintainer_coordinate: Option<&'a Coordinate>, 333 trusted_maintainer_coordinate: Option<&'a Nip19Coordinate>,
333 user_profiles: &HashSet<PublicKey>, 334 user_profiles: &HashSet<PublicKey>,
334 ) -> Result<(Vec<Result<FetchReport>>, MultiProgress)> { 335 ) -> Result<(Vec<Result<FetchReport>>, MultiProgress)> {
335 let fallback_relays = &self 336 let fallback_relays = &self
@@ -504,7 +505,7 @@ impl Connect for Client {
504 request: FetchRequest, 505 request: FetchRequest,
505 pb: &Option<ProgressBar>, 506 pb: &Option<ProgressBar>,
506 ) -> Result<FetchReport> { 507 ) -> Result<FetchReport> {
507 let mut fresh_coordinates: HashSet<Coordinate> = HashSet::new(); 508 let mut fresh_coordinates: HashSet<Nip19Coordinate> = HashSet::new();
508 for (c, _) in request.repo_coordinates_without_relays.clone() { 509 for (c, _) in request.repo_coordinates_without_relays.clone() {
509 fresh_coordinates.insert(c); 510 fresh_coordinates.insert(c);
510 } 511 }
@@ -617,8 +618,8 @@ async fn get_events_of(
617 618
618 if !relay.is_connected() { 619 if !relay.is_connected() {
619 #[allow(clippy::large_futures)] 620 #[allow(clippy::large_futures)]
620 relay 621 let _ = relay
621 .connect(Some(std::time::Duration::from_secs(CONNECTION_TIMEOUT))) 622 .try_connect(std::time::Duration::from_secs(CONNECTION_TIMEOUT))
622 .await; 623 .await;
623 } 624 }
624 625
@@ -627,16 +628,27 @@ async fn get_events_of(
627 } else if let Some(pb) = pb { 628 } else if let Some(pb) = pb {
628 pb.set_prefix(format!("connected {}", relay.url())); 629 pb.set_prefix(format!("connected {}", relay.url()));
629 } 630 }
630 let events = relay 631
631 .fetch_events( 632 let events_res = join_all(filters.into_iter().map(|filter| async {
632 filters, 633 relay
633 // 20 is nostr_sdk default 634 .fetch_events(
634 std::time::Duration::from_secs(GET_EVENTS_TIMEOUT), 635 filter,
635 nostr_sdk::FilterOptions::ExitOnEOSE, 636 // 20 is nostr_sdk default
636 ) 637 std::time::Duration::from_secs(GET_EVENTS_TIMEOUT),
637 .await? 638 ReqExitPolicy::ExitOnEOSE,
638 .to_vec(); 639 )
639 Ok(events) 640 .await
641 }))
642 .await;
643
644 // no Event is being mutated, just new items added to the set
645 #[allow(clippy::mutable_key_type)]
646 let mut events: HashSet<Event> = HashSet::new();
647
648 for res in events_res {
649 events.extend(res?);
650 }
651 Ok(events.into_iter().collect())
640} 652}
641 653
642#[derive(Default)] 654#[derive(Default)]
@@ -770,50 +782,81 @@ pub async fn get_events_from_local_cache(
770 git_repo_path: &Path, 782 git_repo_path: &Path,
771 filters: Vec<nostr::Filter>, 783 filters: Vec<nostr::Filter>,
772) -> Result<Vec<nostr::Event>> { 784) -> Result<Vec<nostr::Event>> {
773 Ok(get_local_cache_database(git_repo_path) 785 let db = get_local_cache_database(git_repo_path).await?;
774 .await? 786
775 .query(filters.clone()) 787 let query_results = join_all(filters.into_iter().map(|filter| async {
776 .await 788 db.query(filter)
777 .context( 789 .await
778 "failed to execute query on opened git repo nostr cache database .git/nostr-cache.lmdb", 790 .context("failed to execute query on opened ngit nostr cache database")
779 )? 791 }))
780 .to_vec()) 792 .await;
793
794 // no Event is being mutated, just new items added to the set
795 #[allow(clippy::mutable_key_type)]
796 let mut events: HashSet<Event> = HashSet::new();
797
798 for result in query_results {
799 events.extend(result?);
800 }
801
802 Ok(events.into_iter().collect())
781} 803}
782 804
783pub async fn get_event_from_global_cache( 805pub async fn get_event_from_global_cache(
784 git_repo_path: Option<&Path>, 806 git_repo_path: Option<&Path>,
785 filters: Vec<nostr::Filter>, 807 filters: Vec<nostr::Filter>,
786) -> Result<Vec<nostr::Event>> { 808) -> Result<Vec<nostr::Event>> {
787 Ok(get_global_cache_database(git_repo_path) 809 let db = get_global_cache_database(git_repo_path).await?;
788 .await? 810
789 .query(filters.clone()) 811 let query_results = join_all(filters.into_iter().map(|filter| async {
790 .await 812 db.query(filter)
791 .context("failed to execute query on opened ngit nostr cache database")? 813 .await
792 .to_vec()) 814 .context("failed to execute query on opened ngit nostr cache database")
815 }))
816 .await;
817
818 // no Event is being mutated, just new items added to the set
819 #[allow(clippy::mutable_key_type)]
820 let mut events: HashSet<Event> = HashSet::new();
821
822 for result in query_results {
823 events.extend(result?);
824 }
825
826 Ok(events.into_iter().collect())
793} 827}
794 828
795pub async fn save_event_in_local_cache(git_repo_path: &Path, event: &nostr::Event) -> Result<bool> { 829pub async fn save_event_in_local_cache(git_repo_path: &Path, event: &nostr::Event) -> Result<bool> {
796 get_local_cache_database(git_repo_path) 830 match get_local_cache_database(git_repo_path)
797 .await? 831 .await?
798 .save_event(event) 832 .save_event(event)
799 .await 833 .await
800 .context("failed to save event in local cache") 834 .context("failed to save event in local cache")?
835 {
836 SaveEventStatus::Success => Ok(true),
837 _ => Ok(false),
838 }
801} 839}
802 840
803pub async fn save_event_in_global_cache( 841pub async fn save_event_in_global_cache(
804 git_repo_path: Option<&Path>, 842 git_repo_path: Option<&Path>,
805 event: &nostr::Event, 843 event: &nostr::Event,
806) -> Result<bool> { 844) -> Result<bool> {
807 get_global_cache_database(git_repo_path) 845 match get_global_cache_database(git_repo_path)
808 .await? 846 .await?
809 .save_event(event) 847 .save_event(event)
810 .await 848 .await
811 .context("failed to save event in local cache") 849 .context("failed to save event in local cache")
850 {
851 Ok(SaveEventStatus::Success) => Ok(true),
852 Ok(_) => Ok(false),
853 Err(e) => Err(e).context("failed to save event in local cache"),
854 }
812} 855}
813 856
814pub async fn get_repo_ref_from_cache( 857pub async fn get_repo_ref_from_cache(
815 git_repo_path: Option<&Path>, 858 git_repo_path: Option<&Path>,
816 repo_coordinate: &Coordinate, 859 repo_coordinate: &Nip19Coordinate,
817) -> Result<RepoRef> { 860) -> Result<RepoRef> {
818 let mut maintainers = HashSet::new(); 861 let mut maintainers = HashSet::new();
819 let mut new_coordinate: bool; 862 let mut new_coordinate: bool;
@@ -824,10 +867,12 @@ pub async fn get_repo_ref_from_cache(
824 new_coordinate = false; 867 new_coordinate = false;
825 let repo_events_filter = 868 let repo_events_filter =
826 get_filter_repo_events(&HashSet::from_iter(maintainers.iter().map(|m| { 869 get_filter_repo_events(&HashSet::from_iter(maintainers.iter().map(|m| {
827 Coordinate { 870 Nip19Coordinate {
828 kind: Kind::GitRepoAnnouncement, 871 coordinate: Coordinate {
829 public_key: *m, 872 kind: Kind::GitRepoAnnouncement,
830 identifier: repo_coordinate.identifier.to_string(), 873 public_key: *m,
874 identifier: repo_coordinate.identifier.to_string(),
875 },
831 relays: vec![], 876 relays: vec![],
832 } 877 }
833 }))); 878 })));
@@ -859,19 +904,21 @@ pub async fn get_repo_ref_from_cache(
859 let repo_ref = RepoRef::try_from(( 904 let repo_ref = RepoRef::try_from((
860 repo_events 905 repo_events
861 .first() 906 .first()
862 .context("no repo announcement event found at specified coordinates. if you are the repository maintainer consider running `ngit init` to create one")? 907 .context("no repo announcement event found at specified Nip19Coordinates. if you are the repository maintainer consider running `ngit init` to create one")?
863 .clone(), 908 .clone(),
864 Some(repo_coordinate.public_key), 909 Some(repo_coordinate.public_key),
865 ))?; 910 ))?;
866 911
867 let mut events: HashMap<Coordinate, nostr::Event> = HashMap::new(); 912 let mut events: HashMap<Nip19Coordinate, nostr::Event> = HashMap::new();
868 for m in &maintainers { 913 for m in &maintainers {
869 if let Some(e) = repo_events.iter().find(|e| e.pubkey.eq(m)) { 914 if let Some(e) = repo_events.iter().find(|e| e.pubkey.eq(m)) {
870 events.insert( 915 events.insert(
871 Coordinate { 916 Nip19Coordinate {
872 kind: e.kind, 917 coordinate: Coordinate {
873 identifier: e.tags.identifier().unwrap().to_string(), 918 kind: e.kind,
874 public_key: e.pubkey, 919 identifier: e.tags.identifier().unwrap().to_string(),
920 public_key: e.pubkey,
921 },
875 relays: vec![], 922 relays: vec![],
876 }, 923 },
877 e.clone(), 924 e.clone(),
@@ -912,7 +959,7 @@ pub async fn get_state_from_cache(
912#[allow(clippy::too_many_lines)] 959#[allow(clippy::too_many_lines)]
913async fn create_relays_request( 960async fn create_relays_request(
914 git_repo_path: Option<&Path>, 961 git_repo_path: Option<&Path>,
915 trusted_maintainer_coordinate: Option<&Coordinate>, 962 trusted_maintainer_coordinate: Option<&Nip19Coordinate>,
916 user_profiles: &HashSet<PublicKey>, 963 user_profiles: &HashSet<PublicKey>,
917 fallback_relays: HashSet<RelayUrl>, 964 fallback_relays: HashSet<RelayUrl>,
918) -> Result<FetchRequest> { 965) -> Result<FetchRequest> {
@@ -929,9 +976,9 @@ async fn create_relays_request(
929 }; 976 };
930 977
931 let repo_coordinates = { 978 let repo_coordinates = {
932 // add coordinates of users listed in maintainers to explicitly specified 979 // add Nip19Coordinates of users listed in maintainers to explicitly
933 // coodinates 980 // specified coodinates
934 let mut set: HashSet<Coordinate> = HashSet::new(); 981 let mut set: HashSet<Nip19Coordinate> = HashSet::new();
935 if let Some(trusted_maintainer_coordinate) = trusted_maintainer_coordinate { 982 if let Some(trusted_maintainer_coordinate) = trusted_maintainer_coordinate {
936 set.insert(trusted_maintainer_coordinate.clone()); 983 set.insert(trusted_maintainer_coordinate.clone());
937 } 984 }
@@ -951,10 +998,12 @@ async fn create_relays_request(
951 let repo_coordinates_without_relays = { 998 let repo_coordinates_without_relays = {
952 let mut set = HashSet::new(); 999 let mut set = HashSet::new();
953 for c in &repo_coordinates { 1000 for c in &repo_coordinates {
954 set.insert(Coordinate { 1001 set.insert(Nip19Coordinate {
955 kind: c.kind, 1002 coordinate: Coordinate {
956 identifier: c.identifier.clone(), 1003 kind: c.kind,
957 public_key: c.public_key, 1004 identifier: c.identifier.clone(),
1005 public_key: c.public_key,
1006 },
958 relays: vec![], 1007 relays: vec![],
959 }); 1008 });
960 } 1009 }
@@ -976,11 +1025,11 @@ async fn create_relays_request(
976 for event in &get_events_from_local_cache(git_repo_path, vec![ 1025 for event in &get_events_from_local_cache(git_repo_path, vec![
977 nostr::Filter::default() 1026 nostr::Filter::default()
978 .kinds(vec![Kind::GitPatch]) 1027 .kinds(vec![Kind::GitPatch])
979 .custom_tag( 1028 .custom_tags(
980 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A), 1029 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A),
981 repo_coordinates_without_relays 1030 repo_coordinates_without_relays
982 .iter() 1031 .iter()
983 .map(std::string::ToString::to_string) 1032 .map(|c| c.coordinate.to_string())
984 .collect::<Vec<String>>(), 1033 .collect::<Vec<String>>(),
985 ), 1034 ),
986 ]) 1035 ])
@@ -1153,7 +1202,7 @@ async fn process_fetched_events(
1153 events: Vec<nostr::Event>, 1202 events: Vec<nostr::Event>,
1154 request: &FetchRequest, 1203 request: &FetchRequest,
1155 git_repo_path: Option<&Path>, 1204 git_repo_path: Option<&Path>,
1156 fresh_coordinates: &mut HashSet<Coordinate>, 1205 fresh_coordinates: &mut HashSet<Nip19Coordinate>,
1157 fresh_proposal_roots: &mut HashSet<EventId>, 1206 fresh_proposal_roots: &mut HashSet<EventId>,
1158 fresh_profiles: &mut HashSet<PublicKey>, 1207 fresh_profiles: &mut HashSet<PublicKey>,
1159 report: &mut FetchReport, 1208 report: &mut FetchReport,
@@ -1188,10 +1237,12 @@ async fn process_fetched_events(
1188 }); 1237 });
1189 if update_to_existing { 1238 if update_to_existing {
1190 report.updated_repo_announcements.push(( 1239 report.updated_repo_announcements.push((
1191 Coordinate { 1240 Nip19Coordinate {
1192 kind: event.kind, 1241 coordinate: Coordinate {
1193 public_key: event.pubkey, 1242 kind: event.kind,
1194 identifier: event.tags.identifier().unwrap().to_owned(), 1243 public_key: event.pubkey,
1244 identifier: event.tags.identifier().unwrap().to_owned(),
1245 },
1195 relays: vec![], 1246 relays: vec![],
1196 }, 1247 },
1197 event.created_at, 1248 event.created_at,
@@ -1204,14 +1255,16 @@ async fn process_fetched_events(
1204 .repo_coordinates_without_relays // prexisting maintainers 1255 .repo_coordinates_without_relays // prexisting maintainers
1205 .iter() 1256 .iter()
1206 .map(|(c, _)| c.clone()) 1257 .map(|(c, _)| c.clone())
1207 .collect::<HashSet<Coordinate>>() 1258 .collect::<HashSet<Nip19Coordinate>>()
1208 .union(&report.repo_coordinates_without_relays) // already added maintainers 1259 .union(&report.repo_coordinates_without_relays) // already added maintainers
1209 .any(|c| c.identifier.eq(&repo_ref.identifier) && m.eq(&c.public_key)) 1260 .any(|c| c.identifier.eq(&repo_ref.identifier) && m.eq(&c.public_key))
1210 { 1261 {
1211 let c = Coordinate { 1262 let c = Nip19Coordinate {
1212 kind: event.kind, 1263 coordinate: Coordinate {
1213 public_key: *m, 1264 kind: event.kind,
1214 identifier: repo_ref.identifier.clone(), 1265 public_key: *m,
1266 identifier: repo_ref.identifier.clone(),
1267 },
1215 relays: vec![], 1268 relays: vec![],
1216 }; 1269 };
1217 fresh_coordinates.insert(c.clone()); 1270 fresh_coordinates.insert(c.clone());
@@ -1343,7 +1396,7 @@ pub fn consolidate_fetch_reports(reports: Vec<Result<FetchReport>>) -> FetchRepo
1343 report 1396 report
1344} 1397}
1345pub fn get_fetch_filters( 1398pub fn get_fetch_filters(
1346 repo_coordinates: &HashSet<Coordinate>, 1399 repo_coordinates: &HashSet<Nip19Coordinate>,
1347 proposal_ids: &HashSet<EventId>, 1400 proposal_ids: &HashSet<EventId>,
1348 required_profiles: &HashSet<PublicKey>, 1401 required_profiles: &HashSet<PublicKey>,
1349) -> Vec<nostr::Filter> { 1402) -> Vec<nostr::Filter> {
@@ -1356,11 +1409,11 @@ pub fn get_fetch_filters(
1356 get_filter_repo_events(repo_coordinates), 1409 get_filter_repo_events(repo_coordinates),
1357 nostr::Filter::default() 1410 nostr::Filter::default()
1358 .kinds(vec![Kind::GitPatch, Kind::EventDeletion]) 1411 .kinds(vec![Kind::GitPatch, Kind::EventDeletion])
1359 .custom_tag( 1412 .custom_tags(
1360 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A), 1413 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A),
1361 repo_coordinates 1414 repo_coordinates
1362 .iter() 1415 .iter()
1363 .map(std::string::ToString::to_string) 1416 .map(|c| c.coordinate.to_string())
1364 .collect::<Vec<String>>(), 1417 .collect::<Vec<String>>(),
1365 ), 1418 ),
1366 ] 1419 ]
@@ -1383,7 +1436,7 @@ pub fn get_fetch_filters(
1383 .concat() 1436 .concat()
1384} 1437}
1385 1438
1386pub fn get_filter_repo_events(repo_coordinates: &HashSet<Coordinate>) -> nostr::Filter { 1439pub fn get_filter_repo_events(repo_coordinates: &HashSet<Nip19Coordinate>) -> nostr::Filter {
1387 nostr::Filter::default() 1440 nostr::Filter::default()
1388 .kind(Kind::GitRepoAnnouncement) 1441 .kind(Kind::GitRepoAnnouncement)
1389 .identifiers( 1442 .identifiers(
@@ -1401,7 +1454,7 @@ pub fn get_filter_repo_events(repo_coordinates: &HashSet<Coordinate>) -> nostr::
1401} 1454}
1402 1455
1403pub static STATE_KIND: nostr::Kind = Kind::Custom(30618); 1456pub static STATE_KIND: nostr::Kind = Kind::Custom(30618);
1404pub fn get_filter_state_events(repo_coordinates: &HashSet<Coordinate>) -> nostr::Filter { 1457pub fn get_filter_state_events(repo_coordinates: &HashSet<Nip19Coordinate>) -> nostr::Filter {
1405 nostr::Filter::default() 1458 nostr::Filter::default()
1406 .kind(STATE_KIND) 1459 .kind(STATE_KIND)
1407 .identifiers( 1460 .identifiers(
@@ -1426,8 +1479,8 @@ pub fn get_filter_contributor_profiles(contributors: HashSet<PublicKey>) -> nost
1426 1479
1427#[derive(Default)] 1480#[derive(Default)]
1428pub struct FetchReport { 1481pub struct FetchReport {
1429 repo_coordinates_without_relays: HashSet<Coordinate>, 1482 repo_coordinates_without_relays: HashSet<Nip19Coordinate>,
1430 updated_repo_announcements: Vec<(Coordinate, Timestamp)>, 1483 updated_repo_announcements: Vec<(Nip19Coordinate, Timestamp)>,
1431 updated_state: Option<(Timestamp, EventId)>, 1484 updated_state: Option<(Timestamp, EventId)>,
1432 proposals: HashSet<EventId>, 1485 proposals: HashSet<EventId>,
1433 /// commits against existing propoals 1486 /// commits against existing propoals
@@ -1518,7 +1571,7 @@ pub struct FetchRequest {
1518 repo_relays: HashSet<RelayUrl>, 1571 repo_relays: HashSet<RelayUrl>,
1519 selected_relay: Option<RelayUrl>, 1572 selected_relay: Option<RelayUrl>,
1520 relay_column_width: usize, 1573 relay_column_width: usize,
1521 repo_coordinates_without_relays: Vec<(Coordinate, Option<Timestamp>)>, 1574 repo_coordinates_without_relays: Vec<(Nip19Coordinate, Option<Timestamp>)>,
1522 state: Option<(Timestamp, EventId)>, 1575 state: Option<(Timestamp, EventId)>,
1523 proposals: HashSet<EventId>, 1576 proposals: HashSet<EventId>,
1524 contributors: HashSet<PublicKey>, 1577 contributors: HashSet<PublicKey>,
@@ -1532,7 +1585,7 @@ pub async fn fetching_with_report(
1532 git_repo_path: &Path, 1585 git_repo_path: &Path,
1533 #[cfg(test)] client: &crate::client::MockConnect, 1586 #[cfg(test)] client: &crate::client::MockConnect,
1534 #[cfg(not(test))] client: &Client, 1587 #[cfg(not(test))] client: &Client,
1535 trusted_maintainer_coordinate: &Coordinate, 1588 trusted_maintainer_coordinate: &Nip19Coordinate,
1536) -> Result<FetchReport> { 1589) -> Result<FetchReport> {
1537 let term = console::Term::stderr(); 1590 let term = console::Term::stderr();
1538 term.write_line("fetching updates...")?; 1591 term.write_line("fetching updates...")?;
@@ -1557,16 +1610,16 @@ pub async fn fetching_with_report(
1557 1610
1558pub async fn get_proposals_and_revisions_from_cache( 1611pub async fn get_proposals_and_revisions_from_cache(
1559 git_repo_path: &Path, 1612 git_repo_path: &Path,
1560 repo_coordinates: HashSet<Coordinate>, 1613 repo_coordinates: HashSet<Nip19Coordinate>,
1561) -> Result<Vec<nostr::Event>> { 1614) -> Result<Vec<nostr::Event>> {
1562 let mut proposals = get_events_from_local_cache(git_repo_path, vec![ 1615 let mut proposals = get_events_from_local_cache(git_repo_path, vec![
1563 nostr::Filter::default() 1616 nostr::Filter::default()
1564 .kind(nostr::Kind::GitPatch) 1617 .kind(nostr::Kind::GitPatch)
1565 .custom_tag( 1618 .custom_tags(
1566 nostr::SingleLetterTag::lowercase(nostr_sdk::Alphabet::A), 1619 nostr::SingleLetterTag::lowercase(nostr_sdk::Alphabet::A),
1567 repo_coordinates 1620 repo_coordinates
1568 .iter() 1621 .iter()
1569 .map(std::string::ToString::to_string) 1622 .map(|c| c.coordinate.to_string())
1570 .collect::<Vec<String>>(), 1623 .collect::<Vec<String>>(),
1571 ), 1624 ),
1572 ]) 1625 ])