Refactor Nostr Client and Update Dependencies

- Replaced NDKPrivateKeySigner with PrivateKeySigner from applesauce-signers for improved signing functionality.
- Updated the Nostr client implementation to utilize nostr-tools for event management and connection pooling.
- Enhanced event fetching logic to support multiple versions of replaceable events based on limit parameters.
- Updated package dependencies in package.json and bun.lock, including the addition of applesauce-core and applesauce-signers.
- Refined event kind definitions and improved documentation for clarity and consistency with NIP specifications.
- Adjusted CSS styles in bundle.css for better visual consistency across components.
This commit is contained in:
2025-10-25 17:27:25 +01:00
parent badac55813
commit c5ff2c648c
13 changed files with 901 additions and 1436 deletions

View File

@@ -51,6 +51,10 @@ func (d *D) QueryAllVersions(c context.Context, f *filter.F) (
func (d *D) QueryEventsWithOptions(c context.Context, f *filter.F, includeDeleteEvents bool, showAllVersions bool) (
evs event.S, err error,
) {
// Determine if we should return multiple versions of replaceable events
// based on the limit parameter
wantMultipleVersions := showAllVersions || (f.Limit != nil && *f.Limit > 1)
// if there is Ids in the query, this overrides anything else
var expDeletes types.Uint40s
var expEvs event.S
@@ -135,11 +139,15 @@ func (d *D) QueryEventsWithOptions(c context.Context, f *filter.F, includeDelete
return
}
// log.T.F("QueryEvents: QueryForIds returned %d candidates", len(idPkTs))
// Create a map to store the latest version of replaceable events
// Create a map to store versions of replaceable events
// If wantMultipleVersions is true, we keep multiple versions (sorted by timestamp)
// Otherwise, we keep only the latest
replaceableEvents := make(map[string]*event.E)
replaceableEventVersions := make(map[string]event.S) // For multiple versions
// Create a map to store the latest version of parameterized replaceable
// events
paramReplaceableEvents := make(map[string]map[string]*event.E)
paramReplaceableEventVersions := make(map[string]map[string]event.S) // For multiple versions
// Regular events that are not replaceable
var regularEvents event.S
// Map to track deletion events by kind and pubkey (for replaceable
@@ -435,11 +443,11 @@ func (d *D) QueryEventsWithOptions(c context.Context, f *filter.F, includeDelete
if deletionsByKindPubkey[key] && !isIdInFilter {
// This replaceable event has been deleted, skip it
continue
} else if showAllVersions {
// If showAllVersions is true, treat replaceable events as regular events
regularEvents = append(regularEvents, ev)
} else if wantMultipleVersions {
// If wantMultipleVersions is true, collect all versions
replaceableEventVersions[key] = append(replaceableEventVersions[key], ev)
} else {
// Normal replaceable event handling
// Normal replaceable event handling - keep only the newest
existing, exists := replaceableEvents[key]
if !exists || ev.CreatedAt > existing.CreatedAt {
replaceableEvents[key] = ev
@@ -469,9 +477,12 @@ func (d *D) QueryEventsWithOptions(c context.Context, f *filter.F, includeDelete
}
}
if showAllVersions {
// If showAllVersions is true, treat parameterized replaceable events as regular events
regularEvents = append(regularEvents, ev)
if wantMultipleVersions {
// If wantMultipleVersions is true, collect all versions
if _, exists := paramReplaceableEventVersions[key]; !exists {
paramReplaceableEventVersions[key] = make(map[string]event.S)
}
paramReplaceableEventVersions[key][dValue] = append(paramReplaceableEventVersions[key][dValue], ev)
} else {
// Initialize the inner map if it doesn't exist
if _, exists := paramReplaceableEvents[key]; !exists {
@@ -496,14 +507,57 @@ func (d *D) QueryEventsWithOptions(c context.Context, f *filter.F, includeDelete
}
}
// Add all the latest replaceable events to the result
for _, ev := range replaceableEvents {
evs = append(evs, ev)
if wantMultipleVersions {
// Add all versions (sorted by timestamp, newest first)
for key, versions := range replaceableEventVersions {
// Sort versions by timestamp (newest first)
sort.Slice(versions, func(i, j int) bool {
return versions[i].CreatedAt > versions[j].CreatedAt
})
// Add versions up to the limit
limit := len(versions)
if f.Limit != nil && int(*f.Limit) < limit {
limit = int(*f.Limit)
}
for i := 0; i < limit && i < len(versions); i++ {
evs = append(evs, versions[i])
}
_ = key // Use key to avoid unused variable warning
}
} else {
// Add only the newest version of each replaceable event
for _, ev := range replaceableEvents {
evs = append(evs, ev)
}
}
// Add all the latest parameterized replaceable events to the result
for _, innerMap := range paramReplaceableEvents {
for _, ev := range innerMap {
evs = append(evs, ev)
if wantMultipleVersions {
// Add all versions (sorted by timestamp, newest first)
for key, dTagMap := range paramReplaceableEventVersions {
for dTag, versions := range dTagMap {
// Sort versions by timestamp (newest first)
sort.Slice(versions, func(i, j int) bool {
return versions[i].CreatedAt > versions[j].CreatedAt
})
// Add versions up to the limit
limit := len(versions)
if f.Limit != nil && int(*f.Limit) < limit {
limit = int(*f.Limit)
}
for i := 0; i < limit && i < len(versions); i++ {
evs = append(evs, versions[i])
}
_ = key // Use key to avoid unused variable warning
_ = dTag // Use dTag to avoid unused variable warning
}
}
} else {
// Add only the newest version of each parameterized replaceable event
for _, innerMap := range paramReplaceableEvents {
for _, ev := range innerMap {
evs = append(evs, ev)
}
}
}
// Add all regular events to the result

View File

@@ -73,7 +73,8 @@ var Privileged = []*K{
JWTBinding,
ApplicationSpecificData,
Seal,
PrivateDirectMessage,
DirectMessage,
FileMessage,
}
// IsPrivileged returns true if the type is the kind of message nobody else than
@@ -165,37 +166,50 @@ var (
// TextNote is a standard short text note of plain text a la twitter
TextNote = &K{1}
// RecommendServer is an event type that...
RecommendServer = &K{2}
RecommendRelay = &K{2}
RecommendRelay = &K{2}
// FollowList an event containing a list of pubkeys of users that should be
// shown as follows in a timeline.
FollowList = &K{3}
Follows = &K{3}
// EncryptedDirectMessage is an event type that...
EncryptedDirectMessage = &K{4}
// Deletion is an event type that...
Deletion = &K{5}
// EventDeletion is an event type that...
EventDeletion = &K{5}
Deletion = &K{5}
// Repost is an event type that...
Repost = &K{6}
// Reaction is an event type that...
Reaction = &K{7}
// BadgeAward is an event type
BadgeAward = &K{8}
// ChatMessage is an event type for NIP-C7 chat messages
ChatMessage = &K{9}
// GroupChatThreadedReply is deprecated
GroupChatThreadedReply = &K{10}
// Thread is an event type for NIP-7D threads
Thread = &K{11}
// GroupThreadReply is deprecated
GroupThreadReply = &K{12}
// Seal is an event that wraps a PrivateDirectMessage and is placed inside a
// GiftWrap or GiftWrapWithKind4
Seal = &K{13}
// PrivateDirectMessage is a nip-17 direct message with a different
// DirectMessage is a nip-17 direct message with a different
// construction. It doesn't actually appear as an event a relay might receive
// but only as the stringified content of a GiftWrap or GiftWrapWithKind4 inside
// a
PrivateDirectMessage = &K{14}
// ReadReceipt is a type of event that marks a list of tagged events (e
// tags) as being seen by the client, its distinctive feature is the
// "expiration" tag which indicates a time after which the marking expires
ReadReceipt = &K{15}
DirectMessage = &K{14}
// FileMessage is a NIP-17 file message
FileMessage = &K{15}
// GenericRepost is an event type that...
GenericRepost = &K{16}
// ReactionToWebsite is a reaction to a website
ReactionToWebsite = &K{17}
// Picture is an event type for NIP-68 picture-first feeds
Picture = &K{20}
// VideoEventHorizontal is for horizontal video events
VideoEventHorizontal = &K{34235}
// VideoEventVertical is for vertical video events
VideoEventVertical = &K{34236}
// ChannelCreation is an event type that...
ChannelCreation = &K{40}
// ChannelMetadata is an event type that...
@@ -338,87 +352,96 @@ var (
var MapMx sync.RWMutex
var Map = map[uint16]string{
ProfileMetadata.K: "ProfileMetadata",
TextNote.K: "TextNote",
RecommendRelay.K: "RecommendRelay",
FollowList.K: "FollowList",
EncryptedDirectMessage.K: "EncryptedDirectMessage",
EventDeletion.K: "EventDeletion",
Repost.K: "Repost",
Reaction.K: "Reaction",
BadgeAward.K: "BadgeAward",
ReadReceipt.K: "ReadReceipt",
GenericRepost.K: "GenericRepost",
ChannelCreation.K: "ChannelCreation",
ChannelMetadata.K: "ChannelMetadata",
ChannelMessage.K: "ChannelMessage",
ChannelHideMessage.K: "ChannelHideMessage",
ChannelMuteUser.K: "ChannelMuteUser",
Bid.K: "Bid",
BidConfirmation.K: "BidConfirmation",
OpenTimestamps.K: "OpenTimestamps",
FileMetadata.K: "FileMetadata",
LiveChatMessage.K: "LiveChatMessage",
ProblemTracker.K: "ProblemTracker",
Reporting.K: "Reporting",
Label.K: "Label",
CommunityPostApproval.K: "CommunityPostApproval",
JobRequestStart.K: "JobRequestStart",
JobRequestEnd.K: "JobRequestEnd",
JobResultStart.K: "JobResultStart",
JobResultEnd.K: "JobResultEnd",
JobFeedback.K: "JobFeedback",
ZapGoal.K: "ZapGoal",
ZapRequest.K: "ZapRequest",
Zap.K: "Zap",
Highlights.K: "Highlights",
BlockList.K: "BlockList",
PinList.K: "PinList",
RelayListMetadata.K: "RelayListMetadata",
BookmarkList.K: "BookmarkList",
CommunitiesList.K: "CommunitiesList",
PublicChatsList.K: "PublicChatsList",
BlockedRelaysList.K: "BlockedRelaysList",
SearchRelaysList.K: "SearchRelaysList",
InterestsList.K: "InterestsList",
UserEmojiList.K: "UserEmojiList",
DMRelaysList.K: "DMRelaysList",
FileStorageServerList.K: "FileStorageServerList",
NWCWalletServiceInfo.K: "NWCWalletServiceInfo",
LightningPubRPC.K: "LightningPubRPC",
ClientAuthentication.K: "ClientAuthentication",
WalletRequest.K: "WalletRequest",
WalletResponse.K: "WalletResponse",
WalletNotificationNip4.K: "WalletNotificationNip4",
WalletNotification.K: "WalletNotification",
NostrConnect.K: "NostrConnect",
HTTPAuth.K: "HTTPAuth",
FollowSets.K: "FollowSets",
GenericLists.K: "GenericLists",
RelaySets.K: "RelaySets",
BookmarkSets.K: "BookmarkSets",
CurationSets.K: "CurationSets",
ProfileBadges.K: "ProfileBadges",
BadgeDefinition.K: "BadgeDefinition",
InterestSets.K: "InterestSets",
StallDefinition.K: "StallDefinition",
ProductDefinition.K: "ProductDefinition",
MarketplaceUIUX.K: "MarketplaceUIUX",
ProductSoldAsAuction.K: "ProductSoldAsAuction",
LongFormContent.K: "LongFormContent",
DraftLongFormContent.K: "DraftLongFormContent",
EmojiSets.K: "EmojiSets",
ApplicationSpecificData.K: "ApplicationSpecificData",
ParameterizedReplaceableEnd.K: "ParameterizedReplaceableEnd",
LiveEvent.K: "LiveEvent",
UserStatuses.K: "UserStatuses",
ClassifiedListing.K: "ClassifiedListing",
DraftClassifiedListing.K: "DraftClassifiedListing",
DateBasedCalendarEvent.K: "DateBasedCalendarEvent",
TimeBasedCalendarEvent.K: "TimeBasedCalendarEvent",
Calendar.K: "Calendar",
CalendarEventRSVP.K: "CalendarEventRSVP",
HandlerRecommendation.K: "HandlerRecommendation",
HandlerInformation.K: "HandlerInformation",
CommunityDefinition.K: "CommunityDefinition",
ProfileMetadata.K: "User Metadata",
TextNote.K: "Short Text Note",
RecommendRelay.K: "Recommend Relay",
FollowList.K: "Follows",
EncryptedDirectMessage.K: "Encrypted Direct Messages",
EventDeletion.K: "Event Deletion Request",
Repost.K: "Repost",
Reaction.K: "Reaction",
BadgeAward.K: "Badge Award",
ChatMessage.K: "Chat Message",
GroupChatThreadedReply.K: "Group Chat Threaded Reply",
Thread.K: "Thread",
GroupThreadReply.K: "Group Thread Reply",
Seal.K: "Seal",
DirectMessage.K: "Direct Message",
FileMessage.K: "File Message",
GenericRepost.K: "Generic Repost",
ReactionToWebsite.K: "Reaction to a website",
Picture.K: "Picture",
ChannelCreation.K: "Channel Creation",
ChannelMetadata.K: "Channel Metadata",
ChannelMessage.K: "Channel Message",
ChannelHideMessage.K: "Channel Hide Message",
ChannelMuteUser.K: "Channel Mute User",
Bid.K: "Bid",
BidConfirmation.K: "Bid Confirmation",
OpenTimestamps.K: "OpenTimestamps",
FileMetadata.K: "File Metadata",
LiveChatMessage.K: "Live Chat Message",
ProblemTracker.K: "Problem Tracker",
Reporting.K: "Reporting",
Label.K: "Label",
CommunityPostApproval.K: "Community Post Approval",
JobRequestStart.K: "Job Request",
JobRequestEnd.K: "Job Request",
JobResultStart.K: "Job Result",
JobResultEnd.K: "Job Result",
JobFeedback.K: "Job Feedback",
ZapGoal.K: "Zap Goal",
ZapRequest.K: "Zap Request",
Zap.K: "Zap",
Highlights.K: "Highlights",
BlockList.K: "Mute list",
PinList.K: "Pin list",
RelayListMetadata.K: "Relay List Metadata",
BookmarkList.K: "Bookmarks list",
CommunitiesList.K: "Communities list",
PublicChatsList.K: "Public Chats list",
BlockedRelaysList.K: "Blocked Relays list",
SearchRelaysList.K: "Search Relays list",
InterestsList.K: "Interests",
UserEmojiList.K: "User Emoji list",
DMRelaysList.K: "DM relays",
FileStorageServerList.K: "File Storage Server List",
NWCWalletServiceInfo.K: "Wallet Service Info",
LightningPubRPC.K: "Lightning pub RPC",
ClientAuthentication.K: "Client Authentication",
WalletRequest.K: "Wallet Request",
WalletResponse.K: "Wallet Response",
WalletNotificationNip4.K: "Wallet Notification",
WalletNotification.K: "Wallet Notification",
NostrConnect.K: "Nostr Connect",
HTTPAuth.K: "HTTP Auth",
FollowSets.K: "Follow sets",
GenericLists.K: "Generic lists",
RelaySets.K: "Relay sets",
BookmarkSets.K: "Bookmark sets",
CurationSets.K: "Curation sets",
ProfileBadges.K: "Profile Badges",
BadgeDefinition.K: "Badge Definition",
InterestSets.K: "Interest sets",
StallDefinition.K: "Stall Definition",
ProductDefinition.K: "Product Definition",
MarketplaceUIUX.K: "Marketplace UI/UX",
ProductSoldAsAuction.K: "Product sold as an auction",
LongFormContent.K: "Long-form Content",
DraftLongFormContent.K: "Draft Long-form Content",
EmojiSets.K: "Emoji sets",
ApplicationSpecificData.K: "Application-specific Data",
LiveEvent.K: "Live Event",
UserStatuses.K: "User Statuses",
ClassifiedListing.K: "Classified Listing",
DraftClassifiedListing.K: "Draft Classified Listing",
DateBasedCalendarEvent.K: "Date-Based Calendar Event",
TimeBasedCalendarEvent.K: "Time-Based Calendar Event",
Calendar.K: "Calendar",
CalendarEventRSVP.K: "Calendar Event RSVP",
HandlerRecommendation.K: "Handler recommendation",
HandlerInformation.K: "Handler information",
CommunityDefinition.K: "Community Definition",
VideoEventHorizontal.K: "Video Event Horizontal",
VideoEventVertical.K: "Video Event Vertical",
}

View File

@@ -45,31 +45,37 @@ var (
}
NIP3 = OpenTimestampsAttestations
EncryptedDirectMessage = NIP{
"Direct Message deprecated in favor of NIP-44", 4,
"Encrypted Direct Message -- unrecommended: deprecated in favor of NIP-17", 4,
}
NIP4 = EncryptedDirectMessage
MappingNostrKeysToDNS = NIP{
"Mapping Nostr keys to DNS-based identifiers", 5,
}
NIP5 = MappingNostrKeysToDNS
HandlingMentions = NIP{
"Handling Mentions deprecated in favor of NIP-27", 8,
}
NIP8 = HandlingMentions
EventDeletion = NIP{"Event Deletion", 9}
NIP9 = EventDeletion
RelayInformationDocument = NIP{"Client Information Document", 11}
NIP11 = RelayInformationDocument
GenericTagQueries = NIP{"Generic Tag Queries", 12}
NIP12 = GenericTagQueries
SubjectTag = NIP{"Subject tag in text events", 14}
NIP14 = SubjectTag
NostrMarketplace = NIP{
"Nostr Marketplace (for resilient marketplaces)", 15,
"Mapping Nostr keys to DNS-based internet identifiers", 5,
}
NIP5 = MappingNostrKeysToDNS
BasicKeyDerivation = NIP{"Basic key derivation from mnemonic seed phrase", 6}
NIP6 = BasicKeyDerivation
WindowNostrCapability = NIP{"window.nostr capability for web browsers", 7}
NIP7 = WindowNostrCapability
HandlingMentions = NIP{"Handling Mentions -- unrecommended: deprecated in favor of NIP-27", 8}
NIP8 = HandlingMentions
EventDeletion = NIP{"Event Deletion Request", 9}
NIP9 = EventDeletion
TextNotesAndThreads = NIP{"Text Notes and Threads", 10}
NIP10 = TextNotesAndThreads
RelayInformationDocument = NIP{"Relay Information Document", 11}
NIP11 = RelayInformationDocument
GenericTagQueries = NIP{"Generic Tag Queries", 12}
NIP12 = GenericTagQueries
ProofOfWork = NIP{"Proof of Work", 13}
NIP13 = ProofOfWork
SubjectTag = NIP{"Subject tag in text events", 14}
NIP14 = SubjectTag
NostrMarketplace = NIP{"Nostr Marketplace (for resilient marketplaces)", 15}
NIP15 = NostrMarketplace
EventTreatment = NIP{"EVent Treatment", 16}
EventTreatment = NIP{"Event Treatment", 16}
NIP16 = EventTreatment
PrivateDirectMessages = NIP{"Private Direct Messages", 17}
NIP17 = PrivateDirectMessages
Reposts = NIP{"Reposts", 18}
NIP18 = Reposts
Bech32EncodedEntities = NIP{"bech32-encoded entities", 19}
@@ -86,40 +92,50 @@ var (
NIP24 = ExtraMetadata
Reactions = NIP{"Reactions", 25}
NIP25 = Reactions
DelegatedEventSigning = NIP{"Delegated Event Signing", 26}
DelegatedEventSigning = NIP{"Delegated Event Signing -- unrecommended: adds unnecessary burden for little gain", 26}
NIP26 = DelegatedEventSigning
TextNoteReferences = NIP{"Text Note References", 27}
NIP27 = TextNoteReferences
PublicChat = NIP{"Public Chat", 28}
NIP28 = PublicChat
RelayBasedGroups = NIP{"Relay-based Groups", 29}
NIP29 = RelayBasedGroups
CustomEmoji = NIP{"Custom Emoji", 30}
NIP30 = CustomEmoji
DealingWithUnknownEvents = NIP{"Dealing with Unknown Events", 31}
NIP31 = DealingWithUnknownEvents
Labeling = NIP{"Labeling", 32}
NIP32 = Labeling
ParameterizedReplaceableEvents = NIP{"Parameterized Replaceable Events", 33}
NIP33 = ParameterizedReplaceableEvents
GitStuff = NIP{"git stuff", 34}
NIP34 = GitStuff
Torrents = NIP{"Torrents", 35}
NIP35 = Torrents
SensitiveContent = NIP{"Sensitive Content", 36}
NIP36 = SensitiveContent
DraftEvents = NIP{"Draft Events", 37}
NIP37 = DraftEvents
UserStatuses = NIP{"User Statuses", 38}
NIP38 = UserStatuses
ExternalIdentitiesInProfiles = NIP{"External Identities in Profiles", 39}
NIP39 = ExternalIdentitiesInProfiles
ExpirationTimestamp = NIP{"Expiration Timestamp", 40}
NIP40 = ExpirationTimestamp
Authentication = NIP{
"Authentication of clients to relays", 42,
}
Authentication = NIP{"Authentication of clients to relays", 42}
NIP42 = Authentication
VersionedEncryption = NIP{"Versioned Encryption", 44}
VersionedEncryption = NIP{"Encrypted Payloads (Versioned)", 44}
NIP44 = VersionedEncryption
CountingResults = NIP{"Counting results", 45}
NIP45 = CountingResults
NostrConnect = NIP{"Nostr Connect", 46}
NIP46 = NostrConnect
WalletConnect = NIP{"Wallet Connect", 47}
NostrRemoteSigning = NIP{"Nostr Remote Signing", 46}
NIP46 = NostrRemoteSigning
WalletConnect = NIP{"Nostr Wallet Connect", 47}
NIP47 = WalletConnect
ProxyTags = NIP{"Proxy Tags", 48}
NIP48 = ProxyTags
PrivateKeyEncryption = NIP{"Private Key Encryption", 49}
NIP49 = PrivateKeyEncryption
SearchCapability = NIP{"Search Capability", 50}
NIP50 = SearchCapability
Lists = NIP{"Lists", 51}
@@ -128,51 +144,97 @@ var (
NIP52 = CalendarEvents
LiveActivities = NIP{"Live Activities", 53}
NIP53 = LiveActivities
Wiki = NIP{"Wiki", 54}
NIP54 = Wiki
AndroidSignerApplication = NIP{"Android Signer Application", 55}
NIP55 = AndroidSignerApplication
Reporting = NIP{"Reporting", 56}
NIP56 = Reporting
LightningZaps = NIP{"Lightning Zaps", 57}
NIP57 = LightningZaps
Badges = NIP{"Badges", 58}
NIP58 = Badges
RelayListMetadata = NIP{"Client List Metadata", 65}
GiftWrap = NIP{"Gift Wrap", 59}
NIP59 = GiftWrap
CashuWallet = NIP{"Cashu Wallet", 60}
NIP60 = CashuWallet
Nutzaps = NIP{"Nutzaps", 61}
NIP61 = Nutzaps
RequestToVanish = NIP{"Request to Vanish", 62}
NIP62 = RequestToVanish
ChessPGN = NIP{"Chess (PGN)", 64}
NIP64 = ChessPGN
RelayListMetadata = NIP{"Relay List Metadata", 65}
NIP65 = RelayListMetadata
RelayDiscoveryAndLiveness = NIP{"Relay Discovery and Liveness Monitoring", 66}
NIP66 = RelayDiscoveryAndLiveness
PictureFirstFeeds = NIP{"Picture-first feeds", 68}
NIP68 = PictureFirstFeeds
PeerToPeerOrderEvents = NIP{"Peer-to-peer Order events", 69}
NIP69 = PeerToPeerOrderEvents
ProtectedEvents = NIP{"Protected Events", 70}
NIP70 = ProtectedEvents
VideoEvents = NIP{"Video Events", 71}
NIP71 = VideoEvents
ModeratedCommunities = NIP{"Moderated Communities", 72}
NIP72 = ModeratedCommunities
ExternalContentIDs = NIP{"External Content IDs", 73}
NIP73 = ExternalContentIDs
ZapGoals = NIP{"Zap Goals", 75}
NIP75 = ZapGoals
NegentropySync = NIP{"Negentropy Syncing", 77}
NIP77 = NegentropySync
ApplicationSpecificData = NIP{"Application-specific data", 78}
NIP78 = ApplicationSpecificData
Threads = NIP{"Threads", 0x7D}
NIP7D = Threads
Highlights = NIP{"Highlights", 84}
NIP84 = Highlights
RelayManagementAPI = NIP{"Relay Management API", 86}
NIP86 = RelayManagementAPI
EcashMintDiscoverability = NIP{"Ecash Mint Discoverability", 87}
NIP87 = EcashMintDiscoverability
Polls = NIP{"Polls", 88}
NIP88 = Polls
RecommendedApplicationHandlers = NIP{"Recommended Application Handlers", 89}
NIP89 = RecommendedApplicationHandlers
DataVendingMachines = NIP{"Data Vending Machines", 90}
NIP90 = DataVendingMachines
MediaAttachments = NIP{"Media Attachments", 92}
NIP92 = MediaAttachments
FileMetadata = NIP{"File Metadata", 94}
NIP94 = FileMetadata
HTTPFileStorageIntegration = NIP{"HTTP File Storage Integration", 96}
HTTPFileStorageIntegration = NIP{"HTTP File Storage Integration -- unrecommended: replaced by blossom APIs", 96}
NIP96 = HTTPFileStorageIntegration
HTTPAuth = NIP{"HTTP IsAuthed", 98}
HTTPAuth = NIP{"HTTP Auth", 98}
NIP98 = HTTPAuth
ClassifiedListings = NIP{"Classified Listings", 99}
NIP99 = ClassifiedListings
VoiceMessages = NIP{"Voice Messages", 0xA0}
NIPA0 = VoiceMessages
WebBookmarks = NIP{"Web Bookmarks", 0xB0}
NIPB0 = WebBookmarks
Blossom = NIP{"Blossom", 0xB7}
NIPB7 = Blossom
CodeSnippets = NIP{"Code Snippets", 0xC0}
NIPC0 = CodeSnippets
Chats = NIP{"Chats", 0xC7}
NIPC7 = Chats
E2EEMessagingUsingMLSProtocol = NIP{"E2EE Messaging using MLS Protocol", 0xEE}
NIPEE = E2EEMessagingUsingMLSProtocol
)
var NIPMap = map[int]NIP{
1: NIP1, 2: NIP2, 3: NIP3, 4: NIP4, 5: NIP5, 8: NIP8, 9: NIP9,
11: NIP11, 12: NIP12, 14: NIP14, 15: NIP15, 16: NIP16, 18: NIP18, 19: NIP19,
20: NIP20,
21: NIP21, 22: NIP22, 23: NIP23, 24: NIP24, 25: NIP25, 26: NIP26, 27: NIP27,
28: NIP28,
30: NIP30, 32: NIP32, 33: NIP33, 36: NIP36, 38: NIP38, 39: NIP39, 40: NIP40,
42: NIP42,
44: NIP44, 45: NIP45, 46: NIP46, 47: NIP47, 48: NIP48, 50: NIP50, 51: NIP51,
52: NIP52,
53: NIP53, 56: NIP56, 57: NIP57, 58: NIP58, 65: NIP65, 72: NIP72, 75: NIP75,
78: NIP78,
84: NIP84, 89: NIP89, 90: NIP90, 94: NIP94, 96: NIP96, 98: NIP98, 99: NIP99,
1: NIP1, 2: NIP2, 3: NIP3, 4: NIP4, 5: NIP5, 6: NIP6, 7: NIP7, 8: NIP8, 9: NIP9, 10: NIP10,
11: NIP11, 12: NIP12, 13: NIP13, 14: NIP14, 15: NIP15, 16: NIP16, 17: NIP17, 18: NIP18, 19: NIP19, 20: NIP20,
21: NIP21, 22: NIP22, 23: NIP23, 24: NIP24, 25: NIP25, 26: NIP26, 27: NIP27, 28: NIP28, 29: NIP29, 30: NIP30,
31: NIP31, 32: NIP32, 33: NIP33, 34: NIP34, 35: NIP35, 36: NIP36, 37: NIP37, 38: NIP38, 39: NIP39, 40: NIP40,
42: NIP42, 44: NIP44, 45: NIP45, 46: NIP46, 47: NIP47, 48: NIP48, 49: NIP49, 50: NIP50,
51: NIP51, 52: NIP52, 53: NIP53, 54: NIP54, 55: NIP55, 56: NIP56, 57: NIP57, 58: NIP58, 59: NIP59, 60: NIP60,
61: NIP61, 62: NIP62, 64: NIP64, 65: NIP65, 66: NIP66, 68: NIP68, 69: NIP69, 70: NIP70,
71: NIP71, 72: NIP72, 73: NIP73, 75: NIP75, 77: NIP77, 78: NIP78, 0x7D: NIP7D, 84: NIP84,
86: NIP86, 87: NIP87, 88: NIP88, 89: NIP89, 90: NIP90, 92: NIP92, 94: NIP94, 96: NIP96, 98: NIP98, 99: NIP99,
0xA0: NIPA0, 0xB0: NIPB0, 0xB7: NIPB7, 0xC0: NIPC0, 0xC7: NIPC7, 0xEE: NIPEE,
}
// Limits are rules about what is acceptable for events and filters on a relay.