// Package directory_client provides a client library for the Distributed // Directory Consensus Protocol (NIP-XX). // // This package offers a high-level API for working with directory events, // managing identity resolution, tracking key delegations, and computing // trust scores. It builds on the lower-level directory protocol package. // // # Basic Usage // // // Create an identity resolver // resolver := directory_client.NewIdentityResolver() // // // Parse and track events // event := getDirectoryEvent() // resolver.ProcessEvent(event) // // // Resolve identity behind a delegate key // actualIdentity := resolver.ResolveIdentity(delegateKey) // // // Check if a key is a delegate // isDelegate := resolver.IsDelegateKey(pubkey) // // # Trust Management // // // Create a trust calculator // calculator := directory_client.NewTrustCalculator() // // // Add trust acts // trustAct := directory.ParseTrustAct(event) // calculator.AddAct(trustAct) // // // Calculate aggregate trust score // score := calculator.CalculateTrust(targetPubkey) // // # Replication Filtering // // // Create a replication filter // filter := directory_client.NewReplicationFilter(50) // min trust score of 50 // // // Add trust acts to influence replication decisions // filter.AddTrustAct(trustAct) // // // Check if should replicate from a relay // if filter.ShouldReplicate(relayPubkey) { // // Proceed with replication // } // // # Event Filtering // // // Filter directory events from a stream // events := getEvents() // directoryEvents := directory_client.FilterDirectoryEvents(events) // // // Check if an event is a directory event // if directory_client.IsDirectoryEvent(event) { // // Handle directory event // } package directory_client import ( "lol.mleku.dev/errorf" "git.mleku.dev/mleku/nostr/encoders/event" "next.orly.dev/pkg/protocol/directory" ) // IsDirectoryEvent checks if an event is a directory consensus event. func IsDirectoryEvent(ev *event.E) bool { if ev == nil { return false } k := uint16(ev.Kind) return k == 39100 || k == 39101 || k == 39102 || k == 39103 || k == 39104 || k == 39105 } // FilterDirectoryEvents filters a slice of events to only directory events. func FilterDirectoryEvents(events []*event.E) (filtered []*event.E) { filtered = make([]*event.E, 0) for _, ev := range events { if IsDirectoryEvent(ev) { filtered = append(filtered, ev) } } return } // NormalizeRelayURL ensures a relay URL has the canonical format with trailing slash. func NormalizeRelayURL(url string) string { if url == "" { return "" } if url[len(url)-1] != '/' { return url + "/" } return url } // ParseDirectoryEvent parses any directory event based on its kind. func ParseDirectoryEvent(ev *event.E) (parsed interface{}, err error) { if !IsDirectoryEvent(ev) { return nil, errorf.E("not a directory event: kind %d", uint16(ev.Kind)) } switch uint16(ev.Kind) { case 39100: return directory.ParseRelayIdentityAnnouncement(ev) case 39101: return directory.ParseTrustAct(ev) case 39102: return directory.ParseGroupTagAct(ev) case 39103: return directory.ParsePublicKeyAdvertisement(ev) case 39104: return directory.ParseDirectoryEventReplicationRequest(ev) case 39105: return directory.ParseDirectoryEventReplicationResponse(ev) default: return nil, errorf.E("unknown directory event kind: %d", uint16(ev.Kind)) } }