package main import ( "bytes" "context" "encoding/json" "fmt" "net/http" "time" rice "github.com/GeertJohan/go.rice" "github.com/gorilla/websocket" "github.com/ipld/go-car" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p-core/peer" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/lib/blockstore" ) var topic = "/fil/headnotifs/" func init() { genBytes := build.MaybeGenesis() if len(genBytes) == 0 { topic = "" return } bs := blockstore.NewTemporary() c, err := car.LoadCar(bs, bytes.NewReader(genBytes)) if err != nil { panic(err) } if len(c.Roots) != 1 { panic("expected genesis file to have one root") } fmt.Printf("Genesis CID: %s\n", c.Roots[0]) topic = topic + c.Roots[0].String() } var upgrader = websocket.Upgrader{ WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool { return true }, } func main() { if topic == "" { fmt.Println("FATAL: No genesis found") return } ctx := context.Background() host, err := libp2p.New( ctx, libp2p.Defaults, ) if err != nil { panic(err) } ps, err := pubsub.NewGossipSub(ctx, host) if err != nil { panic(err) } pi, err := build.BuiltinBootstrap() if err != nil { panic(err) } if err := host.Connect(ctx, pi[0]); err != nil { panic(err) } http.HandleFunc("/sub", handler(ps)) http.Handle("/", http.FileServer(rice.MustFindBox("townhall/build").HTTPBox())) fmt.Println("listening on http://localhost:2975") if err := http.ListenAndServe("0.0.0.0:2975", nil); err != nil { panic(err) } } type update struct { From peer.ID Update json.RawMessage Time uint64 } func handler(ps *pubsub.PubSub) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") if r.Header.Get("Sec-WebSocket-Protocol") != "" { w.Header().Set("Sec-WebSocket-Protocol", r.Header.Get("Sec-WebSocket-Protocol")) } conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } sub, err := ps.Subscribe(topic) //nolint if err != nil { return } defer sub.Cancel() //nolint:errcheck fmt.Println("new conn") for { msg, err := sub.Next(r.Context()) if err != nil { return } //fmt.Println(msg) if err := conn.WriteJSON(update{ From: peer.ID(msg.From), Update: msg.Data, Time: uint64(time.Now().UnixNano() / 1000_000), }); err != nil { return } } } }