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)
This commit is contained in:
DanConwayDev
2025-11-05 12:50:03 +00:00
parent 94bf5c39af
commit 64a86de9fc
3 changed files with 59 additions and 58 deletions
+43
View File
@@ -158,6 +158,49 @@ impl AuditClient {
pub fn keys(&self) -> &Keys {
&self.keys
}
/// Create a NIP-34 repository announcement event
///
/// This helper creates a properly formatted NIP-34 announcement that will be
/// accepted by GRASP relays (which require events to list the relay in clone/relays tags).
///
/// # Arguments
/// * `test_name` - Name of the test (used to create unique repo identifier)
///
/// # Returns
/// A built and signed Event ready to be sent to the relay
pub async fn create_repo_announcement(&self, test_name: &str) -> Result<Event> {
// Get relay URL from client
let relay_url = self.client.relays().await
.keys()
.next()
.ok_or_else(|| anyhow!("No relay connected"))?
.to_string();
// Convert WebSocket URL to HTTP URL for clone tag
let http_url = relay_url
.replace("ws://", "http://")
.replace("wss://", "https://");
// Create unique repository identifier using UUID for consistency
let repo_id = format!("{}-{}", test_name, uuid::Uuid::new_v4());
// Get npub for clone URL
let npub = self.public_key().to_bech32()
.map_err(|e| anyhow!("Failed to convert public key to bech32 npub format: {}", e))?;
// Build kind 30617 repository announcement
let event = self.event_builder(Kind::GitRepoAnnouncement, format!("Test repository for {}", test_name))
.tag(Tag::identifier(&repo_id))
.tag(Tag::custom(TagKind::custom("name"), vec![format!("{} Test Repository", test_name)]))
.tag(Tag::custom(TagKind::custom("description"), vec![format!("Repository for {} testing", test_name)]))
.tag(Tag::custom(TagKind::custom("clone"), vec![format!("{}/{}/{}.git", http_url, npub, repo_id)]))
.tag(Tag::custom(TagKind::custom("relays"), vec![relay_url.clone()]))
.build(self.keys())
.map_err(|e| anyhow!("Failed to build repository announcement event: {}", e))?;
Ok(event)
}
}
#[cfg(test)]
+12 -19
View File
@@ -64,35 +64,28 @@ impl Grasp01NostrRelayTests {
"Accept valid repository announcements with service in clone and relays tags",
)
.run(|| async {
// Get relay URL from client
// Create a NIP-34 repository announcement event
let event = client.create_repo_announcement("accept_valid_repo_announcement").await
.map_err(|e| format!("Failed to create repository announcement: {}", e))?;
// Get relay URL for validation
let relay_url = client.client().relays().await
.keys()
.next()
.ok_or("No relay connected")?
.to_string();
// Convert WebSocket URL to HTTP URL for clone tag
// Convert WebSocket URL to HTTP URL for validation
let http_url = relay_url
.replace("ws://", "http://")
.replace("wss://", "https://");
// Create unique repository identifier
let timestamp = Timestamp::now().as_u64();
let repo_id = format!("test-repo-{}", timestamp);
// Get npub for clone URL
let npub = client.public_key().to_bech32()
.map_err(|e| format!("Failed to convert public key to bech32 npub format: {}", e))?;
// Build kind 30617 repository announcement
let event = client.event_builder(Kind::GitRepoAnnouncement, "")
.tag(Tag::identifier(&repo_id))
.tag(Tag::custom(TagKind::Custom("name".into()), vec!["GRASP-01 Test Repository"]))
.tag(Tag::custom(TagKind::Custom("description".into()), vec!["Test repository for GRASP-01 compliance testing"]))
.tag(Tag::custom(TagKind::Custom("clone".into()), vec![format!("{}/{}/{}.git", http_url, npub, repo_id)]))
.tag(Tag::custom(TagKind::Custom("relays".into()), vec![relay_url.clone()]))
.build(client.keys())
.map_err(|e| format!("Failed to build repository announcement event (kind 30617): {}", e))?;
// Extract repo_id from the event's d tag
let repo_id = event.tags.iter()
.find(|t| t.kind() == TagKind::d())
.and_then(|t| t.content())
.ok_or("Missing d tag in announcement")?
.to_string();
// Send the event
let event_id = client.send_event(event.clone()).await
+4 -39
View File
@@ -10,43 +10,6 @@ use nostr_sdk::prelude::*;
pub struct Nip01SmokeTests;
impl Nip01SmokeTests {
/// Create a NIP-34 repository announcement event
///
/// This helper creates a properly formatted NIP-34 announcement that will be
/// accepted by GRASP relays (which require events to list the relay in clone/relays tags).
async fn create_announcement_event(client: &AuditClient, test_name: &str) -> Result<Event, String> {
// Get relay URL from client
let relay_url = client.client().relays().await
.keys()
.next()
.ok_or("No relay URL found")?
.to_string();
// Convert ws:// to http:// for clone URL
let http_url = relay_url
.replace("ws://", "http://")
.replace("wss://", "https://");
// Create unique repository identifier
let repo_id = format!("{}-{}", test_name, uuid::Uuid::new_v4());
let npub = client.public_key().to_bech32()
.map_err(|e| format!("Failed to encode npub: {}", e))?;
// Create NIP-34 repository announcement (kind 30617)
// This event lists the GRASP server, so it should be accepted
let event = client
.event_builder(Kind::Custom(30617), format!("NIP-01 smoke test repository: {}", test_name))
.tag(Tag::identifier(&repo_id)) // d tag
.tag(Tag::custom(TagKind::Custom("name".into()), vec![format!("{} Test Repo", test_name)]))
.tag(Tag::custom(TagKind::Custom("description".into()), vec![format!("Repository for {} smoke testing", test_name)]))
.tag(Tag::custom(TagKind::Custom("clone".into()), vec![format!("{}/{}/{}.git", http_url, npub, repo_id)]))
.tag(Tag::custom(TagKind::Custom("relays".into()), vec![relay_url.clone()]))
.build(client.keys())
.map_err(|e| format!("Failed to build event: {}", e))?;
Ok(event)
}
/// Run all NIP-01 smoke tests
pub async fn run_all(client: &AuditClient) -> AuditResult {
let mut results = AuditResult::new("NIP-01 Smoke Tests");
@@ -97,7 +60,8 @@ impl Nip01SmokeTests {
)
.run(|| async {
// Create a NIP-34 announcement event
let event = Self::create_announcement_event(client, "send_receive_event").await?;
let event = client.create_repo_announcement("send_receive_event").await
.map_err(|e| format!("Failed to create announcement: {}", e))?;
// Send event
let event_id = client
@@ -161,7 +125,8 @@ impl Nip01SmokeTests {
)
.run(|| async {
// Create a NIP-34 announcement event (accepted by GRASP relays)
let event = Self::create_announcement_event(client, "create_subscription").await?;
let event = client.create_repo_announcement("create_subscription").await
.map_err(|e| format!("Failed to create announcement: {}", e))?;
let event_id = client
.send_event(event.clone())