package main import ( "context" "fmt" "log" "net/http" "os" "github.com/fiatjaf/eventstore/lmdb" "github.com/fiatjaf/khatru" "github.com/joho/godotenv" "github.com/nbd-wtf/go-nostr" ) var config Config var relay *khatru.Relay var walletKinds = []int{ nostr.KindNWCWalletInfo, nostr.KindNWCWalletRequest, nostr.KindNWCWalletResponse, nostr.KindNutZap, nostr.KindNutZapInfo, nostr.KindZap, nostr.KindZapRequest, 17375, 7375, 7376, 7374, } type Config struct { RelayName string RelayPubkey string RelayDescription string RelayIcon string RelaySoftware string RelayVersion string RelayPort string LmdbMapSize int64 LmdbPath string } func main() { relay = khatru.NewRelay() config = LoadConfig() db := lmdb.LMDBBackend{ Path: config.LmdbPath, MapSize: config.LmdbMapSize, } if err := db.Init(); err != nil { panic(err) } relay.RejectFilter = append(relay.RejectFilter, func(ctx context.Context, filter nostr.Filter) (bool, string) { if !containsOnlyWalletKids(filter.Kinds) { fmt.Println("attempted to subscribe to non-wallet kinds", filter.Kinds) return true, "invalid-filter: only wallet kinds are allowed" } return false, "" }) relay.RejectEvent = append(relay.RejectEvent, func(ctx context.Context, event *nostr.Event) (bool, string) { if !containsOnlyWalletKids([]int{event.Kind}) { fmt.Println("attempted to publish non-wallet kind", event.Kind) return true, "invalid-event: only wallet kinds are allowed" } return false, "" }) relay.StoreEvent = append(relay.StoreEvent, db.SaveEvent) relay.QueryEvents = append(relay.QueryEvents, db.QueryEvents) relay.ReplaceEvent = append(relay.ReplaceEvent, db.ReplaceEvent) addr := fmt.Sprintf("%s:%s", "0.0.0.0", config.RelayPort) log.Printf("🔗 listening at %s", addr) err := http.ListenAndServe(addr, relay) if err != nil { log.Fatal(err) } } func LoadConfig() Config { _ = godotenv.Load(".env") config = Config{ RelayName: os.Getenv("RELAY_NAME"), RelayPubkey: os.Getenv("RELAY_PUBKEY"), RelayDescription: os.Getenv("RELAY_DESCRIPTION"), RelayIcon: os.Getenv("RELAY_ICON"), RelaySoftware: "https://github.com/bitvora/wallet-relay", RelayVersion: "0.1.0", RelayPort: os.Getenv("RELAY_PORT"), LmdbPath: os.Getenv("LMDB_PATH"), } relay.Info.Name = config.RelayName relay.Info.PubKey = config.RelayPubkey relay.Info.Description = config.RelayDescription relay.Info.Icon = config.RelayIcon relay.Info.Software = config.RelaySoftware relay.Info.Version = config.RelayVersion return config } func containsOnlyWalletKids(kinds []int) bool { walletKindSet := make(map[int]struct{}) for _, walletKind := range walletKinds { walletKindSet[walletKind] = struct{}{} } for _, kind := range kinds { if _, exists := walletKindSet[kind]; !exists { return false } } return true }