mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-03-17 21:32:56 +01:00
I thought `close()` would be nice because it would be cheap and not lock the goroutine while waiting for the receiver to acknowledge the thing, but turns out it introduces the serious risk of users putting <- sub.EndOfStoredEvents in the same for { select {} } statement as sub.Events, for example, and they they get into an infinite loop. we had this same problem here inside this same library, and what is fixed in 242af0bf76e4b23de47012244efb95ccec9e4374 by @mattn.
go-nostr
A set of useful things for Nostr Protocol implementations.
go get github.com/nbd-wtf/go-nostr
Generating a key
package main
import (
"fmt"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19"
)
func main() {
sk := nostr.GeneratePrivateKey()
pk, _ := nostr.GetPublicKey(sk)
nsec, _ := nip19.EncodePrivateKey(sk)
npub, _ := nip19.EncodePublicKey(pk)
fmt.Println("sk:", sk)
fmt.Println("pk:", pk)
fmt.Println(nsec)
fmt.Println(npub)
}
Subscribing to a single relay
ctx := context.Background()
relay, err := nostr.RelayConnect(ctx, "wss://nostr.zebedee.cloud")
if err != nil {
panic(err)
}
npub := "npub1422a7ws4yul24p0pf7cacn7cghqkutdnm35z075vy68ggqpqjcyswn8ekc"
var filters nostr.Filters
if _, v, err := nip19.Decode(npub); err == nil {
pub := v.(string)
filters = []nostr.Filter{{
Kinds: []int{nostr.KindTextNote},
Authors: []string{pub},
Limit: 1,
}}
} else {
panic(err)
}
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
defer cancel()
sub, err := relay.Subscribe(ctx, filters)
if err != nil {
panic(err)
}
for ev := range sub.Events {
// handle returned event.
// channel will stay open until the ctx is cancelled (in this case, context timeout)
fmt.Println(ev.ID)
}
Publishing to two relays
sk := nostr.GeneratePrivateKey()
pub, _ := nostr.GetPublicKey(sk)
ev := nostr.Event{
PubKey: pub,
CreatedAt: nostr.Now(),
Kind: nostr.KindTextNote,
Tags: nil,
Content: "Hello World!",
}
// calling Sign sets the event ID field and the event Sig field
ev.Sign(sk)
// publish the event to two relays
ctx := context.Background()
for _, url := range []string{"wss://nostr.zebedee.cloud", "wss://nostr-pub.wellorder.net"} {
relay, err := nostr.RelayConnect(ctx, url)
if err != nil {
fmt.Println(err)
continue
}
if err := relay.Publish(ctx, ev); err != nil {
fmt.Println(err)
continue
}
fmt.Printf("published to %s\n", url)
}
Example script
go run example/example.go
Warning: risk of goroutine bloat (if used incorrectly)
Remember to cancel subscriptions, either by calling .Unsub()
on them or ensuring their context.Context
will be canceled at some point.
If you don't do that they will keep creating a new goroutine for every new event that arrives and if you have stopped listening on the
sub.Events
channel that will cause chaos and doom in your program.
Languages
C
83.7%
Go
15.5%
Assembly
0.7%
Just
0.1%