nostr_tools.Event

class nostr_tools.Event[source]

Bases: object

Nostr event representation following NIP-01 protocol specifications.

This class handles validation, serialization, and manipulation of Nostr events according to the protocol specification. All events are validated for proper format, signature verification, and ID consistency. Events are automatically validated upon creation and escape sequences in content/tags are properly handled.

Examples

Create an event from a dictionary:

>>> event_data = {
...     "id": "a1b2c3...",
...     "pubkey": "d4e5f6...",
...     "created_at": 1234567890,
...     "kind": 1,
...     "tags": [["p", "abc123..."], ["e", "def456..."]],
...     "content": "Hello Nostr!",
...     "sig": "789abc..."
... }
>>> event = Event.from_dict(event_data)

Validate an event:

>>> if event.is_valid:
...     print("Event is valid!")
... else:
...     print("Event validation failed")

Convert event to dictionary:

>>> event_dict = event.to_dict()
>>> print(event_dict["kind"])
1
Raises:

EventValidationError – If any attribute value is invalid, ID doesn’t match computed hash, or signature verification fails.

Methods

__init__(id, pubkey, created_at, kind, tags, ...)

from_dict(data)

Create an Event object from a dictionary representation.

to_dict()

Convert the Event object to a dictionary representation.

validate()

Validate the Event instance against NIP-01 specifications.

Attributes

is_valid

Check if the Event is valid without raising exceptions.

id

Event ID as a 64-character lowercase hexadecimal string.

pubkey

Public key of the event author as a 64-character lowercase hexadecimal string.

created_at

Unix timestamp (seconds since epoch) of when the event was created.

kind

0=metadata, 1=text note, 3=contacts, 4=DM, etc.

tags

[["e", "event_id"], ["p", "pubkey"]]

content

The event content/message as a string.

sig

Schnorr signature of the event as a 128-character lowercase hexadecimal string.

id: str

Event ID as a 64-character lowercase hexadecimal string. This is the SHA-256 hash of the serialized event data.

pubkey: str

Public key of the event author as a 64-character lowercase hexadecimal string.

created_at: int

Unix timestamp (seconds since epoch) of when the event was created. Must be non-negative.

kind: int

0=metadata, 1=text note, 3=contacts, 4=DM, etc.

Type:

Event kind number (0-65535) defining the event type. Common kinds

tags: list[list[str]]

[[“e”, “event_id”], [“p”, “pubkey”]]

Type:

List of event tags. Each tag is a list of strings where the first element is the tag name. Example

content: str

The event content/message as a string. Cannot contain null bytes.

sig: str

Schnorr signature of the event as a 128-character lowercase hexadecimal string.

__post_init__()[source]

Validate and normalize the Event instance after initialization.

This method is automatically called after the dataclass is created. It normalizes hex strings to lowercase and validates the event. If validation fails due to escape sequences, it attempts to unescape them and re-validates.

Raises:

EventValidationError – If validation fails after escape handling.

Return type:

None

validate()[source]

Validate the Event instance against NIP-01 specifications.

Performs comprehensive validation including: - Type checking for all attributes - Format validation (hex strings, timestamps, etc.) - Event ID verification against computed hash - Schnorr signature verification - Null byte checking in content and tags

Raises:

EventValidationError – If any attribute has an invalid value, including: - Invalid hex string formats - ID mismatch with computed event ID - Invalid signature - Presence of null bytes - Invalid kind range (must be 0-65535)

Return type:

None

Examples

>>> try:
...     event.validate()
...     print("Event is valid")
... except EventValidationError as e:
...     print(f"Validation failed: {e}")
property is_valid: bool

Check if the Event is valid without raising exceptions.

This property attempts validation and returns True if successful, False otherwise. Unlike validate(), this method does not raise exceptions, making it safe for conditional checks.

Returns:

True if the event passes all validation checks,

False if validation fails for any reason.

Return type:

bool

Examples

>>> if event.is_valid:
...     # Process the valid event
...     publish_event(event)
... else:
...     # Handle invalid event
...     log_error("Invalid event detected")
classmethod from_dict(data)[source]

Create an Event object from a dictionary representation.

This class method constructs an Event instance from a dictionary, typically received from a Nostr relay or JSON deserialization. All required fields must be present in the dictionary.

Parameters:

data (dict[str, Any]) – Dictionary containing event attributes. Required keys: id, pubkey, created_at, kind, tags, content, sig

Returns:

A new Event instance created from the dictionary data.

Return type:

Event

Raises:

Examples

Parse an event from relay response:

>>> relay_message = ["EVENT", "sub_id", {
...     "id": "a1b2c3d4...",
...     "pubkey": "e5f6g7h8...",
...     "created_at": 1234567890,
...     "kind": 1,
...     "tags": [["p", "i9j0k1l2..."]],
...     "content": "Hello Nostr!",
...     "sig": "m3n4o5p6..."
... }]
>>> event = Event.from_dict(relay_message[2])
>>> print(event.content)
Hello Nostr!

Parse from JSON:

>>> import json
>>> json_data = '{"id": "...", "pubkey": "...", ...}'
>>> event_dict = json.loads(json_data)
>>> event = Event.from_dict(event_dict)
to_dict()[source]

Convert the Event object to a dictionary representation.

This method serializes the Event instance into a dictionary format suitable for JSON encoding, relay transmission, or storage.

Returns:

Dictionary containing all event fields with keys:
  • id: Event ID (str)

  • pubkey: Public key (str)

  • created_at: Timestamp (int)

  • kind: Event kind (int)

  • tags: Event tags (list[list[str]])

  • content: Event content (str)

  • sig: Signature (str)

Return type:

dict[str, Any]

Examples

Convert event for relay publishing:

>>> event_dict = event.to_dict()
>>> publish_message = ["EVENT", event_dict]
>>> await ws.send_str(json.dumps(publish_message))

Serialize to JSON:

>>> import json
>>> json_str = json.dumps(event.to_dict())
>>> print(json_str)
{"id": "...", "pubkey": "...", ...}

Store in database:

>>> event_data = event.to_dict()
>>> db.events.insert_one(event_data)
__init__(id, pubkey, created_at, kind, tags, content, sig)
Parameters:
Return type:

None