Skip to content

Commit 8b2f9a2

Browse files
committed
perf: loop once through tags in NIP-25 validation and parsing
1 parent 8dc8f2a commit 8b2f9a2

2 files changed

Lines changed: 31 additions & 12 deletions

File tree

src/schemas/event-schema.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,13 @@ export const eventSchema = z
3333
.strict()
3434
.superRefine((event, ctx) => {
3535
if (isReactionEvent(event)) {
36-
const hasEventTag = event.tags.some((tag) => tag[0] === EventTags.Event && typeof tag[1] === 'string' && tag[1].length > 0)
37-
const hasAddressTag = event.tags.some((tag) => tag[0] === EventTags.Address && typeof tag[1] === 'string' && tag[1].length > 0)
36+
let hasEventTag = false
37+
let hasAddressTag = false
38+
for (const tag of event.tags) {
39+
if (tag[0] === EventTags.Event && typeof tag[1] === 'string' && tag[1].length > 0) { hasEventTag = true }
40+
else if (tag[0] === EventTags.Address && typeof tag[1] === 'string' && tag[1].length > 0) { hasAddressTag = true }
41+
if (hasEventTag && hasAddressTag) { break }
42+
}
3843
if (!hasEventTag && !hasAddressTag) {
3944
ctx.addIssue({
4045
code: z.ZodIssueCode.custom,
@@ -43,8 +48,13 @@ export const eventSchema = z
4348
})
4449
}
4550
} else if (isExternalContentReactionEvent(event)) {
46-
const hasKTag = event.tags.some((tag) => tag[0] === EventTags.Kind && tag.length >= 2 && typeof tag[1] === 'string' && tag[1].length > 0)
47-
const hasITag = event.tags.some((tag) => tag[0] === EventTags.Index && tag.length >= 2 && typeof tag[1] === 'string' && tag[1].length > 0)
51+
let hasKTag = false
52+
let hasITag = false
53+
for (const tag of event.tags) {
54+
if (tag[0] === EventTags.Kind && tag.length >= 2 && typeof tag[1] === 'string' && tag[1].length > 0) { hasKTag = true }
55+
else if (tag[0] === EventTags.Index && tag.length >= 2 && typeof tag[1] === 'string' && tag[1].length > 0) { hasITag = true }
56+
if (hasKTag && hasITag) { break }
57+
}
4858
if (!hasKTag || !hasITag) {
4959
ctx.addIssue({
5060
code: z.ZodIssueCode.custom,

src/utils/nip25.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,26 @@ export const isDislikeReaction = (event: { kind?: number; content?: string }): b
1313
isReactionEvent(event) && event.content === '-'
1414

1515
export const parseReaction = (event: Event): ReactionEntry => {
16-
const eTags = event.tags.filter((tag) => tag[0] === EventTags.Event)
17-
const pTags = event.tags.filter((tag) => tag[0] === EventTags.Pubkey)
18-
const aTags = event.tags.filter((tag) => tag[0] === EventTags.Address)
19-
const kTag = event.tags.find((tag) => tag[0] === EventTags.Kind)
16+
let lastETag: string[] | undefined
17+
let lastPTag: string[] | undefined
18+
let lastATag: string[] | undefined
19+
let firstKTag: string[] | undefined
2020

21-
const kTagValue = kTag && kTag.length > 1 ? kTag[1] : undefined
21+
for (const tag of event.tags) {
22+
switch (tag[0]) {
23+
case EventTags.Event: lastETag = tag; break
24+
case EventTags.Pubkey: lastPTag = tag; break
25+
case EventTags.Address: lastATag = tag; break
26+
case EventTags.Kind: if (!firstKTag) { firstKTag = tag } break
27+
}
28+
}
29+
30+
const kTagValue = firstKTag && firstKTag.length > 1 ? firstKTag[1] : undefined
2231
const parsedKind = kTagValue !== undefined ? Number(kTagValue) : undefined
2332
return {
24-
targetEventId: eTags.length > 0 ? eTags[eTags.length - 1][1] : undefined,
25-
targetPubkey: pTags.length > 0 ? pTags[pTags.length - 1][1] : undefined,
26-
targetAddress: aTags.length > 0 ? aTags[aTags.length - 1][1] : undefined,
33+
targetEventId: lastETag?.[1],
34+
targetPubkey: lastPTag?.[1],
35+
targetAddress: lastATag?.[1],
2736
targetKind: parsedKind !== undefined && Number.isFinite(parsedKind) ? parsedKind : undefined,
2837
content: event.content,
2938
}

0 commit comments

Comments
 (0)