|
70 | 70 | } |
71 | 71 | } |
72 | 72 |
|
| 73 | +impl Contact { |
| 74 | + /// Returns the relays to use for this contact of the specified type |
| 75 | + /// If the contact has no relays of the specified type, it will fallback to nip65 relays |
| 76 | + /// If the contact has no nip65 relays, it will fallback to default relays |
| 77 | + pub fn get_relays_of_type(&self, relay_type: RelayType) -> DashSet<RelayUrl> { |
| 78 | + let relays = match relay_type { |
| 79 | + RelayType::Nostr => &self.nip65_relays, |
| 80 | + RelayType::Inbox => &self.inbox_relays, |
| 81 | + RelayType::KeyPackage => &self.key_package_relays, |
| 82 | + }; |
| 83 | + |
| 84 | + if relays.is_empty() { |
| 85 | + self.relay_fallback(relay_type) |
| 86 | + } else { |
| 87 | + relays.clone() |
| 88 | + } |
| 89 | + } |
| 90 | + |
| 91 | + fn relay_fallback(&self, relay_type: RelayType) -> DashSet<RelayUrl> { |
| 92 | + match relay_type { |
| 93 | + RelayType::Nostr => Account::default_relays(), |
| 94 | + RelayType::Inbox => self.get_relays_of_type(RelayType::Nostr), |
| 95 | + RelayType::KeyPackage => self.get_relays_of_type(RelayType::Nostr), |
| 96 | + } |
| 97 | + } |
| 98 | +} |
| 99 | + |
73 | 100 | impl Whitenoise { |
74 | 101 | // ============================================================================ |
75 | 102 | // CONTACT MANAGEMENT |
@@ -700,4 +727,123 @@ mod tests { |
700 | 727 | .get_nostr_keys_for_pubkey(&account.pubkey); |
701 | 728 | assert!(signing_keys_result.is_err()); |
702 | 729 | } |
| 730 | + |
| 731 | + #[tokio::test] |
| 732 | + async fn test_get_relays_of_type() { |
| 733 | + use crate::whitenoise::Whitenoise; |
| 734 | + use crate::RelayType; |
| 735 | + use dashmap::DashSet; |
| 736 | + use nostr_sdk::RelayUrl; |
| 737 | + |
| 738 | + // Create test relay URLs |
| 739 | + let nip65_relay = RelayUrl::parse("wss://relay.damus.io").unwrap(); |
| 740 | + let inbox_relay = RelayUrl::parse("wss://inbox.relay.com").unwrap(); |
| 741 | + let key_package_relay = RelayUrl::parse("wss://keypackage.relay.com").unwrap(); |
| 742 | + |
| 743 | + // Create contact with different relay types |
| 744 | + let contact = super::Contact { |
| 745 | + pubkey: create_test_keys().public_key(), |
| 746 | + metadata: None, |
| 747 | + nip65_relays: { |
| 748 | + let set = DashSet::new(); |
| 749 | + set.insert(nip65_relay.clone()); |
| 750 | + set |
| 751 | + }, |
| 752 | + inbox_relays: { |
| 753 | + let set = DashSet::new(); |
| 754 | + set.insert(inbox_relay.clone()); |
| 755 | + set |
| 756 | + }, |
| 757 | + key_package_relays: { |
| 758 | + let set = DashSet::new(); |
| 759 | + set.insert(key_package_relay.clone()); |
| 760 | + set |
| 761 | + }, |
| 762 | + }; |
| 763 | + |
| 764 | + // Test getting each relay type |
| 765 | + let nip65_relays = contact.get_relays_of_type(RelayType::Nostr); |
| 766 | + assert!(Whitenoise::relayurl_dashset_eq( |
| 767 | + nip65_relays, |
| 768 | + DashSet::from_iter([nip65_relay]) |
| 769 | + )); |
| 770 | + |
| 771 | + let inbox_relays = contact.get_relays_of_type(RelayType::Inbox); |
| 772 | + assert!(Whitenoise::relayurl_dashset_eq( |
| 773 | + inbox_relays, |
| 774 | + DashSet::from_iter([inbox_relay]) |
| 775 | + )); |
| 776 | + |
| 777 | + let key_package_relays = contact.get_relays_of_type(RelayType::KeyPackage); |
| 778 | + assert!(Whitenoise::relayurl_dashset_eq( |
| 779 | + key_package_relays, |
| 780 | + DashSet::from_iter([key_package_relay]) |
| 781 | + )); |
| 782 | + } |
| 783 | + |
| 784 | + #[tokio::test] |
| 785 | + async fn test_get_relays_of_type_empty_fallback() { |
| 786 | + use crate::whitenoise::accounts::Account; |
| 787 | + use crate::whitenoise::Whitenoise; |
| 788 | + use crate::RelayType; |
| 789 | + use dashmap::DashSet; |
| 790 | + |
| 791 | + // Create contact with empty relay sets |
| 792 | + let contact = super::Contact { |
| 793 | + pubkey: create_test_keys().public_key(), |
| 794 | + metadata: None, |
| 795 | + nip65_relays: DashSet::new(), |
| 796 | + inbox_relays: DashSet::new(), |
| 797 | + key_package_relays: DashSet::new(), |
| 798 | + }; |
| 799 | + |
| 800 | + // Test that empty relays fallback to default_relays |
| 801 | + let nip65_relays = contact.get_relays_of_type(RelayType::Nostr); |
| 802 | + let default_relays = Account::default_relays(); |
| 803 | + assert!(Whitenoise::relayurl_dashset_eq( |
| 804 | + nip65_relays, |
| 805 | + default_relays.clone() |
| 806 | + )); |
| 807 | + |
| 808 | + let inbox_relays = contact.get_relays_of_type(RelayType::Inbox); |
| 809 | + assert!(Whitenoise::relayurl_dashset_eq( |
| 810 | + inbox_relays, |
| 811 | + default_relays.clone() |
| 812 | + )); |
| 813 | + |
| 814 | + let key_package_relays = contact.get_relays_of_type(RelayType::KeyPackage); |
| 815 | + assert!(Whitenoise::relayurl_dashset_eq( |
| 816 | + key_package_relays, |
| 817 | + default_relays |
| 818 | + )); |
| 819 | + } |
| 820 | + |
| 821 | + #[tokio::test] |
| 822 | + async fn test_get_relays_of_type_fallback_goes_to_nip65_if_available() { |
| 823 | + use crate::whitenoise::Whitenoise; |
| 824 | + use crate::RelayType; |
| 825 | + use dashmap::DashSet; |
| 826 | + |
| 827 | + let nip65_relay = RelayUrl::parse("wss://relay.damus.io").unwrap(); |
| 828 | + |
| 829 | + let contact = super::Contact { |
| 830 | + pubkey: create_test_keys().public_key(), |
| 831 | + metadata: None, |
| 832 | + nip65_relays: DashSet::from_iter([nip65_relay.clone()]), |
| 833 | + inbox_relays: DashSet::new(), |
| 834 | + key_package_relays: DashSet::new(), |
| 835 | + }; |
| 836 | + |
| 837 | + let inbox_relays = contact.get_relays_of_type(RelayType::Inbox); |
| 838 | + assert!(Whitenoise::relayurl_dashset_eq( |
| 839 | + inbox_relays, |
| 840 | + DashSet::from_iter([nip65_relay.clone()]) |
| 841 | + )); |
| 842 | + |
| 843 | + let key_package_relays = contact.get_relays_of_type(RelayType::KeyPackage); |
| 844 | + assert!(Whitenoise::relayurl_dashset_eq( |
| 845 | + key_package_relays, |
| 846 | + DashSet::from_iter([nip65_relay]) |
| 847 | + )); |
| 848 | + } |
703 | 849 | } |
0 commit comments