summaryrefslogtreecommitdiffstats
path: root/internal/handler/websocket/nip11.go
diff options
context:
space:
mode:
authorbndw <ben@bdw.to>2026-02-13 19:12:28 -0800
committerbndw <ben@bdw.to>2026-02-13 19:12:28 -0800
commit656748ea286ff7eac6cbe1b241ad31212892ba61 (patch)
treee9685b4a585809463bdf51a4d1ecb7f7c5efaf70 /internal/handler/websocket/nip11.go
parent83876eae868bd1e4fb6b9a823a6e8173919f290d (diff)
feat: implement NIP-09 (deletions) and NIP-11 (relay info)
NIP-11 (Relay Information Document): - Serves relay metadata at GET / with Accept: application/nostr+json - Returns name, description, supported NIPs, limitations - CORS headers for browser compatibility NIP-09 (Event Deletion): - Kind 5 events delete events referenced in 'e' tags - Only authors can delete their own events - Soft delete (marks deleted=1) - Records deletion in deletions table - Works across all protocols (gRPC, Connect, WebSocket) Fixed deletions schema: - deleted_event_id as PRIMARY KEY (not deletion_event_id) - Allows one deletion event to delete multiple events 3 new tests, 44 total tests passing Supported NIPs now: 1, 9, 11
Diffstat (limited to 'internal/handler/websocket/nip11.go')
-rw-r--r--internal/handler/websocket/nip11.go60
1 files changed, 60 insertions, 0 deletions
diff --git a/internal/handler/websocket/nip11.go b/internal/handler/websocket/nip11.go
new file mode 100644
index 0000000..a5bb9ca
--- /dev/null
+++ b/internal/handler/websocket/nip11.go
@@ -0,0 +1,60 @@
1package websocket
2
3import (
4 "encoding/json"
5 "net/http"
6)
7
8type RelayInfo struct {
9 Name string `json:"name"`
10 Description string `json:"description"`
11 Pubkey string `json:"pubkey,omitempty"`
12 Contact string `json:"contact,omitempty"`
13 SupportedNIPs []int `json:"supported_nips"`
14 Software string `json:"software"`
15 Version string `json:"version"`
16 Limitation *Limits `json:"limitation,omitempty"`
17}
18
19type Limits struct {
20 MaxMessageLength int `json:"max_message_length,omitempty"`
21 MaxSubscriptions int `json:"max_subscriptions,omitempty"`
22 MaxFilters int `json:"max_filters,omitempty"`
23 MaxLimit int `json:"max_limit,omitempty"`
24 MaxSubidLength int `json:"max_subid_length,omitempty"`
25 MaxEventTags int `json:"max_event_tags,omitempty"`
26 MaxContentLength int `json:"max_content_length,omitempty"`
27 MinPowDifficulty int `json:"min_pow_difficulty,omitempty"`
28 AuthRequired bool `json:"auth_required"`
29 PaymentRequired bool `json:"payment_required"`
30 RestrictedWrites bool `json:"restricted_writes"`
31}
32
33func (h *Handler) ServeNIP11(w http.ResponseWriter, r *http.Request) {
34 info := RelayInfo{
35 Name: "nostr-grpc relay",
36 Description: "High-performance Nostr relay with gRPC, Connect, and WebSocket support",
37 SupportedNIPs: []int{1, 9, 11},
38 Software: "northwest.io/nostr-grpc",
39 Version: "0.1.0",
40 Limitation: &Limits{
41 MaxMessageLength: 65536,
42 MaxSubscriptions: 20,
43 MaxFilters: 10,
44 MaxLimit: 5000,
45 MaxSubidLength: 64,
46 MaxEventTags: 2000,
47 MaxContentLength: 65536,
48 AuthRequired: false,
49 PaymentRequired: false,
50 RestrictedWrites: false,
51 },
52 }
53
54 w.Header().Set("Content-Type", "application/nostr+json")
55 w.Header().Set("Access-Control-Allow-Origin", "*")
56 w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Accept")
57 w.Header().Set("Access-Control-Allow-Methods", "GET")
58
59 json.NewEncoder(w).Encode(info)
60}