111 lines
4.4 KiB
Markdown
111 lines
4.4 KiB
Markdown
---
|
|
title: Whisper JavaScript example
|
|
sort_key: B
|
|
---
|
|
|
|
[This link](https://github.com/gballet/whisper-chat-example) contains a full-fledged example of how to use Whisper in a small chat application.
|
|
|
|
The app is a simple Vue single page application that works in several steps. In the first step, the user configures the RPC service that they wish to connect to. Typically, this would be a `geth` client with the `--shh` option enabled.
|
|
|
|
Then one can install the application locally by typing:
|
|
|
|
```
|
|
$ git clone https://github.com/gballet/whisper-chat-example
|
|
$ cd whisper-chat-example
|
|
$ npm install
|
|
```
|
|
|
|
The application is then started by typing:
|
|
|
|
```
|
|
$ npm run dev
|
|
```
|
|
|
|
The application will then be available at `http://localhost:8080` (Note the http here, which is because it's a **demo application** and should not be used in production)
|
|
|
|
## User workflow
|
|
|
|
The app starts by asking the user for their user name and whether they want a symmetric or asymmetric connection. If it's asymmetric, the geth server will propose a public key. If it's symmetric, a key has to be provided.
|
|
|
|
Then the user presses "Start" and the conversation begins.
|
|
|
|
## The app's state
|
|
|
|
```javascript
|
|
let data = {
|
|
msgs: [],
|
|
text: "",
|
|
symKeyId: null,
|
|
name: "",
|
|
asymKeyId: null,
|
|
sympw: "",
|
|
asym: true,
|
|
configured: false,
|
|
topic: defaultTopic,
|
|
recipientPubKey: defaultRecipientPubKey,
|
|
asymPubKey: ""
|
|
};
|
|
```
|
|
|
|
This is how the current, transient, state of the application is represented:
|
|
|
|
* `msgs` is the list of messages in the current conversation
|
|
* `text` contains the text that the current user is typing
|
|
* `name` is the name of the current user, which is used to identify them in conversations
|
|
* `asymKeyId` and `symKeyId` represent handles to the corresponding keys in `geth`'s memory
|
|
* `recipientPubKey` is a hex string representing the public key that an asymmetric message is sent to
|
|
* `topic` is a hex string representing the message's topic
|
|
* `asymPubKey` is a hex string representing the user's own public key
|
|
* `configured` is a flag that is set to true when the user has choosen either a public key or a symmetric key, and a user name
|
|
* `sympw` contains the symmetric password
|
|
|
|
## The `sendMessage` callback
|
|
|
|
The `sendMessage` callback is called every time the user clicks on "Send" or presses the return key. It is responsible for creating the RPC request that instructs the `geth` node to encrypt and send the message.
|
|
|
|
```javascript
|
|
sendMessage() {
|
|
// Start by declaring the message, we picked a JSON format with
|
|
// `text` as the content and `name` as the name of the user who
|
|
// is sending the message.
|
|
let msg = {
|
|
text: this.text,
|
|
name: this.name
|
|
};
|
|
|
|
// (code elided for clarity)
|
|
// ...
|
|
|
|
// Create the data object that will be sent to the RPC endpoint.
|
|
let postData = {
|
|
ttl: 7,
|
|
topic: '0x07678231',
|
|
powTarget: 2.01,
|
|
powTime: 100,
|
|
payload: encodeToHex(JSON.stringify(msg)),
|
|
};
|
|
|
|
// Set the appropriate key id.
|
|
if (this.asym) {
|
|
postData.pubKey = this.recipientPubKey;
|
|
postData.sig = this.asymKeyId;
|
|
} else
|
|
postData.symKeyID = this.symKeyId;
|
|
|
|
// Perform the RPC call that will tell the node to forward
|
|
// that message to all its neighboring nodes.
|
|
this.shh.post(postData);
|
|
|
|
// (code elided for clarity)
|
|
// ...
|
|
}
|
|
```
|
|
|
|
The `msg` object is created. The format chosen for the object is specific to this demo application. It just contains a text and the name of the sender. This is obviously not secure enough for a real-world application.
|
|
|
|
That object is converted to a string and then encoded as a hexadecimal string, in the `payload` member of the request's `POST` data object. Other fields include the `topic` of the message, how much work the sending server should do and other parameters.
|
|
|
|
Next, depending whether the "asymmetric" checkbox has been ticked, the value of `this.asym` will be true or false. Based on this, the system will update the request object with the relevant information.
|
|
|
|
Finally, the request is being sent with `this.shh.post(postData)`, which calls Web3's `shh.post` function to send the message.
|