Event
Functions for creating, signing, and verifying Nostr events.
Import
import {
finalizeEvent,
verifyEvent,
verifyEventSignature,
getEventHash,
serializeEvent,
validateEvent,
verifiedSymbol,
} from 'nostr-core'Types
NostrEvent
type NostrEvent = {
kind: number
tags: string[][]
content: string
created_at: number
pubkey: string
id: string
sig: string
[verifiedSymbol]?: boolean
}EventTemplate
type EventTemplate = Pick<NostrEvent, 'kind' | 'tags' | 'content' | 'created_at'>The minimum fields needed to create an event (before signing).
UnsignedEvent
type UnsignedEvent = Pick<NostrEvent, 'kind' | 'tags' | 'content' | 'created_at' | 'pubkey'>An event with a pubkey but no id or sig.
VerifiedEvent
interface VerifiedEvent extends NostrEvent {
[verifiedSymbol]: true
}An event whose signature has been verified.
finalizeEvent
function finalizeEvent(template: EventTemplate, secretKey: Uint8Array): VerifiedEventSigns an event template, adding pubkey, id, and sig fields.
| Parameter | Type | Description |
|---|---|---|
template | EventTemplate | Event with kind, tags, content, created_at |
secretKey | Uint8Array | 32-byte secret key |
Returns: VerifiedEvent - the fully signed event.
import { finalizeEvent, generateSecretKey } from 'nostr-core'
const sk = generateSecretKey()
const event = finalizeEvent({
kind: 1,
tags: [],
content: 'Hello world',
created_at: Math.floor(Date.now() / 1000),
}, sk)
console.log(event.id) // 64-char hex
console.log(event.sig) // 128-char hexverifyEvent
function verifyEvent(event: NostrEvent): event is VerifiedEventVerifies an event's hash and schnorr signature. Acts as a TypeScript type guard.
The result is cached on the event under verifiedSymbol, so repeated checks of the same object are free.
| Parameter | Type | Description |
|---|---|---|
event | NostrEvent | Event to verify |
Returns: boolean - true if valid, narrowing the type to VerifiedEvent.
verifyEventSignature
function verifyEventSignature(event: NostrEvent): booleanVerifies an event's id and signature from scratch, consulting no cache and writing none.
WARNING
verifiedSymbol is an own enumerable symbol property, and object spread copies own symbols. That means { ...signedEvent, content: 'changed' } inherits the original event's "already verified" flag, and verifyEvent would return true for it.
Events parsed from JSON are unaffected - JSON has no symbols - so data arriving off the wire is never at risk. But any code path that spreads a signed event and mutates it should use verifyEventSignature. The Schema and Policy modules use it for exactly this reason.
const tampered = { ...signed, content: 'changed' }
verifyEvent(tampered) // true - reads the copied cache flag
verifyEventSignature(tampered) // false - actually checksResults are cached on the event object via [verifiedSymbol].
if (verifyEvent(event)) {
// event is now typed as VerifiedEvent
console.log('Valid event from', event.pubkey)
}getEventHash
function getEventHash(event: UnsignedEvent): stringComputes the SHA-256 hash of a serialized event (the event id).
| Parameter | Type | Description |
|---|---|---|
event | UnsignedEvent | Event with pubkey but no id/sig |
Returns: string - 64-character hex hash.
serializeEvent
function serializeEvent(event: UnsignedEvent): stringSerializes an event to NIP-01 canonical JSON format:
[0, "<pubkey>", <created_at>, <kind>, <tags>, "<content>"]Throws: Error if the event fails validation.
validateEvent
function validateEvent<T>(event: T): event is T & UnsignedEventValidates an event's structure. Type guard that checks:
kindis a numbercontentis a stringcreated_atis a numberpubkeyis a 64-character hex stringtagsis an array of string arrays
verifiedSymbol
const verifiedSymbol: unique symbolSymbol used to mark events as verified. Set to true on events that pass verifyEvent() or are created with finalizeEvent().