# farseer: Another kind of Farcaster hub Source: https://github.com/noctisatrae/farseer Kiwi News: https://news.kiwistand.com/stories/farseer-Another-kind-of-Farcaster-hub?index=0x66866602378090fb374eb1212afba2a18a80fac785e4a8c97d9a14bc8f41dbd4e4d5add7 Submitted by noctisatrae.eth on 2024-07-04 UTC, 12 upvotes, 6 comments ## Summary farseer is a lightweight re-implementation of a Farcaster hub that does not require syncing to operate and can be extended through plugins. Users can bring their own database, logic and infrastructure to harvest protocol data. The project offers a Docker setup that starts the hub with default behavior and plugins, or a manual route that requires Go 1.22+ to compile the binary and plugins. Configuration is handled through a config.toml file, which sets the public IP, gossip port, bootstrap peers, and per-plugin options such as the PostgreSQL plugin's database address, allowed message types and tracked FIDs. Plugins export a Handler struct with functions for message types such as cast adds and reaction adds. ## Article farseer is a lightweight re-implementation of a Farcaster hub that does not require syncing to operate & is extendable through plugins. In short, you can bring your own DB, logic & infrastructure and harvest data from the protocol while fostering decentralization! If you like this project, consider giving a star to the repository: it's a real help for motivation! Looking for PRs, issues & feedback, so feel free to write something and send it to me! See the todos to see what's left to do :) How to get started? General architecture There are four components to farseer: a config file (config.toml), plugins, the identity file & the hub itself. Here's a quick rundown of how it works: . ├── compiled_handlers <== where you'll put your compiled plugins │ └── postgresql.so ├── config.toml <== configure the behaviour of the hubs & the plugin ├── docker-compose.yml <== infrastructure example ├── Dockerfile <== automatization of the process ├── hub_identity <== SECRET private key of the hub (needs to be generated for docker-compose) ├── relay <== what you'll run (binary) Easy mode (Docker) Compiling the plugins for Docker Generate a hub_identity using the latest utility found in the release section or run the code in the identity folder. Don't forget to put in the root of the repository! Change your public IP address in the config.toml file so other peers can connect to you! Run this command to start the containers! This will start the hub with the default behavior & plug-ins. The DIY way Get the source from somewhere: git clone https://github.com/noctisatrae/farseer.git Compile with Go 1.22+ and produce a binary in the same directory where config.toml is: go build -v -o app ./relay Compile your plugins/custom handlers using the plugin mode of go build (here we'll compile the example postgresql plugin): go build -buildmode=plugin -o ./compiled_handlers/postgresql.so postgresql/postgresql.go There's a lot going here but essentially, we tell Go to build a plugin from the postgresql.go file output it in the compiled_handlers folder that will be read by the hub to exectute the custom logic. Now, you'll start the hub by running: For fine-tuning the behavior of the hub, see the configuration section Configuration [hub] # How can other peers reach your hub! PublicHubIp = "92.158.95.48" GossipPort = 2282 # Who will be your first contacts? # Quick rundown of the libp2p multiaddr format: # /typeOfAddr/addr/protocol/port/p2p/publicIdentity BootstrapPeers = [ # Those are the peers used by the farcaster dev team, nemes.farcaster.xyz is the public one & the others will certainly not make the connection with you! # As of the 25th of July 2024, nemes.farcaster.xyz is not working # "/dns/lamia.farcaster.xyz/tcp/2283/p2p/12D3KooWJECuSHn5edaorpufE9ceAoqR5zcAuD4ThoyDzVaz77GV", # "/dns/nemes.farcaster.xyz/tcp/2283/p2p/12D3KooWMQrf6unpGJfLBmTGy3eKTo4cGcXktWRbgMnfbZLXqBbn", # "/dns/hoyt.farcaster.xyz/tcp/2283/p2p/12D3KooWRnSZUxjVJjbSHhVKpXtvibMarSfLSKDBeMpfVaNm1Joo", ] # Super handy when things go wrong! Debug = false # Not sure of the usefulness of this, it's something I have yet to experiment with BufferSize = 128 ContactInterval = 30 # The interesting part! # To define the behavior of a plugin in `compiled_handlers`, you write: # [handlers.(pluginName)] [handlers.postgresql] # This is common to all plugins: do you want to enable it? Enabled = true # Below, the options are specific: # The options below are determined to by the developer of the plugin. They manage how the arguments are parsed and used! DbAddress = "postgres://postgres:example@db:5432/postgres" # refer to the enum l.60 in message.proto for the integer of msg types | here we only want to save the casts & deletions # delete a filter to not use it! MessageTypesAllowed = [1, 2] # who are you tracking? FidsAllowed = [10626] Plugins Handler API At some point, you'll want to make your own plug-ins. To get started, you should look at handlers/handlers.go! A plugin exports a Handler struct defining its own function to handle the message; here's an excerpt from the struct: type Handler struct { Name string // Used to make a connection to the DB. Go to handlers/handlers.go to see a method to pass down variables to the functions. InitHandler InitBehaviour // Those functions will handle incoming messages! It's up to you to define those you need. CastAddHandler HandlerBehaviour CastRemoveHandler HandlerBehaviour FrameActionHandler HandlerBehaviour ReactionAddHandler HandlerBehaviour ReactionRemoveHandler HandlerBehaviour LinkAddHandler HandlerBehaviour LinkRemoveHandler HandlerBehaviour VerificationAddHandler HandlerBehaviour VerificationRemoveHandler HandlerBehaviour } var PluginHandler = handler.Handler{ // .... amazing stuff here } // Then you compile & put it in compiled_handlers! It's up to you to define & verify the paramaters that will be used in config.toml. Compiling plugins for Docker You can edit the project's Dockerfile to add your plugin build command! FROM golang:1.22 WORKDIR /usr/src/app # pre-copy/cache go.mod for pre-downloading dependencies and only redownloading them in subsequent builds if they change COPY go.mod go.sum ./ RUN go mod download && go mod verify # 1. Make sure your plugin is included into the image COPY . . + RUN go build -buildmode=plugin -o ./compiled_handlers/[plugin name].so [your source code for the plugin] # 2. Example for the postgresql plugin RUN go build -buildmode=plugin -o ./compiled_handlers/postgresql.so postgresql/postgresql.go # Then, build the hub itself RUN go build -v -o /usr/local/bin/app ./relay CMD ["app"] ## Comments **tim**: @noctis, please tell us what your goals are with Farseer. Where do you see this project in 1-5 years? **noctisatrae.eth**: In 1-5y, I would love the project to have community-made plug-ins who bring a lot of new possibilities to the FC ecosystem. More support for DBs, protocol, etc... I have a great basis but without community support it's hard to support every DB. My goal is really to create like an "awesome-list" for my project, and try to expand the capabilities of farseer through open-source. Right now, it's so easy to deploy so anyone could have a cheap powerful hub with FC data available. If I succeed, this could be so beneficial for the network & the developers alike. **tim**: Where do you see the benefit over your solution vs the replicator on Warpcast? I guess your‘s is going to be more neutral in terms of the other tools you can connect to it? **noctisatrae.eth**: I guess it’s always better to be in control of your data source if you truly want to follow the philosophy of decentralization. I think that Farseer is not particularly attractive in an ecosystem that provides a lot of Infrastructure-As-A-Service stuff (i.e Neynar) but I definitely think there’s a place for Farseer for those who want to own their data. **tim**: What‘s your definition of owning your data? To me it seems like you equate it to the right to back your data up, for example. Any other rights you think belong in the bucket we call „owning your data?“ **noctisatrae.eth**: For me, owning your data is self-hosting: being able to access it without a third-party involved.