<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Berty Technologies</title>
    <description>The latest articles on DEV Community by Berty Technologies (@bertytechnologies).</description>
    <link>https://dev.to/bertytechnologies</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1146269%2F3ea9f561-5600-43ce-b29d-f0538a5e43da.jpg</url>
      <title>DEV Community: Berty Technologies</title>
      <link>https://dev.to/bertytechnologies</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bertytechnologies"/>
    <language>en</language>
    <item>
      <title>Wesh: Flight of a Byte</title>
      <dc:creator>Berty Technologies</dc:creator>
      <pubDate>Thu, 07 Sep 2023 15:17:19 +0000</pubDate>
      <link>https://dev.to/bertytechnologies/wesh-flight-of-a-byte-1bn9</link>
      <guid>https://dev.to/bertytechnologies/wesh-flight-of-a-byte-1bn9</guid>
      <description>&lt;p&gt;In the previous blog post, we made an example app where the Wesh user account of &lt;strong&gt;“client2”&lt;/strong&gt; sends a message &lt;strong&gt;“Hello”&lt;/strong&gt; to a Contact group which is received by the other user account of &lt;strong&gt;“client1”&lt;/strong&gt;. You can use the example to start building your Wesh app, but for development and debugging it helps to understand more about how it works. So this blog post will be a theory dive into some of the details of Wesh communication.&lt;/p&gt;

&lt;p&gt;When the Wesh app on the computer for &lt;strong&gt;client2&lt;/strong&gt; sends the bytes of a message, what is the &lt;strong&gt;“flight path”&lt;/strong&gt; of the bytes of &lt;strong&gt;“Hello”&lt;/strong&gt; as they travel to the computer of &lt;strong&gt;client1&lt;/strong&gt;? It's different from “traditional” networking where, for example, a computer sends the message in a UDP packet to the IP address of the other computer, as described in &lt;a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol"&gt;this Wikipedia article&lt;/a&gt;. Instead of a specific IP address, Wesh communication happens between &lt;a href="https://docs.libp2p.io/concepts/fundamentals/peers/"&gt;libp2p&lt;/a&gt; peers, where the client's PeerID is the value that we've seen in previous examples and is the same no matter how the client is connected to the network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Peer discovery&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The “glue” between a libp2p peers and a more traditional network address is &lt;a href="https://docs.libp2p.io/concepts/discovery-routing/overview/"&gt;peer discovery&lt;/a&gt;. There are a lot of details that we won't go into regarding types of discovery, peer authentication, etc. In this blog post, we just describe the minimal steps for how &lt;strong&gt;client1&lt;/strong&gt; receives the message from &lt;strong&gt;client2&lt;/strong&gt;. When the libp2p service of client1 discovers the computer of** client2**, it opens a network connection &lt;a href="https://github.com/libp2p/go-libp2p-pubsub/blob/6d73cd4b56bf9d7fdd0c0caaed629a3d51027a75/comm.go#L115"&gt;(code)&lt;/a&gt; and reads from it using a traditional byte stream &lt;a href="https://github.com/libp2p/go-libp2p-pubsub/blob/6d73cd4b56bf9d7fdd0c0caaed629a3d51027a75/comm.go#L66"&gt;(code)&lt;/a&gt;. (We give links to code for curious readers, but this isn't a code tutorial and you can skip the code links.) We've mentioned the traditional networking code “under the hood” to remove some of the mystery. But that code doesn't immediately read the message from client2. Instead, there are some communication steps which allow Wesh to use libp2p to operate in a peer-to-peer environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Message log and “head”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To send a message in traditional networking, one user connects to the network address of the other user and transmits the message. Or the user connects to a central server and appends to the message log there, while the other user connects to the same central server and reads the message log. But this doesn't work in a peer-to-peer environment. Instead, the goal is for each group member to have a copy of the message log, where there is a “head” (the latest message) which refers to all the previous messages in a chain. To send a message to the group, a member adds to the local copy of the message log and updates the “head”. This will be synchronized with the other members.&lt;/p&gt;

&lt;p&gt;Without a central server, each group member may add to the message log and receive updates from others in a different order. But the synchronization algorithm ensures “eventual consistency”: after exchanging enough messages, eventually all the users will have the same message log in the same order. At that point they will all have the same “head” message, which refers to all the previous messages in a chain. Wesh currently uses OrbitDB for this, and you can read the details in &lt;a href="https://github.com/orbitdb/field-manual/blob/main/03_The_Architecture_of_OrbitDB/02_ipfs-log.md"&gt;their manual&lt;/a&gt;. (In the future, Wesh may use a simpler library but it will still have the same concept of a synchronized message log with a head.)&lt;/p&gt;

&lt;p&gt;As mentioned, &lt;strong&gt;client2&lt;/strong&gt; doesn't send the message “Hello” directly to the other group members. Instead, it puts the message in its own message log and updates the head. The other members learn about the new head which means there is a new message to fetch.&lt;/p&gt;

&lt;p&gt;libp2p pubsub&lt;/p&gt;

&lt;p&gt;So now the question is, how does &lt;strong&gt;client1&lt;/strong&gt; learn that **client2 **says there is a new message log head? This uses libp2p pubsub where peers can subscribe to a topic and publish a pubsub message to that topic, or receive pubsub messages. (We say “pubsub message” to not confuse with the ordinary messages in the log which we'll discuss below.)&lt;/p&gt;

&lt;p&gt;libp2p pubsub is a powerful tool with algorithms which allow it to scale to many peers and to make sure they all get the pubsub message. You can read more in &lt;a href="https://docs.libp2p.io/concepts/pubsub/overview/"&gt;its documentation&lt;/a&gt;, but for this blog post we only need to say that the Wesh group has a libp2p topic name like   &lt;strong&gt;/orbitdb/bafyreihpdptqwgpuwu4ob6nusxebmdx6fm6mq5pma5hva6eu5u74pflo7e/2ac4e88c5272f900c76fd36989f9780e5b2c95d75d38fe5bcef0345b34bc4806_wesh_group_messages.&lt;/strong&gt; &lt;br&gt;
&lt;strong&gt;Client2&lt;/strong&gt; publishes a pubsub message to this topic that contains the message log head. The libp2p on &lt;strong&gt;client1&lt;/strong&gt; receives this pubsub message and sends it &lt;a href="https://github.com/libp2p/go-libp2p-pubsub/blob/6d73cd4b56bf9d7fdd0c0caaed629a3d51027a75/pubsub.go#L978"&gt;(code)&lt;/a&gt; internally to all processes which are subscribed to the topic. The Wesh application of &lt;strong&gt;client1&lt;/strong&gt; has used &lt;strong&gt;ActivateGroup&lt;/strong&gt; and is therefore subscribed to this topic and receives the pubsub message &lt;a href="https://github.com/berty/go-orbit-db/blob/368618e06b3be3bd17952d167d0e2f4fa03960ff/pubsub/pubsubraw/pubsub.go#L76"&gt;(code)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IPFS to fetch the message&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;libp2p pubsub doesn't care about the meaning of a pubsub message. It only makes sure that all subscribers get it. Remember that the next step is to synchronize the message log, which is handled by the local message store of &lt;strong&gt;client1&lt;/strong&gt;. After checking that it's not a repeat, the pubsub message is forwarded &lt;a href="https://github.com/berty/go-orbit-db/blob/368618e06b3be3bd17952d167d0e2f4fa03960ff/pubsub/pubsubraw/pubsub.go#L96"&gt;(code)&lt;/a&gt; as an EventPubSubMessage to the message store which receives it &lt;a href="https://github.com/berty/go-orbit-db/blob/368618e06b3be3bd17952d167d0e2f4fa03960ff/stores/basestore/base_store.go#L1133"&gt;(code)&lt;/a&gt;. This confirms that the type of pubsub message is to update the message log head, and it checks to make sure the head was not already processed. (If &lt;strong&gt;client1&lt;/strong&gt; has already received the same message log head, maybe from another peer, then it doesn't need to do more processing. This may seem trivial, but it's important because it's efficient to exchange these small “head” messages frequently between peers.)&lt;/p&gt;

&lt;p&gt;The message store receives &lt;a href="https://github.com/berty/go-orbit-db/blob/368618e06b3be3bd17952d167d0e2f4fa03960ff/baseorbitdb/orbitdb.go#L828"&gt;(code)&lt;/a&gt; the event for a new head which contains the &lt;strong&gt;CID&lt;/strong&gt; of the message. The message (which may be large) is fetched with IPFS, not with libp2p pubsub (which is better for small messages). If you don't know what a &lt;strong&gt;CID&lt;/strong&gt; is and how IPFS uses it to fetch content, then you can &lt;a href="https://docs.ipfs.tech/concepts/content-addressing/"&gt;read all about it&lt;/a&gt;. Notice that using a &lt;strong&gt;CID&lt;/strong&gt; to fetch the message (code) like “Hello” is a separate process from synchronizing heads. Maybe IPFS has already fetched the same CID, or maybe it can be fetched from another group member that is not client2. Wesh takes advantage of the efficient IPFS algorithms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decrypting and finishing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We're almost done! When the “Hello” message is fetched, it's placed in the local copy of the message log in the correct order. (Messages in the device's storage remain encrypted.) This internally sends the &lt;strong&gt;EventReplicated&lt;/strong&gt; event which is received &lt;a href="https://github.com/berty/weshnet/blob/aa44f7d64dcbc54c643cfddfaac8aa0a4d80f6a0/store_message.go#L452"&gt;(code)&lt;/a&gt; by the Wesh message monitor. We started at the libp2p “level” which doesn't care about the meaning of pubsub messages, up through the message log level which only cares about the correct order of messages. Now at the “top” level, Wesh must use &lt;strong&gt;client1's&lt;/strong&gt; cryptographic keys to decrypt &lt;a href="https://github.com/berty/weshnet/blob/aa44f7d64dcbc54c643cfddfaac8aa0a4d80f6a0/store_message.go#L139"&gt;(code)&lt;/a&gt; the message.&lt;/p&gt;

&lt;p&gt;The decrypted message is sent internally &lt;a href="https://github.com/berty/weshnet/blob/aa44f7d64dcbc54c643cfddfaac8aa0a4d80f6a0/store_message.go#L195"&gt;(code)&lt;/a&gt; to all monitoring processes, including the GroupMessageList service &lt;a href="https://github.com/berty/weshnet/blob/aa44f7d64dcbc54c643cfddfaac8aa0a4d80f6a0/api_event.go#L191"&gt;(code)&lt;/a&gt;. &lt;strong&gt;The client1&lt;/strong&gt; application has called &lt;strong&gt;GroupMessageList&lt;/strong&gt;, so the “Hello” message is sent &lt;a href="https://github.com/berty/weshnet/blob/aa44f7d64dcbc54c643cfddfaac8aa0a4d80f6a0/api_event.go#L199"&gt;(code)&lt;/a&gt; to the application which prints the message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flight of a Byte&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In summary, the flight of a message from &lt;strong&gt;client2&lt;/strong&gt; to &lt;strong&gt;client1&lt;/strong&gt; starts when the &lt;strong&gt;client2&lt;/strong&gt; peer is discovered, subscribes to the libp2p pubsub topic for the group messages and publishes its message log head. &lt;strong&gt;client1&lt;/strong&gt; doesn't have this head yet, so it uses the &lt;strong&gt;CID&lt;/strong&gt; to fetch the message using IPFS. When the message arrives, it is added to &lt;strong&gt;client1's&lt;/strong&gt; copy of the message log in the correct order. Wesh sends this new message to processes using the &lt;strong&gt;GroupMessageList&lt;/strong&gt; service, such as the sample application which receives it and prints “Hello”. Easy, right? Each of these steps is needed to make sure communication can still happen even if a peer disconnects or reconnects at a different network address.&lt;/p&gt;

&lt;p&gt;Now that you know what to expect when your Wesh application communicates, we'll return to some more examples in future blog posts.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>opensource</category>
      <category>p2p</category>
      <category>protocol</category>
    </item>
    <item>
      <title>Wesh App: Share Contact and Send Message</title>
      <dc:creator>Berty Technologies</dc:creator>
      <pubDate>Tue, 05 Sep 2023 15:26:34 +0000</pubDate>
      <link>https://dev.to/bertytechnologies/wesh-app-share-contact-and-send-message-1ecf</link>
      <guid>https://dev.to/bertytechnologies/wesh-app-share-contact-and-send-message-1ecf</guid>
      <description>&lt;p&gt;We continue to use the Wesh API to build more capable apps. In the &lt;a href="https://wesh.network/posts/wesh-app-with-persistent-storage"&gt;previous blog post&lt;/a&gt;, we made an example app which creates an account using persistent on-disk storage, and we discussed the types of information in Wesh. This includes a Contact group where two user accounts can communicate. In this blog post we will make an example app to share contact and send a message in the Contact group. (This is a longer blog post because we’re building a running app.)&lt;/p&gt;

&lt;p&gt;As before, we write an app similar to the &lt;a href="https://go.dev/doc/tutorial/getting-started"&gt;Go tutorial&lt;/a&gt;. In a terminal enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd
mkdir contact
cd contact
go mod init example/contact
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The main function&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your text editor, create a file &lt;strong&gt;&lt;em&gt;contact.go&lt;/em&gt;&lt;/strong&gt; in which to write your code. Paste the following code into your contact.go file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "context"
    "fmt"
    "io"
    "os"
    "time"

    "berty.tech/weshnet"
    "berty.tech/weshnet/pkg/protocoltypes"
    "github.com/mr-tron/base58"
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(&lt;a href="https://wesh.network/posts/wesh-hello-world-app"&gt;See the first example app blog post&lt;/a&gt; for explanation.) To continue the example, paste the following main function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func main() {

    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()

    client1, err := weshnet.NewPersistentServiceClient("data1")
    if err != nil {
        panic(err)
    }
    defer client1.Close()

    // client1 shares contact with client2.
    binaryContact, err := client1.ShareContact(ctx,
        &amp;amp;protocoltypes.ShareContact_Request{})
    if err != nil {
        panic(err)
    }
    fmt.Println(base58.Encode(binaryContact.EncodedContact))

    // client1 receives the contact request from client2.
    request, err := receiveContactRequest(ctx, client1)
    if err != nil {
        panic(err)
    }
    if request == nil {
        fmt.Println("Error: Did not receive the contact request")
        return
    }

    // client1 accepts the contact request from client2.
    _, err = client1.ContactRequestAccept(ctx,
        &amp;amp;protocoltypes.ContactRequestAccept_Request{
            ContactPK: request.ContactPK,
        })
    if err != nil {
        panic(err)
    }

    // Activate the contact group.
    groupInfo, err := client1.GroupInfo(ctx, &amp;amp;protocoltypes.GroupInfo_Request{
        ContactPK: request.ContactPK,
    })
    if err != nil {
        panic(err)
    }
    _, err = client1.ActivateGroup(ctx, &amp;amp;protocoltypes.ActivateGroup_Request{
        GroupPK: groupInfo.Group.PublicKey,
    })
    if err != nil {
        panic(err)
    }

    // Receive a message from the group.
    message, err := receiveMessage(ctx, client1, groupInfo)
    if err != nil {
        panic(err)
    }
    if message == nil {
        fmt.Print("End of stream without receiving message")
        return
    }

    fmt.Println("client2:", string(message.Message))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses some helper functions which we will define below. As in the previous example, we call &lt;strong&gt;NewPersistentServiceClient("data1")&lt;/strong&gt; to create a client with persistent storage on-disk. We name the folder “data1” because this is client1. It will communicate with client2 which we create below.&lt;/p&gt;

&lt;p&gt;Next we call the Wesh API function &lt;strong&gt;ShareContact&lt;/strong&gt; which is &lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.ShareContact"&gt;documented here&lt;/a&gt;. It returns an encoded byte array with the information that client2 needs to make a contact request. We use &lt;strong&gt;base58.Encode&lt;/strong&gt; to make it a shareable string and print it to the console. (The Wesh API leaves it up to the application developer to decide how to encode the byte array. You may use base58, or make a QR code, or a URI, etc.) This string is used by client2, as we will see.&lt;/p&gt;

&lt;p&gt;Let’s imagine that client2 has sent the contact request, so we call &lt;strong&gt;receiveContactRequest&lt;/strong&gt; which we will define below. It returns request which has the account public key of client2, so we call &lt;strong&gt;ContactRequestAccept&lt;/strong&gt; &lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.ContactRequestAccept"&gt;(docs)&lt;/a&gt; to accept the contact request and create the Contact group.&lt;/p&gt;

&lt;p&gt;Now we need to activate this group. We use the same account public key of client2 to identify the Contact group and call GroupInfo &lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.GroupInfo"&gt;(docs) &lt;/a&gt;to get the group’s public key, and then call &lt;strong&gt;ActivateGroup&lt;/strong&gt; &lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.ActivateGroup"&gt;(docs)&lt;/a&gt; to activate it.&lt;/p&gt;

&lt;p&gt;Finally, let’s imagine that client2 has sent a message to the group, so we call &lt;strong&gt;receiveMessage&lt;/strong&gt; which we will define below. This returns the message (or nil if end of stream) which we print to the console.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Helper functions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s it for main! Now we need to define the helper functions &lt;strong&gt;receiveContactRequest&lt;/strong&gt; and &lt;strong&gt;receiveMessage&lt;/strong&gt;. These both follow the pattern of subscribing to an event stream and waiting for the desired event type. Paste the following function to the file &lt;strong&gt;contact.go&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func receiveContactRequest(ctx context.Context, client weshnet.ServiceClient) (*protocoltypes.AccountContactRequestIncomingReceived, error) {
    // Get the client's AccountGroupPK from the configuration.
    config, err := client.ServiceGetConfiguration(ctx, &amp;amp;protocoltypes.ServiceGetConfiguration_Request{})
    if err != nil {
        return nil, err
    }

    // Subscribe to metadata events. ("sub" means "subscription".)
    subCtx, subCancel := context.WithCancel(ctx)
    defer subCancel()
    subMetadata, err := client.GroupMetadataList(subCtx, &amp;amp;protocoltypes.GroupMetadataList_Request{
            GroupPK: config.AccountGroupPK,
        })
    if err != nil {
        return nil, err
    }

    for {
        metadata, err := subMetadata.Recv()
        if err == io.EOF || subMetadata.Context().Err() != nil {
            // Not received.
            return nil, nil
        }
        if err != nil {
            return nil, err
        }

        if metadata == nil || metadata.Metadata.EventType !=
                protocoltypes.EventTypeAccountContactRequestIncomingReceived {
            continue
        }

        request := &amp;amp;protocoltypes.AccountContactRequestIncomingReceived{}
        if err = request.Unmarshal(metadata.Event); err != nil {
            return nil, err
        }

        return request, nil
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function takes the client1 which we created in &lt;strong&gt;main&lt;/strong&gt; and calls &lt;strong&gt;ServiceGetConfiguration&lt;/strong&gt; &lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.ServiceGetConfiguration"&gt;(docs)&lt;/a&gt;. Instead of getting the configuration’s peer ID as in previous examples, we get the public key of client1’s Account group. This public key is also in the shared contact, and is used by client2 to send a contact request to client1. To receive it, we call *&lt;em&gt;GroupMetadataList *&lt;/em&gt;&lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.GroupMetadataList"&gt;(docs)&lt;/a&gt; with the Account group public key.&lt;/p&gt;

&lt;p&gt;Most API functions return a data structure, but a few like &lt;strong&gt;GroupMetadataList&lt;/strong&gt; return a subscription stream like &lt;strong&gt;subMetadata&lt;/strong&gt;. We use a &lt;strong&gt;for&lt;/strong&gt; loop and call &lt;strong&gt;subMetadata.Recv()&lt;/strong&gt; which blocks until it receives an event (or end of stream). As you build more complex apps, an event loop like this may handle more event types and operations. For now, we just check that the event type is the one we’re waiting for, &lt;strong&gt;EventTypeAccountContactRequestIncomingReceived.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we can use &lt;strong&gt;Unmarshal&lt;/strong&gt; to convert the &lt;strong&gt;metadata&lt;/strong&gt; event to the specific &lt;strong&gt;AccountContactRequestIncomingReceived&lt;/strong&gt; event. (&lt;strong&gt;Unmarshal&lt;/strong&gt; is part of the Protobuf interface. For more details, &lt;a href="https://pkg.go.dev/github.com/golang/protobuf/proto#Unmarshal"&gt;see the docs)&lt;/a&gt;. This is the contact &lt;strong&gt;request&lt;/strong&gt; that we return from the function.&lt;/p&gt;

&lt;p&gt;Now we need to define &lt;strong&gt;receiveMessage&lt;/strong&gt; which waits for the message. Paste the following function to the file &lt;strong&gt;contact.go&lt;/strong&gt;. (This one is shorter!)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func receiveMessage(ctx context.Context, client weshnet.ServiceClient, groupInfo *protocoltypes.GroupInfo_Reply) (*protocoltypes.GroupMessageEvent, error) {
    // Subscribe to message events.
    subCtx, subCancel := context.WithCancel(ctx)
    defer subCancel()
    subMessages, err := client.GroupMessageList(subCtx, &amp;amp;protocoltypes.GroupMessageList_Request{
        GroupPK: groupInfo.Group.PublicKey,
    })
    if err != nil {
        panic(err)
    }

    // client waits to receive the message.
    for {
        message, err := subMessages.Recv()
        if err == io.EOF {
            // Not received.
            return nil, nil
        }
        if err != nil {
            return nil, err
        }

        return message, nil
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to the previous function, this function takes the client1 which we created in &lt;strong&gt;main&lt;/strong&gt;. It also takes the &lt;strong&gt;groupInfo&lt;/strong&gt; object of the Contact group. (The &lt;strong&gt;main&lt;/strong&gt; function already used this to activate the group.)&lt;/p&gt;

&lt;p&gt;As in the previous function, we want to subscribe to events. In the &lt;a href="https://wesh.network/posts/wesh-app-with-persistent-storage"&gt;previous blog post&lt;/a&gt;, we briefly discussed the difference between the Metadata log and the Message log. A contact request is an event in the Metadata log, so &lt;strong&gt;receiveContactRequest&lt;/strong&gt; called &lt;strong&gt;GroupMetadataList&lt;/strong&gt;. But now we want to receive a “normal” message when it is added to the Message log.&lt;/p&gt;

&lt;p&gt;We call the API method &lt;strong&gt;GroupMessageList&lt;/strong&gt; &lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.GroupMessageList"&gt;(docs)&lt;/a&gt; which returns the subscription stream &lt;strong&gt;subMessages&lt;/strong&gt;. We use a for loop and call &lt;strong&gt;subMetadata.Recv()&lt;/strong&gt; which blocks until it receives an event (or end of stream). Finally, the function returns &lt;strong&gt;message&lt;/strong&gt; which is a &lt;strong&gt;GroupMessageEvent&lt;/strong&gt; so that the main function can print the message from client2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client 2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Wait a moment (you may be thinking). We don’t have the code where client2 sends the message. We will add it to this same file and you will run the app in two terminals. Remember that the code for client1 prints the contact string to the terminal. When we run the app for client2, we’ll add this string as a command-line parameter. At the very beginning of the main function, insert this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if len(os.Args) == 2 {&lt;br&gt;
        doClient2(os.Args[1])&lt;br&gt;
        return&lt;br&gt;
    }&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Now we can define the function **doClient2** which is called if we run using the contact string. Paste the following function to the file **contact.go** and save it.

func doClient2(encodedContact string) {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()

    client2, err := weshnet.NewPersistentServiceClient("data2")
    if err != nil {
        panic(err)
    }
    defer client2.Close()

    contactBinary, err := base58.Decode(encodedContact)
    if err != nil {
        panic(err)
    }
    contact, err := client2.DecodeContact(ctx,
        &amp;amp;protocoltypes.DecodeContact_Request{
            EncodedContact: contactBinary,
        })
    if err != nil {
        panic(err)
    }

    // Send the contact request.
    _, err = client2.ContactRequestSend(ctx,
        &amp;amp;protocoltypes.ContactRequestSend_Request{
            Contact: contact.Contact,
        })
    if err != nil {
        panic(err)
    }

    // Activate the contact group.
    groupInfo, err := client2.GroupInfo(ctx, &amp;amp;protocoltypes.GroupInfo_Request{
        ContactPK: contact.Contact.PK,
    })
    if err != nil {
        panic(err)
    }
    _, err = client2.ActivateGroup(ctx, &amp;amp;protocoltypes.ActivateGroup_Request{
        GroupPK: groupInfo.Group.PublicKey,
    })
    if err != nil {
        panic(err)
    }

    // Send a message to the contact group.
    _, err = client2.AppMessageSend(ctx, &amp;amp;protocoltypes.AppMessageSend_Request{
        GroupPK: groupInfo.Group.PublicKey,
        Payload: []byte("Hello"),
    })
    if err != nil {
        panic(err)
    }

    fmt.Println("Sending message...")
    time.Sleep(time.Second * 5)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function takes the &lt;strong&gt;encodedContact&lt;/strong&gt; from the command line. It runs as a separate process, so we need to use &lt;strong&gt;NewPersistentServiceClient&lt;/strong&gt; to create a separate client2 with persistent data stored in a separate folder, “data2”.&lt;/p&gt;

&lt;p&gt;Next we use &lt;strong&gt;base58.Decode&lt;/strong&gt; to recover the encoded byte array with client1’s contact info, and use &lt;strong&gt;DecodeContact&lt;/strong&gt; &lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.DecodeContact"&gt;(docs)&lt;/a&gt; to extract the &lt;strong&gt;contact info&lt;/strong&gt;. Now client2 can call &lt;strong&gt;ContactRequestSend&lt;/strong&gt; &lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.ContactRequestSend"&gt;(docs)&lt;/a&gt; to send this to client1 as a contact request. You may be thinking, “client1 just sent this info to client2, so why does client2 need to send it back?” This is part of the secure handshake. client2 needs to make sure that the shared contact really came from client1, and needs to decide if creating a contact is actually desired.&lt;/p&gt;

&lt;p&gt;Similar to the code above, client2 needs to activate the Contact group using &lt;strong&gt;GroupInfo **and **ActivateGroup&lt;/strong&gt;. (In this case, client2 has client1’s account public key from the shared contact in &lt;strong&gt;contact.Contact.PK.&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;We’re almost done! Client2 calls &lt;strong&gt;AppMessageSend&lt;/strong&gt; &lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.AppMessageSend"&gt;(docs)&lt;/a&gt; to use the Contact group public key to send a “Hello” message to the Contact group. (For generality, a message is any byte array. In this case we simply store the message string in it.) For efficiency, the &lt;strong&gt;AppMessageSend&lt;/strong&gt; function queues the message to be sent and returns immediately. If we exit the application too soon, then the Wesh services won’t have time to actually send the message. Therefore, we sleep this function for 5 seconds so that the service threads can complete.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run the app&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s all the code! It’s time to run the app. In a terminal enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go mod tidy
go run .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(You only need to do &lt;strong&gt;go mod tidy&lt;/strong&gt; the first time.) It should print the contact string from client1, something like &lt;strong&gt;2KqzJQpZ2Y7EDaep6CnceT6ozqy1Ss6qJV8tsN59QSBejfa4TiYjMr8Z9PjHr1D2bYa4EozWudwaWMwB5jXqb5gRLj2bX&lt;/strong&gt;. Copy this to the clipboard.&lt;/p&gt;

&lt;p&gt;Leave this app running. Now, in a separate terminal we run as client2. cd to the same directory and enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go run . &amp;lt;contact-string&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;strong&gt;&lt;/strong&gt; is the contact string from client1. It should print &lt;strong&gt;Sending message&lt;/strong&gt;.... Now look at the terminal for client1. It should print &lt;strong&gt;client2: Hello.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You have established Wesh communication! You can use this example app as a basis for more sophisticated Wesh apps. Overall, this simply creates a Contact group and calls &lt;strong&gt;AppMessageSend&lt;/strong&gt;. But you may understand that Wesh communicates differently than using a traditional network connection. How does the message actually get from client2 to client1? In the next blog post, we’ll do a theory dive into how Wesh’s asynchronous communication works.&lt;/p&gt;

</description>
      <category>protocol</category>
      <category>web3</category>
      <category>opensource</category>
      <category>p2p</category>
    </item>
    <item>
      <title>Wesh App with Persistent Storage</title>
      <dc:creator>Berty Technologies</dc:creator>
      <pubDate>Fri, 01 Sep 2023 13:03:18 +0000</pubDate>
      <link>https://dev.to/bertytechnologies/wesh-app-with-persistent-storage-epc</link>
      <guid>https://dev.to/bertytechnologies/wesh-app-with-persistent-storage-epc</guid>
      <description>&lt;p&gt;In the previous blog post, we made an example “Hello world” app using the Wesh API. But it used in-memory storage for the keys and messages, which are lost when the app closes. It's possible to export the data to a file before closing, and re-import it when the in-memory app stars again. But in this blog post we will make an example app to use a persistent storage on disk. We'll also use this to explain some details of what is in the key store and libp2p node.&lt;/p&gt;

&lt;p&gt;As before, we write an app similar to the &lt;a href="https://go.dev/doc/tutorial/getting-started"&gt;Go tutorial&lt;/a&gt;. In a terminal enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd
mkdir persistent
cd persistent
go mod init example/persistent

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As in the previous blog post, paste the following code into your persistent.go file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "context"
    "fmt"

    "berty.tech/weshnet"
    "berty.tech/weshnet/pkg/protocoltypes"
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(See the previous blog post for explanation.) To complete the example, paste the following main function and save the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func main() {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()

    path := "data"
        client, err := weshnet.NewPersistentServiceClient(path)
    if err != nil {
        panic(err)
    }
    defer client.Close()

    config, err := client.ServiceGetConfiguration(ctx,
            &amp;amp;protocoltypes.ServiceGetConfiguration_Request{})
    if err != nil {
        panic(err)
    }

    fmt.Println("Hello, world! My peer ID is", config.PeerID)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is similar to the previous example, except that we change &lt;strong&gt;NewInMemoryServiceClient() to NewPersistentServiceClient(path)&lt;/strong&gt; , where path is the directory for the persistent storage. When we run for the first time, Wesh will create the directory and the storage files for a new peer identity. To run, in a terminal enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go mod tidy
go run . 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(You only need to do go mod tidy the first time.) It should print something like &lt;strong&gt;“Hello, world! My peer ID is 12D3KooWJeVb4rbDisCgmUQQxtzNRikgcQxXzSodoy2AyNCdTEWr”&lt;/strong&gt; . Now, enter the run command again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go run .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, &lt;strong&gt;NewPersistentServiceClient(path)&lt;/strong&gt; uses the storage files that we created the first time. It should print exactly the same peer ID, meaning that the same identity is persistent on disk. To see the storage files, enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;000000.vlog 000002.sst  MANIFEST    config      datastore_spec  repo.lock
000001.sst  KEYREGISTRY blocks      datastore   keystore          version

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Much of the content of these files is encrypted. They are only meant to be accessed through the Wesh API. We aren't going to look at all of these files or describe their format, but seeing them gives us a chance to discuss the basic types of information in Wesh.&lt;/p&gt;

&lt;p&gt;The most important to discuss are the three types of information associated with your identity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#peer-ids"&gt;The libp2p host Peer ID&lt;/a&gt; is what the example prints. It identifies your computer as a node in libp2p communication.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://berty.tech/docs/protocol/#account-creation"&gt;The Account key pair&lt;/a&gt; holds the primary identity that you use to connect to other Wesh users and to join a group.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://berty.tech/docs/protocol/#linking-devices"&gt;A Device key pair&lt;/a&gt; is created on each computer or mobile device where you use Wesh, and is connected cryptographically to your Account key pair.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Wesh, communication is based on the “group” where messages are secure between group members. For each new group, the Wesh service generates a Metadata log (with info like members joining), a Message log (which we'll explore in a future blog post), and cryptographic secrets (your own secrets and secrets received from other group members). There are three types of groups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your &lt;a href="https://berty.tech/docs/protocol/#account-group"&gt;Account group&lt;/a&gt; stores all the secrets and metadata of your account and allows the devices linked to it to sync with each other, as explained above. So, when the example first calls &lt;strong&gt;&lt;code&gt;NewPersistentServiceClient&lt;/code&gt;&lt;/strong&gt;, Wesh creates one Account key pair, one Device key pair for your computer, and the Account group for it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When &lt;a href="https://berty.tech/docs/protocol/#adding-contacts"&gt;you add another Wesh user as a contact&lt;/a&gt;, you are both in a &lt;a href="https://berty.tech/docs/protocol/#contact-group"&gt;Contact group&lt;/a&gt; where just the two of you can communicate securely. No other users can join this group.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, you can create or join a &lt;a href="https://berty.tech/docs/protocol/#multi-member-group"&gt;Multi-member group&lt;/a&gt;. This is what people normally think of when they hear about Wesh, but it's useful to mention the other types of groups and their purpose.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Among other maintenance files, the persistent storage has a Network config file with info on how libp2p makes connections. And there is a block store which is part of the peer-to-peer network and stores information you have received or may be useful to other users that your device connects to.&lt;/p&gt;

&lt;p&gt;That's enough for now! For more details, see the links in the text above. Now that we see how to create an account, in the next blog post we'll look at how to use Wesh to add a contact and send a message.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>p2p</category>
      <category>protocol</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Wesh “Hello World” App</title>
      <dc:creator>Berty Technologies</dc:creator>
      <pubDate>Mon, 28 Aug 2023 15:56:10 +0000</pubDate>
      <link>https://dev.to/bertytechnologies/wesh-hello-world-app-45fo</link>
      <guid>https://dev.to/bertytechnologies/wesh-hello-world-app-45fo</guid>
      <description>&lt;p&gt;Now that you have been introduced to Wesh in the &lt;a href="https://wesh.network/posts/introducing-the-wesh-network-toolkit"&gt;previous blog post&lt;/a&gt;, it’s time to explore the code. We will write a “Hello World” app, similar to the &lt;a href="https://go.dev/doc/tutorial/getting-started"&gt;Go tutorial&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;Similar to the Go tutorial, in a terminal enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd
mkdir hello
cd hello
go mod init example/hello

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your text editor, create a file hello.go in which to write your code. Paste the following code into your hello.go file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "context"
    "fmt"

    "berty.tech/weshnet"
    "berty.tech/weshnet/pkg/protocoltypes"
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We import fmt as usual in Go code so that we can print a message. We import &lt;strong&gt;berty.tech/weshnet&lt;/strong&gt; 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 &lt;strong&gt;berty.tech/weshnet/pkg/protocoltypes&lt;/strong&gt;, and we import context because all of the gRPC calls use a Go &lt;strong&gt;context&lt;/strong&gt; object (explained below).&lt;/p&gt;

&lt;p&gt;To complete the example, paste the following main function and save the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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,
            &amp;amp;protocoltypes.ServiceGetConfiguration_Request{})
    if err != nil {
        panic(err)
    }

    fmt.Println("Hello, world! My peer ID is", config.PeerID)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First we use &lt;strong&gt;context.WithCancel&lt;/strong&gt; 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 &lt;a href="https://pkg.go.dev/context"&gt;its documentation&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;Next we call &lt;strong&gt;weshnet.NewInMemoryServiceClient&lt;/strong&gt; to initialize the Wesh service and create a gRPC &lt;strong&gt;client&lt;/strong&gt; 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.)&lt;/p&gt;

&lt;p&gt;Finally, we interact with the Wesh service by calling &lt;strong&gt;client.ServiceGetConfiguration&lt;/strong&gt; , passing the ctx that we created. This method gets the current configuration of the service and is &lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.ServiceGetConfiguration"&gt;documented here&lt;/a&gt;, 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 &lt;strong&gt;protocoltypes.ServiceGetConfiguration_Request&lt;/strong&gt;. (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 &lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ServiceGetConfiguration.Reply"&gt;ServiceGetConfiguration.Reply&lt;/a&gt;. So to finish, we print a happy message with the PeerID of the in-memory IPFS node.&lt;/p&gt;

&lt;p&gt;To see the result, in a terminal enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go mod tidy
go run .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(You only need to do &lt;strong&gt;go mod tidy&lt;/strong&gt; the first time.) It should print something like “&lt;strong&gt;Hello, world! My peer ID is 12D3KooWGVMm5mum6qMtwbReiD9Aa93WTuTT2hTHsYxQASTzYUfs&lt;/strong&gt;”.&lt;/p&gt;

&lt;p&gt;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 &lt;strong&gt;ServiceGetConfiguration_Request&lt;/strong&gt;. And the API calls like &lt;strong&gt;ServiceGetConfiguration&lt;/strong&gt; only need these Protobuf messages which are language-independent.&lt;/p&gt;

&lt;p&gt;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).&lt;/p&gt;

</description>
      <category>web3</category>
      <category>p2p</category>
      <category>protocol</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Introducing the Wesh Network Toolkit</title>
      <dc:creator>Berty Technologies</dc:creator>
      <pubDate>Fri, 25 Aug 2023 13:34:21 +0000</pubDate>
      <link>https://dev.to/bertytechnologies/introducing-the-wesh-network-toolkit-303b</link>
      <guid>https://dev.to/bertytechnologies/introducing-the-wesh-network-toolkit-303b</guid>
      <description>&lt;p&gt;&lt;strong&gt;Welcome to Wesh!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;If you have an Internet connection, then there are many tools to communicate with others. But if you’re off grid or the Internet is down, then those tools can’t help you. To solve this and other problems, in 2018 &lt;a href="https://berty.tech/about"&gt;Berty Technologies&lt;/a&gt; created a protocol to let you create an identity, join a group and exchange messages all without needing an Internet connection or a central service provider.&lt;/p&gt;

&lt;p&gt;Thanks to strong encryption, you control your own identity without needing permission. You can set up or participate in ad-hoc groups while preserving privacy. And data is encrypted as it moves between users through an untrusted environment, whether device-to-device or over the Internet when available.&lt;/p&gt;

&lt;p&gt;This protocol powers Berty Messenger which brings these features to mobile phone users. But the need for reliable, privacy-based off-grid communication goes beyond a messaging app. That’s why we’re introducing the open-source &lt;a href="https://wesh.network/"&gt;Wesh Network Toolkit&lt;/a&gt; so you can take advantage of the &lt;a href="https://berty.tech/docs/protocol"&gt;Wesh protocol&lt;/a&gt; in your own application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How will you use Wesh?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For maximum flexibility, your application interfaces to Wesh based on &lt;a href="https://grpc.io/"&gt;gRPC&lt;/a&gt;, a well-supported framework which sends and receives Google Protobuf messages.&lt;br&gt;
Even though the &lt;a href="https://github.com/berty/weshnet"&gt;core Wesh code&lt;/a&gt; is written in Go, gRPC messages are language-independent. So, Wesh works with your existing application written in Go, Python, Java, C++ or &lt;a href="https://grpc.io/docs/languages/"&gt;other supported languages&lt;/a&gt;.&lt;br&gt;
gRPC works with the Buf schema registry where we publish the &lt;a href="https://buf.build/berty/weshnet"&gt;Wesh API&lt;/a&gt;. For example, this documents the request and reply to r&lt;a href="https://buf.build/berty/weshnet/docs/main:weshnet.protocol.v1#weshnet.protocol.v1.ProtocolService.GroupInfo"&gt;etrieve information about a group.&lt;/a&gt;&lt;br&gt;
gRPC allows different calling interfaces. The messages can be sent as if Wesh is a library linked directly to your application. Or if your application environment requires it, then API messages can be sent over TCP to a Wesh toolkit running on a local or remote server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The “Wesh” name&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You may be wondering what “Wesh” means. It’s a variant of “mesh” to highlight its asynchronous mesh communication which can use any device to securely store a message for a disconnected group member and deliver it when they connect again. (”Wesh” is also slang for “hi” in the French hip hop scene.)&lt;br&gt;
What’s next?&lt;br&gt;
This was a short and sweet introduction to Wesh. In future posts, we’ll dive into how Wesh is organized by users and groups, how to get started with the code, some example applications and more. Stay tuned!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://wesh.network"&gt;https://wesh.network&lt;/a&gt; The main Wesh Network Toolkit web page&lt;br&gt;
&lt;a href="https://github.com/berty/weshnet"&gt;https://github.com/berty/weshnet&lt;/a&gt; The Wesh GitHub repo for code and issues&lt;br&gt;
&lt;a href="https://berty.tech/docs/protocol"&gt;https://berty.tech/docs/protocol&lt;/a&gt; The Wesh protocol white paper&lt;br&gt;
&lt;a href="https://buf.build/berty/weshnet"&gt;https://buf.build/berty/weshnet&lt;/a&gt; The Wesh API at the Buf schema registry&lt;br&gt;
&lt;a href="https://berty.tech/about"&gt;https://berty.tech/about&lt;/a&gt; About Berty Technologies, the NGO working with the open-source community to make all this real&lt;/p&gt;

</description>
      <category>web3</category>
      <category>protocol</category>
      <category>opensource</category>
      <category>p2p</category>
    </item>
  </channel>
</rss>
