2 - Wesh “Hello World” App
Now that you have been introduced to Wesh in the previous blog post, it’s time to explore the code. We will write a “Hello World” app, similar to the Go tutorial which you can read to set up Go on your computer and for other details. (This has been tested with Go 1.19 on macOS and Ubuntu.) This example app will connect to the Wesh service and call a function. When finished, you will be confident that you can use Wesh on your platform.
Similar to the Go tutorial, in a terminal enter:
cd mkdir hello cd hello
go mod init example/hello
In your text editor, create a file hello.go in which to write your code. Paste the following code into your hello.go file.
package main
import (
"context"
"fmt"
"berty.tech/weshnet"
"berty.tech/weshnet/pkg/protocoltypes"
)
We import fmt
as usual in Go code so that we can print a message. We import berty.tech/weshnet
so that we can call the Go function to initialize the Wesh service (explained below). Finally, your app interacts with the Wesh service through gRPC which uses Protobuf messages. Therefore, we import the Wesh API Protobuf types with berty.tech/weshnet/pkg/protocoltypes
, and we import context
because all of the gRPC calls use a Go context object (explained below).
To complete the example, paste the following main function and save the file.
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := weshnet.NewInMemoryServiceClient()
if err != nil {
panic(err)
}
defer client.Close()
config, err := client.ServiceGetConfiguration(ctx,
&protocoltypes.ServiceGetConfiguration_Request{})
if err != nil {
panic(err)
}
fmt.Println("Hello, world! My peer ID is", config.PeerID)
}
First we use context.WithCancel
to create a ctx
object which is used in the gRPC calls, and a cancel
function to call when the app exits. The Context type is part of the Go standard library and you can read its documentation for more details.
Next we call weshnet.NewInMemoryServiceClient
to initialize the Wesh service and create a gRPC client
that we use to interact with it. Wesh has many init functions for different configurations. A Wesh service can run in memory with a direct connection, or as a separate process with communication through an open socket. We will discuss these options in future blog posts. In this example, we initialize a Wesh service which runs in application memory with a direct connection, and creates a new in-memory user account and data store. If your app doesn’t export the data, then it is lost when the app exits. (It’s also possible to create a persistent data store, which we will explore later.)
Finally, we interact with the Wesh service by calling client.ServiceGetConfiguration
, passing the ctx
that we created. This method gets the current configuration of the service and is documented here, along with all the other API calls. Each API call takes a Protobuf request message. In this case there are no parameters, so we create an empty protocoltypes.ServiceGetConfiguration_Request
. (We will see more complex examples later.) And each API call returns a Protobuf reply message, or sometimes a stream object. In this case it is a ServiceGetConfiguration.Reply. So to finish, we print a happy message with the PeerID
of the in-memory IPFS node.
To see the result, in a terminal enter:
go mod tidy
go run .
(You only need to do go mod tidy
the first time.) It should print something like “Hello, world! My peer ID is 12D3KooWGVMm5mum6qMtwbReiD9Aa93WTuTT2hTHsYxQASTzYUfs”.
In this example, you can now see how the Wesh API can be used with other programming languages. The gRPC support provides helper functions for each language to create the Protobuf messages like ServiceGetConfiguration_Request
. And the API calls like ServiceGetConfiguration
only need these Protobuf messages which are language-independent.
Congratulations on your first Wesh app! This one kept all the data in memory. In the next blog post, we’ll see how to create a persistent key store and IPFS node (and talk more about what these are).
Posted by Jeff on 23/03/2023