forked from nbd-wtf/nostr-tools
-
Notifications
You must be signed in to change notification settings - Fork 1
/
nip58.ts
245 lines (215 loc) · 7.36 KB
/
nip58.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
import { Event, EventTemplate } from './core.ts'
import {
BadgeAward as BadgeAwardKind,
BadgeDefinition as BadgeDefinitionKind,
ProfileBadges as ProfileBadgesKind,
} from './kinds.ts'
/**
* 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
}