You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.7 KiB
133 lines
3.7 KiB
package relaytester |
|
|
|
import ( |
|
"crypto/rand" |
|
"fmt" |
|
"time" |
|
|
|
"lol.mleku.dev/chk" |
|
"git.mleku.dev/mleku/nostr/interfaces/signer/p8k" |
|
"git.mleku.dev/mleku/nostr/encoders/bech32encoding" |
|
"git.mleku.dev/mleku/nostr/encoders/event" |
|
"git.mleku.dev/mleku/nostr/encoders/hex" |
|
"git.mleku.dev/mleku/nostr/encoders/kind" |
|
"git.mleku.dev/mleku/nostr/encoders/tag" |
|
) |
|
|
|
// KeyPair represents a test keypair. |
|
type KeyPair struct { |
|
Secret *p8k.Signer |
|
Pubkey []byte |
|
Nsec string |
|
Npub string |
|
} |
|
|
|
// GenerateKeyPair generates a new keypair for testing. |
|
func GenerateKeyPair() (kp *KeyPair, err error) { |
|
kp = &KeyPair{} |
|
if kp.Secret, err = p8k.New(); chk.E(err) { |
|
return |
|
} |
|
if err = kp.Secret.Generate(); chk.E(err) { |
|
return |
|
} |
|
kp.Pubkey = kp.Secret.Pub() |
|
nsecBytes, err := bech32encoding.BinToNsec(kp.Secret.Sec()) |
|
if chk.E(err) { |
|
return |
|
} |
|
kp.Nsec = string(nsecBytes) |
|
npubBytes, err := bech32encoding.BinToNpub(kp.Pubkey) |
|
if chk.E(err) { |
|
return |
|
} |
|
kp.Npub = string(npubBytes) |
|
return |
|
} |
|
|
|
// CreateEvent creates a signed event with the given parameters. |
|
func CreateEvent(signer *p8k.Signer, kindNum uint16, content string, tags *tag.S) (ev *event.E, err error) { |
|
ev = event.New() |
|
ev.CreatedAt = time.Now().Unix() |
|
ev.Kind = kindNum |
|
ev.Content = []byte(content) |
|
if tags != nil { |
|
ev.Tags = tags |
|
} else { |
|
ev.Tags = tag.NewS() |
|
} |
|
if err = ev.Sign(signer); chk.E(err) { |
|
return |
|
} |
|
return |
|
} |
|
|
|
// CreateEventWithTags creates an event with specific tags. |
|
func CreateEventWithTags(signer *p8k.Signer, kindNum uint16, content string, tagPairs [][]string) (ev *event.E, err error) { |
|
tags := tag.NewS() |
|
for _, pair := range tagPairs { |
|
if len(pair) >= 2 { |
|
// Build tag fields as []byte variadic arguments |
|
tagFields := make([][]byte, len(pair)) |
|
tagFields[0] = []byte(pair[0]) |
|
for i := 1; i < len(pair); i++ { |
|
tagFields[i] = []byte(pair[i]) |
|
} |
|
tags.Append(tag.NewFromBytesSlice(tagFields...)) |
|
} |
|
} |
|
return CreateEvent(signer, kindNum, content, tags) |
|
} |
|
|
|
// CreateReplaceableEvent creates a replaceable event (kind 0-3, 10000-19999). |
|
func CreateReplaceableEvent(signer *p8k.Signer, kindNum uint16, content string) (ev *event.E, err error) { |
|
return CreateEvent(signer, kindNum, content, nil) |
|
} |
|
|
|
// CreateEphemeralEvent creates an ephemeral event (kind 20000-29999). |
|
func CreateEphemeralEvent(signer *p8k.Signer, kindNum uint16, content string) (ev *event.E, err error) { |
|
return CreateEvent(signer, kindNum, content, nil) |
|
} |
|
|
|
// CreateDeleteEvent creates a deletion event (kind 5). |
|
func CreateDeleteEvent(signer *p8k.Signer, eventIDs [][]byte, reason string) (ev *event.E, err error) { |
|
tags := tag.NewS() |
|
for _, id := range eventIDs { |
|
// e tags must contain hex-encoded event IDs |
|
tags.Append(tag.NewFromBytesSlice([]byte("e"), []byte(hex.Enc(id)))) |
|
} |
|
if reason != "" { |
|
tags.Append(tag.NewFromBytesSlice([]byte("content"), []byte(reason))) |
|
} |
|
return CreateEvent(signer, kind.EventDeletion.K, reason, tags) |
|
} |
|
|
|
// CreateParameterizedReplaceableEvent creates a parameterized replaceable event (kind 30000-39999). |
|
func CreateParameterizedReplaceableEvent(signer *p8k.Signer, kindNum uint16, content string, dTag string) (ev *event.E, err error) { |
|
tags := tag.NewS() |
|
tags.Append(tag.NewFromBytesSlice([]byte("d"), []byte(dTag))) |
|
return CreateEvent(signer, kindNum, content, tags) |
|
} |
|
|
|
// RandomID generates a random 32-byte ID. |
|
func RandomID() (id []byte, err error) { |
|
id = make([]byte, 32) |
|
if _, err = rand.Read(id); err != nil { |
|
return nil, fmt.Errorf("failed to generate random ID: %w", err) |
|
} |
|
return |
|
} |
|
|
|
// MustHex decodes a hex string or panics. |
|
func MustHex(s string) []byte { |
|
b, err := hex.Dec(s) |
|
if err != nil { |
|
panic(fmt.Sprintf("invalid hex: %s", s)) |
|
} |
|
return b |
|
} |
|
|
|
// HexID returns the hex-encoded event ID. |
|
func HexID(ev *event.E) string { |
|
return hex.Enc(ev.ID) |
|
}
|
|
|