NIP-01 Wire Format for Nostr Events in Buzz: Implementation Guide

Buzz does not introduce a bespoke wire format for Nostr events; instead, it uses the standard NIP-01 JSON structure transmitted as newline-delimited UTF-8 text over WebSocket and HTTP.

The Block Buzz relay processes all events according to the canonical Nostr protocol, ensuring compatibility with the broader ecosystem while embedding owner-attestation credentials through standard tag extensions. Every event that flows through the relay—whether via WebSocket, HTTP POST /events, /count, or /query—conforms strictly to the seven-field NIP-01 specification.

Standard NIP-01 Event Structure

Buzz enforces the exact seven-field JSON object defined in NIP-01 for every event. The relay validates these fields using helper functions in crates/buzz-sdk/src/event.rs before accepting or forwarding any message.

The Seven Canonical Fields

Every event transmitted to Buzz must contain these required fields with precise encoding:

  • id — A 64-character hexadecimal string representing the SHA-256 hash of the serialized event content.
  • pubkey — The author's 64-character hex-encoded public key.
  • created_at — Unix timestamp in seconds since epoch (integer).
  • kind — Integer defining the application-specific event type (e.g., 0 for metadata, 1 for short text notes, 30078 for read-state blobs), registered in crates/buzz-core/src/kind.rs.
  • tags — Array of arrays containing structured metadata. Buzz specifically utilizes:
    • e tags for event references (replies and mentions).
    • p tags for pubkey references to other users.
    • h tags for group/channel identifiers (implementing NIP-29).
    • auth tags containing NIP-OA credentials that realize the "NIP-OI" owner-identity concept.
  • content — String payload, either plaintext or NIP-44 encrypted.
  • sig — 128-character hex-encoded Schnorr signature covering the event's serialized form.

Transmission Format and Protocol

The NIP-01 wire format employs pure UTF-8 text with newline-delimited JSON framing. No binary encoding, length-prefixing, or additional framing protocols are used.

WebSocket Transport

In crates/buzz-ws-client/src/client.rs, events are encoded as individual JSON objects terminated by newline characters (\n). Each WebSocket message contains exactly one newline-terminated JSON object representing a single Nostr event.

HTTP Endpoints

The identical newline-delimited JSON structure applies to HTTP POST requests against the /events, /count, and /query endpoints. The relay parses each line of the request body as a discrete event, rejecting any messages that deviate from the standard seven-field structure.

NIP-OI Implementation via NIP-OA Credentials

While Buzz adheres strictly to NIP-01 for wire transport, it implements the "NIP-OI" (Owner-Identity) concept through NIP-OA (Owner-Attestation) credentials embedded in standard tags.

The Auth Tag Structure

The auth tag carries the owner-attestation credential validated by crates/buzz-auth/src/nip42.rs and parsed by crates/buzz-acp/src/acp.rs:

{
  "id": "...",
  "pubkey": "...",
  "created_at": 1725064832,
  "kind": 40002,
  "tags": [
    ["h", "01ab23cd-ef45-6789-abcd-0123456789ab"],
    ["e", "a1b2c3d4e5f6..."],
    ["auth", "naddr1..."]
  ],
  "content": "Hello, Buzz!",
  "sig": "..."
}

The relay validates the auth tag before accepting the event, ensuring only agents with valid owner attestations can publish on behalf of users. This verification occurs while maintaining the exact NIP-01 wire format compatibility for the event envelope.

Key Implementation Files

Several components in the Buzz codebase handle the NIP-01 wire format:

  • crates/buzz-ws-client/src/client.rs — Manages WebSocket client connections, handling the encoding and decoding of newline-delimited JSON events.
  • crates/buzz-core/src/kind.rs — Central registry defining all event kind integers used by Buzz, including custom kinds for channels and agents.
  • crates/buzz-sdk/src/event.rs — Provides helper functions to construct valid NIP-01 events, automatically generating the id and sig fields via SHA-256 hashing and Schnorr signing.
  • crates/buzz-auth/src/nip42.rs — Validates the auth tag containing NIP-OA credentials, enforcing owner-attestation before relay acceptance.
  • crates/buzz-acp/src/acp.rs — Parses and extracts NIP-OA credentials from the auth tag for agent-side verification.
  • docs/nips/NIP-OA.md — Specification document defining the credential format reused for the NIP-OI concept according to the block/buzz source code.

Summary

  • Buzz uses the standard NIP-01 wire format for all Nostr events without proprietary extensions or binary encodings.
  • Events transmit as newline-delimited JSON over WebSocket and HTTP POST endpoints (/events, /count, /query).
  • The seven canonical fields follow strict NIP-01 specifications: 64-char hex for id and pubkey, 128-char hex for sig, and integer timestamps.
  • NIP-OI functionality deploys through standard NIP-OA credentials carried in the auth tag, validated in crates/buzz-auth/src/nip42.rs.
  • Client implementations should use crates/buzz-sdk/src/event.rs helpers to ensure proper event serialization and cryptographic signing.

Frequently Asked Questions

What is the NIP-01 wire format used by Buzz?

The NIP-01 wire format is the standard JSON-based event structure defined by the Nostr protocol, consisting of seven required fields transmitted as newline-delimited UTF-8 text. Buzz implements this format exactly as specified in NIP-01, without custom binary encodings or proprietary framing protocols.

How does Buzz handle event authentication within the NIP-01 format?

Buzz embeds authentication credentials within the standard tags array using an auth tag that contains a NIP-OA (Owner-Attestation) credential. The relay validates this tag during ingestion in crates/buzz-auth/src/nip42.rs, proving the event publisher has owner authorization while maintaining the standard wire format envelope specified in NIP-01.

Can standard Nostr clients interact with the Buzz relay?

Yes, because Buzz uses the canonical NIP-01 wire format for Nostr events, any standard Nostr client can connect via WebSocket or HTTP POST to publish and query events. Clients only need to include the auth tag extension to utilize Buzz-specific owner-attestation features, while all other fields remain standard NIP-01.

Where is the NIP-01 event validation implemented in the Buzz codebase?

Core validation and serialization helpers reside in crates/buzz-sdk/src/event.rs, which handles canonical ID generation and Schnorr signature verification. WebSocket-specific encoding logic appears in crates/buzz-ws-client/src/client.rs. The relay rejects malformed events that deviate from the seven-field NIP-01 structure or contain invalid hexadecimal encoding.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →