latest versions
This commit is contained in:
210
waku2/main.go
Normal file
210
waku2/main.go
Normal file
@@ -0,0 +1,210 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/waku-org/go-waku/waku/v2/node"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/waku-org/go-waku/waku/v2/protocol/relay"
|
||||
"github.com/waku-org/go-waku/waku/v2/utils"
|
||||
)
|
||||
|
||||
const sharedKey = "2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe"
|
||||
|
||||
type ChatMessage struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Nick string `json:"nick"`
|
||||
Message string `json:"message"`
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
hostAddr, _ := net.ResolveTCPAddr("tcp", "0.0.0.0:0")
|
||||
|
||||
wakuNode, err := node.New(
|
||||
node.WithHostAddress(hostAddr),
|
||||
node.WithWakuRelay(),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal("Error creating waku node:", err)
|
||||
}
|
||||
|
||||
if err := wakuNode.Start(ctx); err != nil {
|
||||
log.Fatal("Error starting waku node:", err)
|
||||
}
|
||||
defer wakuNode.Stop()
|
||||
|
||||
pubsubTopic := protocol.DefaultPubsubTopic{}.String()
|
||||
contentTopic, _ := protocol.NewContentTopic("waku2chat", "1", "chat", "proto")
|
||||
|
||||
contentFilter := protocol.NewContentFilter(pubsubTopic, contentTopic.String())
|
||||
subs, err := wakuNode.Relay().Subscribe(ctx, contentFilter)
|
||||
if err != nil {
|
||||
log.Fatal("Error subscribing to topic:", err)
|
||||
}
|
||||
|
||||
if len(subs) == 0 {
|
||||
log.Fatal("No subscriptions created")
|
||||
}
|
||||
sub := subs[0]
|
||||
|
||||
log.Println("Waku2 Chat Started")
|
||||
log.Println("Node ID:", wakuNode.ID())
|
||||
log.Println("Listening on:", wakuNode.ListenAddresses())
|
||||
log.Println("Shared Key:", sharedKey)
|
||||
|
||||
var connected bool
|
||||
if len(wakuNode.Relay().PubSub().ListPeers(pubsubTopic)) == 0 {
|
||||
log.Println("No peers connected yet. Trying to connect to bootstrap nodes...")
|
||||
connected = connectToBootstrapNodes(ctx, wakuNode)
|
||||
} else {
|
||||
connected = true
|
||||
}
|
||||
|
||||
if !connected {
|
||||
log.Fatal("Failed to connect to Waku network. Exiting.")
|
||||
}
|
||||
|
||||
go receiveMessages(ctx, sub)
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
nick := fmt.Sprintf("user-%s", generateRandomID())
|
||||
|
||||
fmt.Printf("Your nickname: %s\n", nick)
|
||||
fmt.Println("Type messages and press Enter to send (or 'quit' to exit):")
|
||||
|
||||
for {
|
||||
fmt.Print("> ")
|
||||
text, _ := reader.ReadString('\n')
|
||||
text = strings.TrimSpace(text)
|
||||
|
||||
if text == "quit" {
|
||||
break
|
||||
}
|
||||
|
||||
if text == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if still connected before sending
|
||||
if len(wakuNode.Relay().PubSub().ListPeers(pubsubTopic)) == 0 {
|
||||
log.Println("Not connected to any peers. Message not sent.")
|
||||
continue
|
||||
}
|
||||
|
||||
msg := ChatMessage{
|
||||
Timestamp: time.Now(),
|
||||
Nick: nick,
|
||||
Message: text,
|
||||
Key: sharedKey,
|
||||
}
|
||||
|
||||
msgBytes, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
log.Println("Error marshaling message:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
wakuMsg := &pb.WakuMessage{
|
||||
Payload: msgBytes,
|
||||
ContentTopic: contentTopic.String(),
|
||||
Timestamp: utils.GetUnixEpochFrom(wakuNode.Timesource().Now()),
|
||||
}
|
||||
|
||||
_, err = wakuNode.Relay().Publish(ctx, wakuMsg)
|
||||
if err != nil {
|
||||
log.Println("Error publishing message:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func receiveMessages(ctx context.Context, sub *relay.Subscription) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case envelope := <-sub.Ch:
|
||||
if envelope.Message() == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var msg ChatMessage
|
||||
err := json.Unmarshal(envelope.Message().Payload, &msg)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if msg.Key != sharedKey {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("\n[%s] %s: %s\n> ", msg.Timestamp.Format("15:04:05"), msg.Nick, msg.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func connectToBootstrapNodes(ctx context.Context, wakuNode *node.WakuNode) bool {
|
||||
bootstrapNodes := []string{
|
||||
// Latest Waku v2 production fleet nodes from waku.org
|
||||
"/dns4/node-01.do-ams3.waku.test.status.im/tcp/30303/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
|
||||
"/dns4/node-01.gc-us-central1-a.waku.test.status.im/tcp/30303/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS",
|
||||
"/dns4/node-01.ac-cn-hongkong-c.waku.test.status.im/tcp/30303/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm",
|
||||
|
||||
// Waku Sandbox nodes - actively maintained
|
||||
"/dns4/boot-01.do-ams3.waku.sandbox.status.im/tcp/30303/p2p/16Uiu2HAmPLtEfJpCyUM9JcVDhP3zJ1Mxx1L5WzXp5qJFH2rqVGJS",
|
||||
"/dns4/boot-01.gc-us-central1-a.waku.sandbox.status.im/tcp/30303/p2p/16Uiu2HAmQq5okTJWCUXo8F8Kf3kQ2kLPdqVUoJmqZ3cFWV3u8HuH",
|
||||
"/dns4/boot-01.ac-cn-hongkong-c.waku.sandbox.status.im/tcp/30303/p2p/16Uiu2HAmQJvn5BKvdXFPRTCNBVrWwAJ3dCLKxZDPtJFhLFpHQYoS",
|
||||
|
||||
// Current production nodes with resolved IPs
|
||||
"/dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/30303/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
|
||||
"/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/30303/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA",
|
||||
"/dns4/node-01.ac-cn-hongkong-c.wakuv2.prod.statusim.net/tcp/30303/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD",
|
||||
|
||||
// Use resolved IPs directly in case DNS is issue
|
||||
"/ip4/188.166.135.145/tcp/30303/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
|
||||
"/ip4/34.121.100.108/tcp/30303/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA",
|
||||
"/ip4/8.210.222.231/tcp/30303/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD",
|
||||
}
|
||||
|
||||
connected := false
|
||||
for _, addr := range bootstrapNodes {
|
||||
// Create a context with 2 second timeout
|
||||
dialCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
|
||||
err := wakuNode.DialPeer(dialCtx, addr)
|
||||
cancel()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Could not connect to bootstrap node: %v", err)
|
||||
} else {
|
||||
log.Printf("Connected to bootstrap node: %s", addr)
|
||||
connected = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !connected {
|
||||
log.Println("ERROR: Could not connect to any bootstrap nodes")
|
||||
log.Println("The program will not be able to send or receive messages.")
|
||||
}
|
||||
|
||||
return connected
|
||||
}
|
||||
|
||||
func generateRandomID() string {
|
||||
b := make([]byte, 4)
|
||||
rand.Read(b)
|
||||
return hex.EncodeToString(b)
|
||||
}
|
||||
Reference in New Issue
Block a user