diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-11-05 12:50:03 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-11-05 12:50:03 +0000 |
| commit | 64a86de9fc5ded51a1b5405223fc5dce16839fef (patch) | |
| tree | 9c981e337d3c3908776aa41c1eaff6c3e44cba14 /grasp-audit/src | |
| parent | 94bf5c39af0d8d0a9a15db240d5d46383ec22160 (diff) | |
Refactor: abstract announcement event creation into AuditClient helper
- Add create_repo_announcement() method to AuditClient
- Remove duplicate code from nip01_smoke.rs
- Update grasp01_nostr_relay.rs to use centralized helper
- All tests passing (GRASP-01: 4/18, NIP-01: 6/6)
Diffstat (limited to 'grasp-audit/src')
| -rw-r--r-- | grasp-audit/src/client.rs | 43 | ||||
| -rw-r--r-- | grasp-audit/src/specs/grasp01_nostr_relay.rs | 31 | ||||
| -rw-r--r-- | grasp-audit/src/specs/nip01_smoke.rs | 43 |
3 files changed, 59 insertions, 58 deletions
diff --git a/grasp-audit/src/client.rs b/grasp-audit/src/client.rs index b80b59f..7706ee3 100644 --- a/grasp-audit/src/client.rs +++ b/grasp-audit/src/client.rs | |||
| @@ -158,6 +158,49 @@ impl AuditClient { | |||
| 158 | pub fn keys(&self) -> &Keys { | 158 | pub fn keys(&self) -> &Keys { |
| 159 | &self.keys | 159 | &self.keys |
| 160 | } | 160 | } |
| 161 | |||
| 162 | /// Create a NIP-34 repository announcement event | ||
| 163 | /// | ||
| 164 | /// This helper creates a properly formatted NIP-34 announcement that will be | ||
| 165 | /// accepted by GRASP relays (which require events to list the relay in clone/relays tags). | ||
| 166 | /// | ||
| 167 | /// # Arguments | ||
| 168 | /// * `test_name` - Name of the test (used to create unique repo identifier) | ||
| 169 | /// | ||
| 170 | /// # Returns | ||
| 171 | /// A built and signed Event ready to be sent to the relay | ||
| 172 | pub async fn create_repo_announcement(&self, test_name: &str) -> Result<Event> { | ||
| 173 | // Get relay URL from client | ||
| 174 | let relay_url = self.client.relays().await | ||
| 175 | .keys() | ||
| 176 | .next() | ||
| 177 | .ok_or_else(|| anyhow!("No relay connected"))? | ||
| 178 | .to_string(); | ||
| 179 | |||
| 180 | // Convert WebSocket URL to HTTP URL for clone tag | ||
| 181 | let http_url = relay_url | ||
| 182 | .replace("ws://", "http://") | ||
| 183 | .replace("wss://", "https://"); | ||
| 184 | |||
| 185 | // Create unique repository identifier using UUID for consistency | ||
| 186 | let repo_id = format!("{}-{}", test_name, uuid::Uuid::new_v4()); | ||
| 187 | |||
| 188 | // Get npub for clone URL | ||
| 189 | let npub = self.public_key().to_bech32() | ||
| 190 | .map_err(|e| anyhow!("Failed to convert public key to bech32 npub format: {}", e))?; | ||
| 191 | |||
| 192 | // Build kind 30617 repository announcement | ||
| 193 | let event = self.event_builder(Kind::GitRepoAnnouncement, format!("Test repository for {}", test_name)) | ||
| 194 | .tag(Tag::identifier(&repo_id)) | ||
| 195 | .tag(Tag::custom(TagKind::custom("name"), vec![format!("{} Test Repository", test_name)])) | ||
| 196 | .tag(Tag::custom(TagKind::custom("description"), vec![format!("Repository for {} testing", test_name)])) | ||
| 197 | .tag(Tag::custom(TagKind::custom("clone"), vec![format!("{}/{}/{}.git", http_url, npub, repo_id)])) | ||
| 198 | .tag(Tag::custom(TagKind::custom("relays"), vec![relay_url.clone()])) | ||
| 199 | .build(self.keys()) | ||
| 200 | .map_err(|e| anyhow!("Failed to build repository announcement event: {}", e))?; | ||
| 201 | |||
| 202 | Ok(event) | ||
| 203 | } | ||
| 161 | } | 204 | } |
| 162 | 205 | ||
| 163 | #[cfg(test)] | 206 | #[cfg(test)] |
diff --git a/grasp-audit/src/specs/grasp01_nostr_relay.rs b/grasp-audit/src/specs/grasp01_nostr_relay.rs index 5a93672..837434b 100644 --- a/grasp-audit/src/specs/grasp01_nostr_relay.rs +++ b/grasp-audit/src/specs/grasp01_nostr_relay.rs | |||
| @@ -64,35 +64,28 @@ impl Grasp01NostrRelayTests { | |||
| 64 | "Accept valid repository announcements with service in clone and relays tags", | 64 | "Accept valid repository announcements with service in clone and relays tags", |
| 65 | ) | 65 | ) |
| 66 | .run(|| async { | 66 | .run(|| async { |
| 67 | // Get relay URL from client | 67 | // Create a NIP-34 repository announcement event |
| 68 | let event = client.create_repo_announcement("accept_valid_repo_announcement").await | ||
| 69 | .map_err(|e| format!("Failed to create repository announcement: {}", e))?; | ||
| 70 | |||
| 71 | // Get relay URL for validation | ||
| 68 | let relay_url = client.client().relays().await | 72 | let relay_url = client.client().relays().await |
| 69 | .keys() | 73 | .keys() |
| 70 | .next() | 74 | .next() |
| 71 | .ok_or("No relay connected")? | 75 | .ok_or("No relay connected")? |
| 72 | .to_string(); | 76 | .to_string(); |
| 73 | 77 | ||
| 74 | // Convert WebSocket URL to HTTP URL for clone tag | 78 | // Convert WebSocket URL to HTTP URL for validation |
| 75 | let http_url = relay_url | 79 | let http_url = relay_url |
| 76 | .replace("ws://", "http://") | 80 | .replace("ws://", "http://") |
| 77 | .replace("wss://", "https://"); | 81 | .replace("wss://", "https://"); |
| 78 | 82 | ||
| 79 | // Create unique repository identifier | 83 | // Extract repo_id from the event's d tag |
| 80 | let timestamp = Timestamp::now().as_u64(); | 84 | let repo_id = event.tags.iter() |
| 81 | let repo_id = format!("test-repo-{}", timestamp); | 85 | .find(|t| t.kind() == TagKind::d()) |
| 82 | 86 | .and_then(|t| t.content()) | |
| 83 | // Get npub for clone URL | 87 | .ok_or("Missing d tag in announcement")? |
| 84 | let npub = client.public_key().to_bech32() | 88 | .to_string(); |
| 85 | .map_err(|e| format!("Failed to convert public key to bech32 npub format: {}", e))?; | ||
| 86 | |||
| 87 | // Build kind 30617 repository announcement | ||
| 88 | let event = client.event_builder(Kind::GitRepoAnnouncement, "") | ||
| 89 | .tag(Tag::identifier(&repo_id)) | ||
| 90 | .tag(Tag::custom(TagKind::Custom("name".into()), vec!["GRASP-01 Test Repository"])) | ||
| 91 | .tag(Tag::custom(TagKind::Custom("description".into()), vec!["Test repository for GRASP-01 compliance testing"])) | ||
| 92 | .tag(Tag::custom(TagKind::Custom("clone".into()), vec![format!("{}/{}/{}.git", http_url, npub, repo_id)])) | ||
| 93 | .tag(Tag::custom(TagKind::Custom("relays".into()), vec![relay_url.clone()])) | ||
| 94 | .build(client.keys()) | ||
| 95 | .map_err(|e| format!("Failed to build repository announcement event (kind 30617): {}", e))?; | ||
| 96 | 89 | ||
| 97 | // Send the event | 90 | // Send the event |
| 98 | let event_id = client.send_event(event.clone()).await | 91 | let event_id = client.send_event(event.clone()).await |
diff --git a/grasp-audit/src/specs/nip01_smoke.rs b/grasp-audit/src/specs/nip01_smoke.rs index cb256c5..9ed0f56 100644 --- a/grasp-audit/src/specs/nip01_smoke.rs +++ b/grasp-audit/src/specs/nip01_smoke.rs | |||
| @@ -10,43 +10,6 @@ use nostr_sdk::prelude::*; | |||
| 10 | pub struct Nip01SmokeTests; | 10 | pub struct Nip01SmokeTests; |
| 11 | 11 | ||
| 12 | impl Nip01SmokeTests { | 12 | impl Nip01SmokeTests { |
| 13 | /// Create a NIP-34 repository announcement event | ||
| 14 | /// | ||
| 15 | /// This helper creates a properly formatted NIP-34 announcement that will be | ||
| 16 | /// accepted by GRASP relays (which require events to list the relay in clone/relays tags). | ||
| 17 | async fn create_announcement_event(client: &AuditClient, test_name: &str) -> Result<Event, String> { | ||
| 18 | // Get relay URL from client | ||
| 19 | let relay_url = client.client().relays().await | ||
| 20 | .keys() | ||
| 21 | .next() | ||
| 22 | .ok_or("No relay URL found")? | ||
| 23 | .to_string(); | ||
| 24 | |||
| 25 | // Convert ws:// to http:// for clone URL | ||
| 26 | let http_url = relay_url | ||
| 27 | .replace("ws://", "http://") | ||
| 28 | .replace("wss://", "https://"); | ||
| 29 | |||
| 30 | // Create unique repository identifier | ||
| 31 | let repo_id = format!("{}-{}", test_name, uuid::Uuid::new_v4()); | ||
| 32 | let npub = client.public_key().to_bech32() | ||
| 33 | .map_err(|e| format!("Failed to encode npub: {}", e))?; | ||
| 34 | |||
| 35 | // Create NIP-34 repository announcement (kind 30617) | ||
| 36 | // This event lists the GRASP server, so it should be accepted | ||
| 37 | let event = client | ||
| 38 | .event_builder(Kind::Custom(30617), format!("NIP-01 smoke test repository: {}", test_name)) | ||
| 39 | .tag(Tag::identifier(&repo_id)) // d tag | ||
| 40 | .tag(Tag::custom(TagKind::Custom("name".into()), vec![format!("{} Test Repo", test_name)])) | ||
| 41 | .tag(Tag::custom(TagKind::Custom("description".into()), vec![format!("Repository for {} smoke testing", test_name)])) | ||
| 42 | .tag(Tag::custom(TagKind::Custom("clone".into()), vec![format!("{}/{}/{}.git", http_url, npub, repo_id)])) | ||
| 43 | .tag(Tag::custom(TagKind::Custom("relays".into()), vec![relay_url.clone()])) | ||
| 44 | .build(client.keys()) | ||
| 45 | .map_err(|e| format!("Failed to build event: {}", e))?; | ||
| 46 | |||
| 47 | Ok(event) | ||
| 48 | } | ||
| 49 | |||
| 50 | /// Run all NIP-01 smoke tests | 13 | /// Run all NIP-01 smoke tests |
| 51 | pub async fn run_all(client: &AuditClient) -> AuditResult { | 14 | pub async fn run_all(client: &AuditClient) -> AuditResult { |
| 52 | let mut results = AuditResult::new("NIP-01 Smoke Tests"); | 15 | let mut results = AuditResult::new("NIP-01 Smoke Tests"); |
| @@ -97,7 +60,8 @@ impl Nip01SmokeTests { | |||
| 97 | ) | 60 | ) |
| 98 | .run(|| async { | 61 | .run(|| async { |
| 99 | // Create a NIP-34 announcement event | 62 | // Create a NIP-34 announcement event |
| 100 | let event = Self::create_announcement_event(client, "send_receive_event").await?; | 63 | let event = client.create_repo_announcement("send_receive_event").await |
| 64 | .map_err(|e| format!("Failed to create announcement: {}", e))?; | ||
| 101 | 65 | ||
| 102 | // Send event | 66 | // Send event |
| 103 | let event_id = client | 67 | let event_id = client |
| @@ -161,7 +125,8 @@ impl Nip01SmokeTests { | |||
| 161 | ) | 125 | ) |
| 162 | .run(|| async { | 126 | .run(|| async { |
| 163 | // Create a NIP-34 announcement event (accepted by GRASP relays) | 127 | // Create a NIP-34 announcement event (accepted by GRASP relays) |
| 164 | let event = Self::create_announcement_event(client, "create_subscription").await?; | 128 | let event = client.create_repo_announcement("create_subscription").await |
| 129 | .map_err(|e| format!("Failed to create announcement: {}", e))?; | ||
| 165 | 130 | ||
| 166 | let event_id = client | 131 | let event_id = client |
| 167 | .send_event(event.clone()) | 132 | .send_event(event.clone()) |