# How to build application on top of the mixnet: the example of Pastenym

> Disclaimer: in this article, we assume the reader to have some technical background, as it is written for developers. We chose to not detail every term *on purpose*.

The Nym mixnet offers very interesting privacy guarantees, as we detailed in some of our previous articles. In this article, we will explain how to build your application to use the mixnet provided by [Nym Technologies](https://nymtech.net/), to leverage the privacy guarantees it can bring. To illustrate the process, we will take our anonymous pastebin service Pastenym ([v2.0.2](https://github.com/notrustverify/pastenym/blob/v2.0.2/)), as an example. Do not hesitate to check the [code on the repository of the application](https://github.com/notrustverify/pastenym)!

> At the time of writing this article, our instance of Pastenym ([https://pastenym.ch](https://pastenym.ch)) is down due to some issue with some components from Nym. In the meantime, we advise you to use another instance, such as [https://pastenym.mynixnode.com](https://pastenym.mynixnode.com/)

If you missed what Pastenym was, make sure to read [this article](https://blog.notrustverify.ch/pastenym-a-privacy-friendly-sharing-service-ac3d5f337bde) from our blog! If you are not familiar with the mixnet of Nym, we would advise [this introduction to mixnets](https://blog.nymtech.net/a-simple-introduction-to-mixnets-6783a103d20e) from their blog.

Naturally, if your application is made of different components (client-server application) or involves different actors (peer-to-peer application), these will need to communicate. We'll first review the traditional way of exchanging data between applications and then explain how to do it using the mixnet.

## **The traditional way of communicating**

The traditional way of exchanging data between components or applications is through a REST, GraphQL or custom API, or using a custom protocol, through (web)sockets. The exchanged messages are sent using HTTP requests from a component through the internet to another component, identified by an IP address and a port.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1697533666148/05f79efe-eea0-4888-9f4c-7b4cc77232e5.png align="center")

If we wanted to have Pastenym components communicate traditionally, we would have had our React frontend call REST API endpoints on our backend in Python, for which we would probably have used an API-oriented framework such as Flask or FastAPI.

## **How to send & receive messages through the mixnet?**

When your application communicates with the mixnet, it is not the application itself that is talking directly to the mixnet. To exchange messages on the mixnet, your component needs a **nym client**. The nym client is in charge of the encryption and decryption of messages, communicating with the other mixnet's components, managing the Single Use Reply Blocks (SURBs) and plenty of other things that you probably do not want to manage yourself in your application. You can learn more about nym clients [in the official documentation](https://nymtech.net/docs/clients/overview.html).

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1697533685715/43674843-ab15-4ab4-bb6c-bd77d1c87782.png align="center")

Nym clients identify each other using `clientID`s. A `clientID` is a string, composed of three parts, delimited by two points `'.'`. You can find more information on the addressing system [here](https://nymtech.net/docs/clients/addressing-system.html).

Nym clients can send each other messages, through the mixnet. They can exchange raw or text data, depending on your need and configuration. In Pastenym, we exchanged JSON payloads, containing everything we need to store and retrieve pastes!

We will now detail to use the two nym clients that we use in Pastenym: the websocket client & the Web Assembly client.

### **Websocket nym client**

This nym client is convenient because it runs on every platform and can be used independently of the language you chose for your application. However, it requires running a standalone executable with which your application will communicate through a websocket. For these reasons, this nym client is the default choice to run on the backend side. You can find [here](https://nymtech.net/docs/clients/websocket-client.html) the documentation of Nym on this client.

Here is a step-by-step guide of what to do to use the websocket nym client:

1. Download the websocket nym client from the releases from [Nym's Github repository](https://github.com/nymtech/nym/releases?q=binaries&expanded=true) or build it yourself (instructions [here](https://nymtech.net/docs/binaries/building-nym.html)).
    
2. Make sure that the `nym-client` is executable. You may need to adapt the following command if you want another user to be able to execute it
    
    ```bash
    chmod u+x nym-client
    ```
    
3. Initialize the websocket nym client as follows:
    
    ```bash
    ./nym-client init --id <name_of_your_choosing>
    ```
    
    where you replaced `<name_of_your_choosing>` by some name of your choosing. You will need to remember this name when you want to run the nym client. The name is associated with the `clientID`: if you use a different name, the `clientID` will be different. If you want to provide a service available through the Nym network (as we do with Pastenym backend), you may not want the `clientID` of your application to change.
    
4. Run the websocket nym client as follows:
    
    ```bash
    ./nym-client run --id <name_of_your_choosing>
    ```
    
    > You cannot run the nym-client for the `<name_of_your_choosing>`without having initialized it beforehand.
    
    If this command is executed successfully, you should see a line in the logs, displaying the `clientID` of this nym client, similar to:
    
    ```bash
    > The address of this client is: GCdwdkpnn94YjsDqkQjXQi7mMkYxrf87LDCkdi8Wsh4f.E4edYXjPN4DZi77q4n6JEUavVwdFhFFj2J2yEGpW15Tq@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN
    ```
    
    You may also have noticed the following line in the logs:
    
    ```bash
    > Running websocket on "127.0.0.1:1977"
    ```
    
    Indicating the address of the websocket your application should connect to, to exchange with the mixnet. Note that this websocket is only available on [localhost](http://localhost), so your application needs to be on the same host as the nym client. If you want to run your app on a different machine (or in a docker container), you can use our nym client Docker image [here](https://github.com/notrustverify/pastenym/tree/v2.0.2/nym-client).
    
5. In your application, you can now connect to the websocket at the address printed in the logs, using a websocket library available for the language of your app, as we did for Pastenym, in Python. Hereafter is an extract, you can find the whole code [here](https://github.com/notrustverify/pastenym/blob/v2.0.2/backend/serve.py#L55):
    
    ```python
    import websocket
    import json
    import rel
    ​
    class Serve:
        def __init__(self):
            websocket.enableTrace(False)
            self.ws = websocket.WebSocketApp(f"ws://127.0.0.1:1977",
                on_message=lambda ws, msg: self.on_message(ws, msg),
                on_error=lambda ws, msg: self.on_error(ws, msg),
                on_close=lambda ws: self.on_close(ws),
                on_open=lambda ws: self.on_open(ws),
                on_pong=lambda ws, msg: self.on_pong(ws, msg)
            )
            self.ws.run_forever(dispatcher=rel,
                ping_interval=30, ping_timeout=10)
    ​
            rel.signal(2, rel.abort)  # Keyboard Interrupt
            rel.dispatch()
            self.ws.close()
        
        def on_message(self, ws, message):
            # Implement your app logic
            try:
                received_message = json.loads(message)
            except JSONDecodeError as e:
                print(f"Failed to decode JSON message: {e}")
                return
            print(f"Got: {received_message}")
            
        # on_error, on_close, on_open, on_pong functions
        
        def send_reply_to(self, recipient, message):
            if recipient is None or self.ws is None:
                print("Cannot send message: recipient or ws is None")
                return
            
            self.ws.send(json.dumps({
                "type": "reply",
                "message": message,
                "senderTag": recipient,
            })
    ```
    
    If you use Golang, we developed a module to facilitate the mixnet integration in your application, you can check it out on our repository: [github.com/notrustverify/nymsocketmanager](http://github.com/notrustverify/nymsocketmanager).
    

### Web assembly client

> Please note that we explain here how to use the web assembly client in a JS/TS web application, however, a new Typescript SDK has been released in early October 2023, which we will integrate into Pastenym in the near future. We might release a guide for this as well or update this article, keep an eye on our blog ;)

The web assembly client is a bit trickier to use and you might need to check our code or [Nym's examples](https://github.com/nymtech/nym/tree/3be0a6cf655e71fce1485fba4deddf995b6a137d/sdk/typescript/examples) a bit more in-depth. In our case, we used it in Pastenym frontend, in React and the whole application is packaged with Webpack. You can find the documentation for the web assembly client [here](https://github.com/nymtech/nym/blob/3be0a6cf655e71fce1485fba4deddf995b6a137d/documentation/docs/src/sdk/typescript.md#using-the-sdk).

You first need to install the [Nym SDK](https://www.npmjs.com/package/@nymproject/sdk), which eases the use of the Wasm client, using the following command, from your project directory:

```bash
npm install @nymproject/sdk
# you can of course use yarn or other package managers
```

In our React frontend, we grouped the connection to the Nym client in a file ([this one](https://github.com/notrustverify/pastenym-frontend/blob/v2.0.2/src/context/createConnection.js)), where we do the following:

```javascript
import { createNymMixnetClient } from '@nymproject/sdk'
​
export async function connectMixnet() {
    const nym = await createNymMixnetClient()
​
    const nymApiUrl = 'https://validator.nymtech.net/api'
    const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM'
​
    // WSS is mandatory for HTTPS website
    const gatewayListener = 'wss://gateway1.nymtech.net:443'
​
    // start the client and connect to a gateway
    await nym.client.start({
        clientId: '<another_name_of_your_choosing>',
        nymApiUrl,
        preferredGatewayIdentityKey: preferredGatewayIdentityKey,
        gatewayListener: gatewayListener,
    })
​
    return nym
}
```

We can see that we use Nym's library to create a nym client and we then start with specific parameters, among which, a `clientID`, which you are invited to change, as for the websocket nym client.

The `nym` object returned by the Nym library, after being started, allows to subscribe functions with [`nym.events`](http://nym.events)`.subscribeToConnected`, [`nym.events`](http://nym.events)`.subscribeToTextMessageReceivedEvent`, or [`nym.events`](http://nym.events)`.subscribeToRawMessageReceivedEvent` to receive messages, as well as to send messages to the mixnet using `nym.client.Send` or `nym.client.rawSend`.

The above piece of code allows us to call the `connectMixnet()` function in our components. For instance, in the [UserText.js](https://github.com/notrustverify/pastenym-frontend/blob/v2.0.2/src/UserInput.js) component (the landing page of the application), we have the following piece of code that will, once the component has been mounted, load the Nym client and instruct callback functions to be called upon reception of messages from the mixnet ([here](https://github.com/notrustverify/pastenym-frontend/blob/v2.0.2/src/UserInput.js#L209)). In our case, it is the `displayReceived` function of the `UserInput` component that will handle the messages received from the mixnet.

```javascript
import * as React from 'react'
import { connectMixnet } from './context/createConnection'
​
class UserInput extends React.Component {
    
    // Plenty of other stuff here
    
    async componentDidMount() {
        this.nym = await connectMixnet()
​
        // When connected, we receive a message with our clientID
        this.nym.events.subscribeToConnected((e) => {
            if (e.args.address) {
                // We store our clientID in the component's state
                this.setState({ self_address: e.args.address })
            }
        })
​
        this.nym.events.subscribeToRawMessageReceivedEvent((e) => {
            this.displayReceived(this.decoder.decode(e.args.payload))
        })
    }
    
    async sendMessageTo(payload) {
        if (!this.nym) {
            console.error('Could not send message because worker does not exist')
            return
        }
​
        await this.nym.client.rawSend({
            payload: this.encoder.encode(payload),
            recipient: recipient
        })
    }
}
```

This is how we can use the Nym SDK to have a frontend communicating with the mixnet.

## **Conclusion**

And that's it! You now know how to send messages to and receive messages from the mixnet from your application! You will maybe only use one of these two nym clients, maybe both, or maybe another one, it will depend on your application. We did not mentioned about SURBs, the last nym client, or the latest Typescript SDK to keep it simple, however you can always check the official documentation, Nym's examples or our code to learn more about these!

### **Warning from the privacy wizard**

**It is not because an application uses the mixnet that the privacy guarantees of the mixnet are still applying to your application or that your application will be perfectly private!** In other words, using the mixnet is a necessary but not sufficient condition to respect the privacy of the users.

If your application requires users to provide a unique identifier (pseudo, email, phone number,...), to connect the an account for instance, then the sender of a message will still be identifiable, despite the use of the mixnet. The "sender pseudonimity" property will be lost, as the sender will be identifiable.

Similarly, if your application requires the user to visit a specific URL or endpoint to use a specific feature of your application (`/login`, `/sendMessage`, `/profile?id=1234, ...`), each use of the feature will result in an HTTP request, that will not go through the mixnet and will leak information about the user and their activity to the ISP and other internet intermediaries.

For these reasons, your application should be designed with privacy as the default and each implementation choice should be carefully thought to prevent harming the privacy of the users.

---

%%[footer-english]
