Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/nip70-protected-event-util.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"nostream": patch
---

feat: add NIP-70 protected event detection utility
2 changes: 2 additions & 0 deletions src/constants/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ export enum EventTags {
AuthRelay = 'relay',
// Marmot Protocol MIP-03: group ID for filtering kind:445 Group Events
Group = 'h',
// NIP-70: Protected Events
Protected = '-',
}

export const ALL_RELAYS = 'ALL_RELAYS'
Expand Down
6 changes: 6 additions & 0 deletions src/utils/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,9 @@ export const isWelcomeRumorEvent = (event: Event): boolean => {
export const isMarmotGroupEvent = (event: Event): boolean => {
return event.kind === EventKinds.MARMOT_GROUP_EVENT
}

// NIP-70: Protected Events

export const isProtectedEvent = (event: Event): boolean => {
return event.tags.some((tag) => tag[0] === EventTags.Protected)
}
54 changes: 54 additions & 0 deletions test/unit/utils/event.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
isGiftWrapEvent,
isMarmotGroupEvent,
isParameterizedReplaceableEvent,
isProtectedEvent,
isReplaceableEvent,
isRequestToVanishEvent,
isSealEvent,
Expand Down Expand Up @@ -655,3 +656,56 @@ describe('NIP-40', () => {
})
})
})

describe('NIP-70', () => {
describe('isProtectedEvent', () => {
it('returns true if event has a ["-"] tag', () => {
const event: Event = {
tags: [['-']],
} as any
expect(isProtectedEvent(event)).to.be.true
})

it('returns true if protected tag has extra values', () => {
const event: Event = {
tags: [['-', 'some-reason']],
} as any
expect(isProtectedEvent(event)).to.be.true
})

it('returns false if event has no tags', () => {
const event: Event = {
tags: [],
} as any
expect(isProtectedEvent(event)).to.be.false
})

it('returns false if event has unrelated tags', () => {
const event: Event = {
tags: [
['e', '7377fa81fc6c7ae7f7f4ef8938d4a603f7bf98183b35ab128235cc92d4bebf96'],
['p', '22e804d26ed16b68db5259e78449e96dab5d464c8f470bda3eb1a70467f2c793'],
],
} as any
expect(isProtectedEvent(event)).to.be.false
})

it('returns false if "-" appears as a tag value, not a tag name', () => {
const event: Event = {
tags: [['e', '-']],
} as any
expect(isProtectedEvent(event)).to.be.false
})

it('returns true when protected tag is among other tags', () => {
const event: Event = {
tags: [
['e', '7377fa81fc6c7ae7f7f4ef8938d4a603f7bf98183b35ab128235cc92d4bebf96'],
['-'],
['p', '22e804d26ed16b68db5259e78449e96dab5d464c8f470bda3eb1a70467f2c793'],
],
} as any
expect(isProtectedEvent(event)).to.be.true
})
})
})
Loading