From 581ceecbf046f99b39885c74e2780a5320e5b15e Mon Sep 17 00:00:00 2001 From: bndw Date: Fri, 13 Feb 2026 17:35:32 -0800 Subject: feat: add Nostr protocol implementation (internal/nostr, internal/websocket) --- internal/nostr/event.go | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 internal/nostr/event.go (limited to 'internal/nostr/event.go') diff --git a/internal/nostr/event.go b/internal/nostr/event.go new file mode 100644 index 0000000..a8156bb --- /dev/null +++ b/internal/nostr/event.go @@ -0,0 +1,72 @@ +package nostr + +import ( + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" +) + +// Event represents a Nostr event as defined in NIP-01. +type Event struct { + ID string `json:"id"` + PubKey string `json:"pubkey"` + CreatedAt int64 `json:"created_at"` + Kind int `json:"kind"` + Tags Tags `json:"tags"` + Content string `json:"content"` + Sig string `json:"sig"` +} + +// Serialize returns the canonical JSON serialization of the event for ID computation. +// Format: [0, "pubkey", created_at, kind, tags, "content"] +func (e *Event) Serialize() []byte { + // Use json.Marshal for proper escaping of content and tags + arr := []interface{}{ + 0, + e.PubKey, + e.CreatedAt, + e.Kind, + e.Tags, + e.Content, + } + data, _ := json.Marshal(arr) + return data +} + +// ComputeID calculates the SHA256 hash of the serialized event. +// Returns the 64-character hex-encoded ID. +func (e *Event) ComputeID() string { + serialized := e.Serialize() + hash := sha256.Sum256(serialized) + return hex.EncodeToString(hash[:]) +} + +// SetID computes and sets the event ID. +func (e *Event) SetID() { + e.ID = e.ComputeID() +} + +// CheckID verifies that the event ID matches the computed ID. +func (e *Event) CheckID() bool { + return e.ID == e.ComputeID() +} + +// MarshalJSON implements json.Marshaler with empty tags as [] instead of null. +func (e Event) MarshalJSON() ([]byte, error) { + type eventAlias Event + ea := eventAlias(e) + if ea.Tags == nil { + ea.Tags = Tags{} + } + return json.Marshal(ea) +} + +// String returns a JSON representation of the event for debugging. +func (e *Event) String() string { + data, err := json.MarshalIndent(e, "", " ") + if err != nil { + return fmt.Sprintf("", err) + } + return string(data) +} -- cgit v1.2.3