Nip58 Implementation (#386)
* implement nip58 * add tests for nip58 * export nip58 * bump version
This commit is contained in:
parent
5429142858
commit
59426d9f35
|
@ -0,0 +1,357 @@
|
||||||
|
import { expect, test } from 'bun:test'
|
||||||
|
|
||||||
|
import { EventTemplate } from './core.ts'
|
||||||
|
import {
|
||||||
|
BadgeAward as BadgeAwardKind,
|
||||||
|
BadgeDefinition as BadgeDefinitionKind,
|
||||||
|
ProfileBadges as ProfileBadgesKind,
|
||||||
|
} from './kinds.ts'
|
||||||
|
import { finalizeEvent, generateSecretKey } from './pure.ts'
|
||||||
|
|
||||||
|
import {
|
||||||
|
BadgeAward,
|
||||||
|
BadgeDefinition,
|
||||||
|
ProfileBadges,
|
||||||
|
generateBadgeAwardEventTemplate,
|
||||||
|
generateBadgeDefinitionEventTemplate,
|
||||||
|
generateProfileBadgesEventTemplate,
|
||||||
|
validateBadgeAwardEvent,
|
||||||
|
validateBadgeDefinitionEvent,
|
||||||
|
validateProfileBadgesEvent,
|
||||||
|
} from './nip58.ts'
|
||||||
|
|
||||||
|
test('BadgeDefinition has required property "d"', () => {
|
||||||
|
const badge: BadgeDefinition = {
|
||||||
|
d: 'badge-id',
|
||||||
|
}
|
||||||
|
expect(badge.d).toEqual('badge-id')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('BadgeDefinition has optional property "name"', () => {
|
||||||
|
const badge: BadgeDefinition = {
|
||||||
|
d: 'badge-id',
|
||||||
|
name: 'Badge Name',
|
||||||
|
}
|
||||||
|
expect(badge.name).toEqual('Badge Name')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('BadgeDefinition has optional property "description"', () => {
|
||||||
|
const badge: BadgeDefinition = {
|
||||||
|
d: 'badge-id',
|
||||||
|
description: 'Badge Description',
|
||||||
|
}
|
||||||
|
expect(badge.description).toEqual('Badge Description')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('BadgeDefinition has optional property "image"', () => {
|
||||||
|
const badge: BadgeDefinition = {
|
||||||
|
d: 'badge-id',
|
||||||
|
image: ['https://example.com/badge.png', '1024x1024'],
|
||||||
|
}
|
||||||
|
expect(badge.image).toEqual(['https://example.com/badge.png', '1024x1024'])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('BadgeDefinition has optional property "thumbs"', () => {
|
||||||
|
const badge: BadgeDefinition = {
|
||||||
|
d: 'badge-id',
|
||||||
|
thumbs: [
|
||||||
|
['https://example.com/thumb.png', '100x100'],
|
||||||
|
['https://example.com/thumb2.png', '200x200'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
expect(badge.thumbs).toEqual([
|
||||||
|
['https://example.com/thumb.png', '100x100'],
|
||||||
|
['https://example.com/thumb2.png', '200x200'],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('BadgeAward has required property "a"', () => {
|
||||||
|
const badgeAward: BadgeAward = {
|
||||||
|
a: 'badge-definition-address',
|
||||||
|
p: [
|
||||||
|
['pubkey1', 'relay1'],
|
||||||
|
['pubkey2', 'relay2'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
expect(badgeAward.a).toEqual('badge-definition-address')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('BadgeAward has required property "p"', () => {
|
||||||
|
const badgeAward: BadgeAward = {
|
||||||
|
a: 'badge-definition-address',
|
||||||
|
p: [
|
||||||
|
['pubkey1', 'relay1'],
|
||||||
|
['pubkey2', 'relay2'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
expect(badgeAward.p).toEqual([
|
||||||
|
['pubkey1', 'relay1'],
|
||||||
|
['pubkey2', 'relay2'],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('ProfileBadges has required property "d"', () => {
|
||||||
|
const profileBadges: ProfileBadges = {
|
||||||
|
d: 'profile_badges',
|
||||||
|
badges: [],
|
||||||
|
}
|
||||||
|
expect(profileBadges.d).toEqual('profile_badges')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('ProfileBadges has required property "badges"', () => {
|
||||||
|
const profileBadges: ProfileBadges = {
|
||||||
|
d: 'profile_badges',
|
||||||
|
badges: [],
|
||||||
|
}
|
||||||
|
expect(profileBadges.badges).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('ProfileBadges badges array contains objects with required properties "a" and "e"', () => {
|
||||||
|
const profileBadges: ProfileBadges = {
|
||||||
|
d: 'profile_badges',
|
||||||
|
badges: [
|
||||||
|
{
|
||||||
|
a: 'badge-definition-address',
|
||||||
|
e: ['badge-award-event-id'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
expect(profileBadges.badges[0].a).toEqual('badge-definition-address')
|
||||||
|
expect(profileBadges.badges[0].e).toEqual(['badge-award-event-id'])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('generateBadgeDefinitionEventTemplate generates EventTemplate with mandatory tags', () => {
|
||||||
|
const badge: BadgeDefinition = {
|
||||||
|
d: 'badge-id',
|
||||||
|
}
|
||||||
|
const eventTemplate = generateBadgeDefinitionEventTemplate(badge)
|
||||||
|
expect(eventTemplate.tags).toEqual([['d', 'badge-id']])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('generateBadgeDefinitionEventTemplate generates EventTemplate with optional tags', () => {
|
||||||
|
const badge: BadgeDefinition = {
|
||||||
|
d: 'badge-id',
|
||||||
|
name: 'Badge Name',
|
||||||
|
description: 'Badge Description',
|
||||||
|
image: ['https://example.com/badge.png', '1024x1024'],
|
||||||
|
thumbs: [
|
||||||
|
['https://example.com/thumb.png', '100x100'],
|
||||||
|
['https://example.com/thumb2.png', '200x200'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const eventTemplate = generateBadgeDefinitionEventTemplate(badge)
|
||||||
|
expect(eventTemplate.tags).toEqual([
|
||||||
|
['d', 'badge-id'],
|
||||||
|
['name', 'Badge Name'],
|
||||||
|
['description', 'Badge Description'],
|
||||||
|
['image', 'https://example.com/badge.png', '1024x1024'],
|
||||||
|
['thumb', 'https://example.com/thumb.png', '100x100'],
|
||||||
|
['thumb', 'https://example.com/thumb2.png', '200x200'],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('generateBadgeDefinitionEventTemplate generates EventTemplate without optional tags', () => {
|
||||||
|
const badge: BadgeDefinition = {
|
||||||
|
d: 'badge-id',
|
||||||
|
}
|
||||||
|
const eventTemplate = generateBadgeDefinitionEventTemplate(badge)
|
||||||
|
expect(eventTemplate.tags).toEqual([['d', 'badge-id']])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('validateBadgeDefinitionEvent returns true for valid BadgeDefinition event', () => {
|
||||||
|
const sk = generateSecretKey()
|
||||||
|
const eventTemplate: EventTemplate = {
|
||||||
|
content: '',
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
kind: BadgeDefinitionKind,
|
||||||
|
tags: [
|
||||||
|
['d', 'badge-id'],
|
||||||
|
['name', 'Badge Name'],
|
||||||
|
['description', 'Badge Description'],
|
||||||
|
['image', 'https://example.com/badge.png', '1024x1024'],
|
||||||
|
['thumb', 'https://example.com/thumb.png', '100x100'],
|
||||||
|
['thumb', 'https://example.com/thumb2.png', '200x200'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const event = finalizeEvent(eventTemplate, sk)
|
||||||
|
const isValid = validateBadgeDefinitionEvent(event)
|
||||||
|
|
||||||
|
expect(isValid).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('validateBadgeDefinitionEvent returns false for invalid BadgeDefinition event', () => {
|
||||||
|
const sk = generateSecretKey()
|
||||||
|
const eventTemplate: EventTemplate = {
|
||||||
|
content: '',
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
kind: BadgeDefinitionKind,
|
||||||
|
tags: [],
|
||||||
|
}
|
||||||
|
const event = finalizeEvent(eventTemplate, sk)
|
||||||
|
const isValid = validateBadgeDefinitionEvent(event)
|
||||||
|
|
||||||
|
expect(isValid).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('generateBadgeAwardEventTemplate generates EventTemplate with mandatory tags', () => {
|
||||||
|
const badgeAward: BadgeAward = {
|
||||||
|
a: 'badge-definition-address',
|
||||||
|
p: [
|
||||||
|
['pubkey1', 'relay1'],
|
||||||
|
['pubkey2', 'relay2'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const eventTemplate = generateBadgeAwardEventTemplate(badgeAward)
|
||||||
|
expect(eventTemplate.tags).toEqual([
|
||||||
|
['a', 'badge-definition-address'],
|
||||||
|
['p', 'pubkey1', 'relay1'],
|
||||||
|
['p', 'pubkey2', 'relay2'],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('generateBadgeAwardEventTemplate generates EventTemplate without optional tags', () => {
|
||||||
|
const badgeAward: BadgeAward = {
|
||||||
|
a: 'badge-definition-address',
|
||||||
|
p: [
|
||||||
|
['pubkey1', 'relay1'],
|
||||||
|
['pubkey2', 'relay2'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const eventTemplate = generateBadgeAwardEventTemplate(badgeAward)
|
||||||
|
expect(eventTemplate.tags).toEqual([
|
||||||
|
['a', 'badge-definition-address'],
|
||||||
|
['p', 'pubkey1', 'relay1'],
|
||||||
|
['p', 'pubkey2', 'relay2'],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('generateBadgeAwardEventTemplate generates EventTemplate with optional tags', () => {
|
||||||
|
const badgeAward: BadgeAward = {
|
||||||
|
a: 'badge-definition-address',
|
||||||
|
p: [
|
||||||
|
['pubkey1', 'relay1'],
|
||||||
|
['pubkey2', 'relay2'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const eventTemplate = generateBadgeAwardEventTemplate(badgeAward)
|
||||||
|
expect(eventTemplate.tags).toEqual([
|
||||||
|
['a', 'badge-definition-address'],
|
||||||
|
['p', 'pubkey1', 'relay1'],
|
||||||
|
['p', 'pubkey2', 'relay2'],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('validateBadgeAwardEvent returns true for valid BadgeAward event', () => {
|
||||||
|
const sk = generateSecretKey()
|
||||||
|
const eventTemplate: EventTemplate = {
|
||||||
|
content: '',
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
kind: BadgeAwardKind,
|
||||||
|
tags: [
|
||||||
|
['a', 'badge-definition-address'],
|
||||||
|
['p', 'pubkey1', 'relay1'],
|
||||||
|
['p', 'pubkey2', 'relay2'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const event = finalizeEvent(eventTemplate, sk)
|
||||||
|
const isValid = validateBadgeAwardEvent(event)
|
||||||
|
|
||||||
|
expect(isValid).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('validateBadgeAwardEvent returns false for invalid BadgeAward event', () => {
|
||||||
|
const sk = generateSecretKey()
|
||||||
|
const eventTemplate: EventTemplate = {
|
||||||
|
content: '',
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
kind: BadgeAwardKind,
|
||||||
|
tags: [],
|
||||||
|
}
|
||||||
|
const event = finalizeEvent(eventTemplate, sk)
|
||||||
|
const isValid = validateBadgeAwardEvent(event)
|
||||||
|
|
||||||
|
expect(isValid).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('generateProfileBadgesEventTemplate generates EventTemplate with mandatory tags', () => {
|
||||||
|
const profileBadges: ProfileBadges = {
|
||||||
|
d: 'profile_badges',
|
||||||
|
badges: [],
|
||||||
|
}
|
||||||
|
const eventTemplate = generateProfileBadgesEventTemplate(profileBadges)
|
||||||
|
expect(eventTemplate.tags).toEqual([['d', 'profile_badges']])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('generateProfileBadgesEventTemplate generates EventTemplate with optional tags', () => {
|
||||||
|
const profileBadges: ProfileBadges = {
|
||||||
|
d: 'profile_badges',
|
||||||
|
badges: [
|
||||||
|
{
|
||||||
|
a: 'badge-definition-address',
|
||||||
|
e: ['badge-award-event-id'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const eventTemplate = generateProfileBadgesEventTemplate(profileBadges)
|
||||||
|
expect(eventTemplate.tags).toEqual([
|
||||||
|
['d', 'profile_badges'],
|
||||||
|
['a', 'badge-definition-address'],
|
||||||
|
['e', 'badge-award-event-id'],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('generateProfileBadgesEventTemplate generates EventTemplate with multiple optional tags', () => {
|
||||||
|
const profileBadges: ProfileBadges = {
|
||||||
|
d: 'profile_badges',
|
||||||
|
badges: [
|
||||||
|
{
|
||||||
|
a: 'badge-definition-address1',
|
||||||
|
e: ['badge-award-event-id1', 'badge-award-event-id2'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a: 'badge-definition-address2',
|
||||||
|
e: ['badge-award-event-id3'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const eventTemplate = generateProfileBadgesEventTemplate(profileBadges)
|
||||||
|
expect(eventTemplate.tags).toEqual([
|
||||||
|
['d', 'profile_badges'],
|
||||||
|
['a', 'badge-definition-address1'],
|
||||||
|
['e', 'badge-award-event-id1', 'badge-award-event-id2'],
|
||||||
|
['a', 'badge-definition-address2'],
|
||||||
|
['e', 'badge-award-event-id3'],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('validateProfileBadgesEvent returns true for valid ProfileBadges event', () => {
|
||||||
|
const sk = generateSecretKey()
|
||||||
|
const eventTemplate: EventTemplate = {
|
||||||
|
content: '',
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
kind: ProfileBadgesKind,
|
||||||
|
tags: [
|
||||||
|
['d', 'profile_badges'],
|
||||||
|
['a', 'badge-definition-address'],
|
||||||
|
['e', 'badge-award-event-id'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const event = finalizeEvent(eventTemplate, sk)
|
||||||
|
const isValid = validateProfileBadgesEvent(event)
|
||||||
|
|
||||||
|
expect(isValid).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('validateProfileBadgesEvent returns false for invalid ProfileBadges event', () => {
|
||||||
|
const sk = generateSecretKey()
|
||||||
|
const eventTemplate: EventTemplate = {
|
||||||
|
content: '',
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
kind: ProfileBadgesKind,
|
||||||
|
tags: [],
|
||||||
|
}
|
||||||
|
const event = finalizeEvent(eventTemplate, sk)
|
||||||
|
const isValid = validateProfileBadgesEvent(event)
|
||||||
|
|
||||||
|
expect(isValid).toBe(false)
|
||||||
|
})
|
|
@ -0,0 +1,245 @@
|
||||||
|
import { Event, EventTemplate } from './core'
|
||||||
|
import {
|
||||||
|
BadgeAward as BadgeAwardKind,
|
||||||
|
BadgeDefinition as BadgeDefinitionKind,
|
||||||
|
ProfileBadges as ProfileBadgesKind,
|
||||||
|
} from './kinds'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the structure for defining a badge within the Nostr network.
|
||||||
|
* This structure is used to create templates for badge definition events,
|
||||||
|
* facilitating the recognition and awarding of badges to users for various achievements.
|
||||||
|
*/
|
||||||
|
export type BadgeDefinition = {
|
||||||
|
/**
|
||||||
|
* A unique identifier for the badge. This is used to distinguish badges
|
||||||
|
* from one another and should be unique across all badge definitions.
|
||||||
|
* Typically, this could be a short, descriptive string.
|
||||||
|
*/
|
||||||
|
d: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional short name for the badge. This provides a human-readable
|
||||||
|
* title for the badge, making it easier to recognize and refer to.
|
||||||
|
*/
|
||||||
|
name?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional description for the badge. This field can be used to
|
||||||
|
* provide more detailed information about the badge, such as the criteria
|
||||||
|
* for its awarding or its significance.
|
||||||
|
*/
|
||||||
|
description?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional image URL and dimensions for the badge. The first element
|
||||||
|
* of the tuple is the URL pointing to a high-resolution image representing
|
||||||
|
* the badge, and the second element specifies the image's dimensions in
|
||||||
|
* the format "widthxheight". The recommended dimensions are 1024x1024 pixels.
|
||||||
|
*/
|
||||||
|
image?: [string, string]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional list of thumbnail images for the badge. Each element in the
|
||||||
|
* array is a tuple, where the first element is the URL pointing to a thumbnail
|
||||||
|
* version of the badge image, and the second element specifies the thumbnail's
|
||||||
|
* dimensions in the format "widthxheight". Multiple thumbnails can be provided
|
||||||
|
* to support different display sizes.
|
||||||
|
*/
|
||||||
|
thumbs?: Array<[string, string]>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the structure for awarding a badge to one or more recipients
|
||||||
|
* within the Nostr network. This structure is used to create templates for
|
||||||
|
* badge award events, which are immutable and signify the recognition of
|
||||||
|
* individuals' achievements or contributions.
|
||||||
|
*/
|
||||||
|
export type BadgeAward = {
|
||||||
|
/**
|
||||||
|
* A reference to the Badge Definition event. This is typically composed
|
||||||
|
* of the event ID of the badge definition. It establishes a clear linkage
|
||||||
|
* between the badge being awarded and its original definition, ensuring
|
||||||
|
* that recipients are awarded the correct badge.
|
||||||
|
*/
|
||||||
|
a: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of p tags, each containing a pubkey and its associated relays.
|
||||||
|
*/
|
||||||
|
p: string[][]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the collection of badges a user chooses to display on their profile.
|
||||||
|
* This structure is crucial for applications that allow users to showcase achievements
|
||||||
|
* or recognitions in the form of badges, following the specifications of NIP-58.
|
||||||
|
*/
|
||||||
|
export type ProfileBadges = {
|
||||||
|
/**
|
||||||
|
* A unique identifier for the profile badges collection. According to NIP-58,
|
||||||
|
* this should be set to "profile_badges" to differentiate it from other event types.
|
||||||
|
*/
|
||||||
|
d: 'profile_badges'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of badges that the user has elected to display on their profile. Each item
|
||||||
|
* in the array represents a specific badge, including references to both its definition
|
||||||
|
* and the award event.
|
||||||
|
*/
|
||||||
|
badges: Array<{
|
||||||
|
/**
|
||||||
|
* The event address of the badge definition. This is a reference to the specific badge
|
||||||
|
* being displayed, linking back to the badge's original definition event. It allows
|
||||||
|
* clients to fetch and display the badge's details, such as its name, description,
|
||||||
|
* and image.
|
||||||
|
*/
|
||||||
|
a: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The event id of the badge award with corresponding relays. This references the event
|
||||||
|
* in which the badge was awarded to the user. It is crucial for verifying the
|
||||||
|
* authenticity of the badge display, ensuring that the user was indeed awarded the
|
||||||
|
* badge they are choosing to display.
|
||||||
|
*/
|
||||||
|
e: string[]
|
||||||
|
}>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an EventTemplate based on the provided BadgeDefinition.
|
||||||
|
*
|
||||||
|
* @param {BadgeDefinition} badgeDefinition - The BadgeDefinition object.
|
||||||
|
* @returns {EventTemplate} - The generated EventTemplate object.
|
||||||
|
*/
|
||||||
|
export function generateBadgeDefinitionEventTemplate({
|
||||||
|
d,
|
||||||
|
description,
|
||||||
|
image,
|
||||||
|
name,
|
||||||
|
thumbs,
|
||||||
|
}: BadgeDefinition): EventTemplate {
|
||||||
|
// Mandatory tags
|
||||||
|
const tags: string[][] = [['d', d]]
|
||||||
|
|
||||||
|
// Append optional tags
|
||||||
|
name && tags.push(['name', name])
|
||||||
|
description && tags.push(['description', description])
|
||||||
|
image && tags.push(['image', ...image])
|
||||||
|
if (thumbs) {
|
||||||
|
for (const thumb of thumbs) {
|
||||||
|
tags.push(['thumb', ...thumb])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the EventTemplate object
|
||||||
|
const eventTemplate: EventTemplate = {
|
||||||
|
content: '',
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
kind: BadgeDefinitionKind,
|
||||||
|
tags,
|
||||||
|
}
|
||||||
|
|
||||||
|
return eventTemplate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a badge definition event.
|
||||||
|
*
|
||||||
|
* @param event - The event to validate.
|
||||||
|
* @returns A boolean indicating whether the event is a valid badge definition event.
|
||||||
|
*/
|
||||||
|
export function validateBadgeDefinitionEvent(event: Event): boolean {
|
||||||
|
if (event.kind !== BadgeDefinitionKind) return false
|
||||||
|
|
||||||
|
const requiredTags = ['d'] as const
|
||||||
|
for (const tag of requiredTags) {
|
||||||
|
if (!event.tags.find(([t]) => t == tag)) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an EventTemplate based on the provided BadgeAward.
|
||||||
|
*
|
||||||
|
* @param {BadgeAward} badgeAward - The BadgeAward object.
|
||||||
|
* @returns {EventTemplate} - The generated EventTemplate object.
|
||||||
|
*/
|
||||||
|
export function generateBadgeAwardEventTemplate({ a, p }: BadgeAward): EventTemplate {
|
||||||
|
// Mandatory tags
|
||||||
|
const tags: string[][] = [['a', a]]
|
||||||
|
for (const _p of p) {
|
||||||
|
tags.push(['p', ..._p])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the EventTemplate object
|
||||||
|
const eventTemplate: EventTemplate = {
|
||||||
|
content: '',
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
kind: BadgeAwardKind,
|
||||||
|
tags,
|
||||||
|
}
|
||||||
|
|
||||||
|
return eventTemplate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a badge award event.
|
||||||
|
*
|
||||||
|
* @param event - The event to validate.
|
||||||
|
* @returns A boolean indicating whether the event is a valid badge award event.
|
||||||
|
*/
|
||||||
|
export function validateBadgeAwardEvent(event: Event): boolean {
|
||||||
|
if (event.kind !== BadgeAwardKind) return false
|
||||||
|
|
||||||
|
const requiredTags = ['a', 'p'] as const
|
||||||
|
for (const tag of requiredTags) {
|
||||||
|
if (!event.tags.find(([t]) => t == tag)) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an EventTemplate based on the provided ProfileBadges.
|
||||||
|
*
|
||||||
|
* @param {ProfileBadges} profileBadges - The ProfileBadges object.
|
||||||
|
* @returns {EventTemplate} - The generated EventTemplate object.
|
||||||
|
*/
|
||||||
|
export function generateProfileBadgesEventTemplate({ badges }: ProfileBadges): EventTemplate {
|
||||||
|
// Mandatory tags
|
||||||
|
const tags: string[][] = [['d', 'profile_badges']]
|
||||||
|
|
||||||
|
// Append optional tags
|
||||||
|
for (const badge of badges) {
|
||||||
|
tags.push(['a', badge.a], ['e', ...badge.e])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the EventTemplate object
|
||||||
|
const eventTemplate: EventTemplate = {
|
||||||
|
content: '',
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
kind: ProfileBadgesKind,
|
||||||
|
tags,
|
||||||
|
}
|
||||||
|
|
||||||
|
return eventTemplate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a profile badges event.
|
||||||
|
*
|
||||||
|
* @param event - The event to validate.
|
||||||
|
* @returns A boolean indicating whether the event is a valid profile badges event.
|
||||||
|
*/
|
||||||
|
export function validateProfileBadgesEvent(event: Event): boolean {
|
||||||
|
if (event.kind !== ProfileBadgesKind) return false
|
||||||
|
|
||||||
|
const requiredTags = ['d'] as const
|
||||||
|
for (const tag of requiredTags) {
|
||||||
|
if (!event.tags.find(([t]) => t == tag)) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
|
@ -170,6 +170,11 @@
|
||||||
"require": "./lib/cjs/nip57.js",
|
"require": "./lib/cjs/nip57.js",
|
||||||
"types": "./lib/types/nip57.d.ts"
|
"types": "./lib/types/nip57.d.ts"
|
||||||
},
|
},
|
||||||
|
"./nip58": {
|
||||||
|
"import": "./lib/esm/nip58.js",
|
||||||
|
"require": "./lib/cjs/nip58.js",
|
||||||
|
"types": "./lib/types/nip58.d.ts"
|
||||||
|
},
|
||||||
"./nip75": {
|
"./nip75": {
|
||||||
"import": "./lib/esm/nip75.js",
|
"import": "./lib/esm/nip75.js",
|
||||||
"require": "./lib/cjs/nip75.js",
|
"require": "./lib/cjs/nip75.js",
|
||||||
|
|
Loading…
Reference in New Issue