summaryrefslogtreecommitdiffstats
path: root/cmd/testclient
diff options
context:
space:
mode:
authorbndw <ben@bdw.to>2026-02-13 17:50:09 -0800
committerbndw <ben@bdw.to>2026-02-13 17:50:09 -0800
commite3b336ab45a6acf8a02a8c0f1b6d22fb3a320826 (patch)
tree3072812e21fd36a955e6e757d974c45f646f0308 /cmd/testclient
parent62d31434ddbadff18580826576e1169f539e23f0 (diff)
feat: add relay server and test client
Server (cmd/relay): - gRPC server on :50051 (configurable) - SQLite database (default: relay.db) - Graceful shutdown on SIGTERM/SIGINT Test client (cmd/testclient): - Generates key - Publishes event - Queries events back Build: - make build (relay) - make build-client (test client) - make build-all (both)
Diffstat (limited to 'cmd/testclient')
-rw-r--r--cmd/testclient/main.go85
1 files changed, 85 insertions, 0 deletions
diff --git a/cmd/testclient/main.go b/cmd/testclient/main.go
new file mode 100644
index 0000000..571751e
--- /dev/null
+++ b/cmd/testclient/main.go
@@ -0,0 +1,85 @@
1package main
2
3import (
4 "context"
5 "flag"
6 "log"
7 "time"
8
9 "google.golang.org/grpc"
10 "google.golang.org/grpc/credentials/insecure"
11
12 pb "northwest.io/nostr-grpc/api/nostr/v1"
13 "northwest.io/nostr-grpc/internal/nostr"
14)
15
16func main() {
17 addr := flag.String("addr", "localhost:50051", "relay address")
18 flag.Parse()
19
20 conn, err := grpc.NewClient(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
21 if err != nil {
22 log.Fatalf("failed to connect: %v", err)
23 }
24 defer conn.Close()
25
26 client := pb.NewNostrRelayClient(conn)
27 ctx := context.Background()
28
29 key, err := nostr.GenerateKey()
30 if err != nil {
31 log.Fatalf("failed to generate key: %v", err)
32 }
33
34 log.Printf("Generated key: %s", key.Npub())
35
36 event := &nostr.Event{
37 PubKey: key.Public(),
38 CreatedAt: time.Now().Unix(),
39 Kind: 1,
40 Tags: nostr.Tags{},
41 Content: "Hello from gRPC client!",
42 }
43
44 if err := key.Sign(event); err != nil {
45 log.Fatalf("failed to sign event: %v", err)
46 }
47
48 pbEvent := &pb.Event{
49 Id: event.ID,
50 Pubkey: event.PubKey,
51 CreatedAt: event.CreatedAt,
52 Kind: int32(event.Kind),
53 Tags: []*pb.Tag{},
54 Content: event.Content,
55 Sig: event.Sig,
56 }
57
58 log.Println("Publishing event...")
59 resp, err := client.PublishEvent(ctx, &pb.PublishEventRequest{Event: pbEvent})
60 if err != nil {
61 log.Fatalf("failed to publish: %v", err)
62 }
63
64 if resp.Accepted {
65 log.Printf("✓ Event published successfully: %s", event.ID)
66 } else {
67 log.Printf("✗ Event rejected: %s", resp.Message)
68 return
69 }
70
71 log.Println("Querying events...")
72 queryResp, err := client.QueryEvents(ctx, &pb.QueryRequest{
73 Filters: []*pb.Filter{
74 {Authors: []string{key.Public()}},
75 },
76 })
77 if err != nil {
78 log.Fatalf("failed to query: %v", err)
79 }
80
81 log.Printf("Found %d events", len(queryResp.Events))
82 for _, e := range queryResp.Events {
83 log.Printf(" - %s: %s", e.Id[:16], e.Content)
84 }
85}