Announce NIP-46 support in relay metadata (#3)

Co-authored-by: highperfocused <highperfocused@pm.me>
This commit is contained in:
mroxso
2026-06-16 23:17:05 +02:00
committed by GitHub
parent 3755d0cbce
commit 1feea858f3
2 changed files with 112 additions and 1 deletions

View File

@@ -64,7 +64,7 @@ func main() {
relay.Info.Software = "https://github.com/layer-systems/relay"
relay.Info.Version = "0.1.1"
relay.Info.SupportedNIPs = []any{1, 11, 17, 40, 42, 70, 86}
relay.Info.SupportedNIPs = []any{1, 11, 17, 40, 42, 46, 70, 86}
// Open shared database connection with aggressive pool limits
managementDB, err := sql.Open("postgres", getEnv("DATABASE_URL", "postgresql://postgres:postgres@db:5432/khatru-relay?sslmode=disable"))

111
nip46_integration_test.go Normal file
View File

@@ -0,0 +1,111 @@
package main
import (
"context"
"net/http/httptest"
"os"
"testing"
"time"
"github.com/fiatjaf/eventstore/slicestore"
"github.com/fiatjaf/khatru"
"github.com/fiatjaf/khatru/policies"
"github.com/nbd-wtf/go-nostr"
)
func TestNIP46Transport(t *testing.T) {
url := os.Getenv("NIP46_RELAY_URL")
var store *slicestore.SliceStore
if url == "" {
relay := khatru.NewRelay()
store = &slicestore.SliceStore{}
store.Init()
relay.StoreEvent = append(relay.StoreEvent, store.SaveEvent)
relay.QueryEvents = append(relay.QueryEvents, store.QueryEvents)
relay.RejectEvent = append(relay.RejectEvent, policies.ValidateKind)
policies.ApplySaneDefaults(relay)
relay.RejectFilter = append(relay.RejectFilter, RejectNonAuthenticatedGiftWrapQueries)
server := httptest.NewServer(relay)
defer server.Close()
url = "ws" + server.URL[4:]
}
clientSecret := nostr.GeneratePrivateKey()
clientPublic, err := nostr.GetPublicKey(clientSecret)
if err != nil {
t.Fatal(err)
}
signerSecret := nostr.GeneratePrivateKey()
signerPublic, err := nostr.GetPublicKey(signerSecret)
if err != nil {
t.Fatal(err)
}
event := nostr.Event{
PubKey: clientPublic,
CreatedAt: nostr.Now(),
Kind: nostr.KindNostrConnect,
Tags: nostr.Tags{{"p", signerPublic}},
Content: "opaque-nip44-payload",
}
if err := event.Sign(clientSecret); err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
receiver, err := nostr.RelayConnect(ctx, url)
if err != nil {
t.Fatal(err)
}
defer receiver.Close()
sender, err := nostr.RelayConnect(ctx, url)
if err != nil {
t.Fatal(err)
}
defer sender.Close()
sub, err := receiver.Subscribe(ctx, nostr.Filters{{
Kinds: []int{nostr.KindNostrConnect},
Tags: nostr.TagMap{"p": []string{signerPublic}},
Since: &event.CreatedAt,
LimitZero: true,
}})
if err != nil {
t.Fatal(err)
}
defer sub.Unsub()
select {
case <-sub.EndOfStoredEvents:
case reason := <-sub.ClosedReason:
t.Fatalf("subscription closed: %s", reason)
case <-ctx.Done():
t.Fatal("timed out waiting for EOSE")
}
if err := sender.Publish(ctx, event); err != nil {
t.Fatalf("publish NIP-46 event: %v", err)
}
select {
case received := <-sub.Events:
if received.ID != event.ID {
t.Fatalf("received event %s, want %s", received.ID, event.ID)
}
case <-ctx.Done():
t.Fatal("timed out waiting for NIP-46 event")
}
if store != nil {
queryCtx, queryCancel := context.WithTimeout(context.Background(), time.Second)
defer queryCancel()
stored, err := store.QueryEvents(queryCtx, nostr.Filter{IDs: []string{event.ID}})
if err != nil {
t.Fatal(err)
}
if got := <-stored; got != nil {
t.Fatalf("ephemeral NIP-46 event was stored: %s", got.ID)
}
}
}