Introduction
In recent times, blockchain technology has transcended from being just a foundation for cryptocurrencies to a pivotal technology for decentralized applications (DApps). One blockchain platform that has caught the attention of developers globally is Celo.
This article provides an extensive overview of the Celo blockchain, the Whisper protocol, and demonstrates how to implement these technologies to build a decentralized messaging application. By the end of this tutorial, you should be equipped with an understanding of how to build decentralized messaging apps on Celo and how to use Whisper for secure, decentralized communication.
Prerequisites
To follow along with this tutorial, you will need:
-
Basic understanding of JavaScript and React
-
Basic understanding of blockchain technology and smart contracts
-
Familiarity with the command line
Requirements
The following tool and technologies will be required to Build a Celo-Based Decentralized Messaging App with Whisper
-
Node.js and npm installed on your local machine
-
A code editor, such as Visual Studio Code
-
Celo SDK, Web3.js library, and React framework installed
Here is the Source code for our project.
Step-by-Step Guide to Building a Celo-Based Decentralized Messaging App with Whisper
What is Celo?
Celo is a decentralized, open-source blockchain protocol aimed at making cryptocurrencies accessible to anyone with a smartphone. Celo uses proof-of-stake (PoS) consensus mechanism, which offers scalability without compromising decentralization.
What is Whisper?
Whisper is a communication protocol for DApps to communicate with each other on the Ethereum network. It’s designed for broadcasting short messages to the network for peers to pick up and process. Whisper messages are encrypted and designed to provide a layer of anonymity between the sender and the receiver.
Step 1: Setting Up the Development Environment
Before you can start building the app, you need to set up your development environment. Install Celo SDK and Web3.js using npm (Node Package Manager):
//bash
npm install @celo/contractkit web3
Step 2: Creating a React Application
Create a new React application using Create React App:
bash
npx create-react-app celo-whisper-app
This command will create a new React application with the name celo-whisper-app. You can replace celo-whisper-app with the name of your choice.
Step 3: Backend Development - Creating a Whisper Channel
To create a Whisper channel, we first need to generate a Whisper identity and then use it to create the channel. Include the following code in your backend:
const identity = await web3.shh.newIdentity();
const channel = await web3.shh.subscribe('messages', {
ttl: 20,
minPow: 2.77,
topics: ['0x776869737065722d6368616e6e656c'],
allowP2P: true
}, identity);
In a decentralized messaging app, communication occurs through channels. Whisper enables the creation of secure messaging channels. To differentiate channels, we generate a Whisper identity using the shh.newIdentity()
function. Then, we subscribe to a new Whisper channel using the shh.subscribe()
function, passing the identity, message type, and a configuration object.
Step 4: Connecting to Celo Network
To connect to the Celo network, you need to create an instance of the ContractKit. Here’s how you do it:
//javascript
const Web3 = require('web3');
const { newKitFromWeb3 } = require('@celo/contractkit');
const web3 = new Web3('https://alfajores-forno.celo-testnet.org');
const kit = newKitFromWeb3(web3);
Here, https://alfajores-forno.celo-testnet.org is the URL for the Alfajores testnet. Replace it with the URL of the Celo network you want to connect to.
Step 5: Creating a Whisper Channel
To create a Whisper channel, you need to create a Whisper identity and then use this identity to create a Whisper channel.
//javascript
const identity = await web3.shh.newIdentity();
const channel = await web3.shh.subscribe('messages', {
ttl: 20,
minPow: 2.77,
topics: ['0x776869737065722d6368616e6e656c'],
allowP2P: true
}, identity);
In the above code, 0x776869737065722d6368616e6e656c is the topic of the Whisper channel.
In a decentralized messaging app, the communication takes place through channels. Whisper allows you to create such channels for secure messaging. Each channel needs a unique identity for differentiation. You can create a Whisper identity using the shh.newIdentity()
function.
//javascript
const identity = await web3.shh.newIdentity();
After the identity has been created, you can use it to subscribe to a new Whisper channel. This is done using the shh.subscribe()
function, which requires an identity, the type of messages to subscribe to (‘messages’ in our case), and a configuration object.
The configuration object should contain:
-
ttl: Time-to-live in seconds, showing how long a message should be kept in the network.
-
minPow: The minimal proof-of-work (PoW) a message needs to have.
-
topics: An array of topics. The topics act as filters that determine the messages the node is interested in receiving.
-
allowP2P: If true, allows peer-to-peer messages (directly between peers, not through the Whisper protocol).
Here’s the code snippet for it:
//javascript
const channel = await web3.shh.subscribe('messages', {
ttl: 20,
minPow: 2.77,
topics: ['0x776869737065722d6368616e6e656c'],
allowP2P: true
}, identity);
In the above code, 0x776869737065722d6368616e6e656c is the topic of the Whisper channel.
Step 6: Sending Messages
With Whisper, messages are sent as objects containing different parameters such as payload, ttl, powTarget, and powTime. Here is how to send a message:
//javascript
const message = {
from: identity,
payload: web3.fromAscii('Hello, Celo!'),
ttl: 10,
topic: '0x776869737065722d6368616e6e656c',
powTarget: 2.01,
powTime: 100
};
await web3.shh.postMessage(message);
After setting up the Whisper channel, the next step is sending messages. In Whisper, messages are not just strings but objects that contain several properties:
from: The identity of the sender.
payload: The message itself.
ttl: Time-to-live in seconds.
topic: The topic of the message.
powTarget: The target proof-of-work.
powTime: The max work time in seconds.
Firstly, we convert the text message into a hexadecimal format using the web3.fromAscii() function
. After that, we use the shh.postMessage()
function to send the message:
//javascript
const message = {
from: identity,
payload: web3.fromAscii('Hello, Celo!'),
ttl: 10,
topic: '0x776869737065722d6368616e6e656c',
powTarget: 2.01,
powTime: 100
};
await web3.shh.postMessage(message);
Step 7: Receiving Messages
You can listen to incoming messages by using the channel.on(‘data’, callback) method, where callback is the function that will be executed when a message is received.
//javascript
channel.on('data', (message) => {
console.log(web3.toAscii(message.payload));
});
To receive messages, you need to listen for new messages on the Whisper channel. This can be done by using the channel.on('data', callback)
function.
The channel.on('data', callback)
function listens for the ‘data’ event which is emitted whenever a new message is received. The callback function is then invoked with the new message as an argument.
In this case, the callback function takes the payload property from the received message, converts it from hexadecimal to ASCII using web3.toAscii(), and then logs it to the console:
//javascript
channel.on('data', (message) => {
console.log(web3.toAscii(message.payload));
});
This will print the content of any new message received on the Whisper channel.
Conclusion
This tutorial provided a comprehensive guide on building a Celo-based decentralized messaging app with the Whisper protocol. By following these steps, developers can leverage the power of Celo and Whisper to build secure, decentralized applications. However, remember to follow the best security practices during development to ensure the privacy and safety of your application’s users.
About the Author
Michael Diagbare is a Software Engineer with expertise in Web, Blockchain development and content creation, certified by Cisco and MongoDB university. He is passionate about building software, problem solving and helping programmers deal with complicated tasks and challenges.
Connect with me on LinkedIn