Add signevent to nip86

This commit is contained in:
Jon Staab
2026-06-22 17:13:41 -07:00
parent a525b66054
commit fa7d25a59b
2 changed files with 74 additions and 0 deletions
+9
View File
@@ -48,6 +48,7 @@ type RelayManagementAPI struct {
DeleteRole func(ctx context.Context, id string) error
AssignRole func(ctx context.Context, pubkey nostr.PubKey, roleID string) error
UnassignRole func(ctx context.Context, pubkey nostr.PubKey, roleID string) error
SignEvent func(ctx context.Context, kind nostr.Kind, createdAt nostr.Timestamp, tags nostr.Tags, content string) (nostr.Event, error)
Generic func(ctx context.Context, request nip86.Request) (nip86.Response, error)
}
@@ -375,6 +376,14 @@ func (rl *Relay) HandleNIP86(w http.ResponseWriter, r *http.Request) {
} else {
resp.Result = true
}
case nip86.SignEvent:
if rl.ManagementAPI.SignEvent == nil {
resp.Error = fmt.Sprintf("method %s not supported", thing.MethodName())
} else if result, err := rl.ManagementAPI.SignEvent(ctx, thing.Kind, thing.CreatedAt, thing.Tags, thing.Content); err != nil {
resp.Error = err.Error()
} else {
resp.Result = result
}
case nip86.ListDisallowedKinds:
if rl.ManagementAPI.ListDisallowedKinds == nil {
resp.Error = fmt.Sprintf("method %s not supported", thing.MethodName())
+65
View File
@@ -330,6 +330,32 @@ func DecodeRequest(req Request) (MethodParams, error) {
return nil, fmt.Errorf("missing role id param for '%s'", req.Method)
}
return UnassignRole{pk, roleID}, nil
case "signevent":
if len(req.Params) == 0 {
return nil, fmt.Errorf("invalid number of params for '%s'", req.Method)
}
tmpl, ok := req.Params[0].(map[string]any)
if !ok {
return nil, fmt.Errorf("missing event param for '%s'", req.Method)
}
kind, ok := tmpl["kind"].(float64)
if !ok || math.Trunc(kind) != kind {
return nil, fmt.Errorf("invalid kind '%v' for '%s'", tmpl["kind"], req.Method)
}
var createdAt nostr.Timestamp
if ca, ok := tmpl["created_at"]; ok {
caf, ok := ca.(float64)
if !ok || math.Trunc(caf) != caf {
return nil, fmt.Errorf("invalid created_at '%v' for '%s'", ca, req.Method)
}
createdAt = nostr.Timestamp(caf)
}
tags, err := coerceTags(tmpl["tags"])
if err != nil {
return nil, fmt.Errorf("invalid tags for '%s': %w", req.Method, err)
}
content, _ := tmpl["content"].(string)
return SignEvent{nostr.Kind(kind), createdAt, tags, content}, nil
case "stats":
return Stats{}, nil
default:
@@ -350,6 +376,35 @@ func coerceInt(v any) int {
return 0
}
// coerceTags converts a decoded JSON value (an array of arrays of strings) into
// nostr.Tags. A nil value yields nil tags; any other shape is an error.
func coerceTags(v any) (nostr.Tags, error) {
if v == nil {
return nil, nil
}
rawTags, ok := v.([]any)
if !ok {
return nil, fmt.Errorf("tags must be an array")
}
tags := make(nostr.Tags, len(rawTags))
for i, rt := range rawTags {
rawTag, ok := rt.([]any)
if !ok {
return nil, fmt.Errorf("tag %d must be an array", i)
}
tag := make(nostr.Tag, len(rawTag))
for j, el := range rawTag {
s, ok := el.(string)
if !ok {
return nil, fmt.Errorf("tag %d element %d must be a string", i, j)
}
tag[j] = s
}
tags[i] = tag
}
return tags, nil
}
type MethodParams interface {
MethodName() string
}
@@ -384,6 +439,7 @@ var (
_ MethodParams = (*DeleteRole)(nil)
_ MethodParams = (*AssignRole)(nil)
_ MethodParams = (*UnassignRole)(nil)
_ MethodParams = (*SignEvent)(nil)
_ MethodParams = (*Stats)(nil)
)
@@ -563,6 +619,15 @@ type UnassignRole struct {
func (UnassignRole) MethodName() string { return "unassignrole" }
type SignEvent struct {
Kind nostr.Kind
CreatedAt nostr.Timestamp
Tags nostr.Tags
Content string
}
func (SignEvent) MethodName() string { return "signevent" }
type Stats struct{}
func (Stats) MethodName() string { return "stats" }