Blockchain Discord Bot
Introduction
This tutorial teaches you how to create a web3 discord bot that listens to blockchain events and sends real-time notifications.
We will use discord.js, express and Moralis Streams API.
YouTube Tutorial
Project Setup
This section is split in multiple steps that you can follow. Let's dive in.
You can find the repository with the final code here: Github.
Create a folder and initiate a project using the package manager of your choice.
- npm
- Yarn
- pnpm
npm init -y
yarn init -y
pnpm init -y
This will initiate the project and create a package.json
file containing the following:
{
"name": "blockchainbot",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "MIT"
}
Install the required dependencies.
- npm
- Yarn
- pnpm
npm install moralis express discord.js dotenv nodemon
yarn add moralis express discord.js dotenv nodemon
pnpm add moralis express discord.js dotenv nodemon
Create an
index.js
file containing our express endpoint.
const express = require("express");
const app = express();
const port = 3000;
app.use(express.json());
app.post("/webhook", async (req, res) => {
const { body, headers } = req;
console.log(body);
res.status(200).json();
});
app.listen(port, () => {
console.log(`Listening to streams`);
});
Setup an
ngrok
tunnel to our express app that will be running locally
- Install
ngrok
.
npm i -g ngrok
- In a new terminal window run
ngrok http
to create a tunnel to our express app using the same port that we specified insideindex.js
ngrok http 3000
This will give us an address where out express app will be running and where we can setup webhooks for streams api.
Start our express server.
Back inside package.json
add a start script that will start our express app and reload when we make changes.
{
"name": "blockchainbot",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"discord.js": "^14.6.0",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"moralis": "^2.6.7",
"nodemon": "^2.0.20"
}
}
Run the start command.
- npm
- Yarn
- pnpm
npm run start
yarn run start
pnpm run start
Streams Setup
We will use Moralis Streams API to get real-time events and send notifications
Inside our admin panel access streams section and create a new stream.
Select Create From Scratch
For this example we will use this simple donation contract, but you can use any smart contract of your choice:
- Contract Address :
OxbD317B46A004CCF0e1773DBFcEE89E77e32D2dB9
- Abi:
[
{ "inputs": [], "stateMutability": "nonpayable", "type": "constructor" },
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "Donate",
"type": "event"
},
{
"inputs": [],
"name": "newDonation",
"outputs": [],
"stateMutability": "payable",
"type": "function"
}
]
For the webhook url have to use the url provided previously by ngrok, followed by our /webhook
endpoint from our express app
Our contract is deployed on mumbai testnet, so here you will select the network that your smart contract is deployed on:
Because our donations are sending native currency to a smart contract, here we will select native transactions and check Event Emittance.
Next we have to add the ABI and select the topic we want to stream.
After creating the stream Moralis will send an empty POST request to confirm that the stream was created successfully.
Verify Stream Sender
Right now everybody who knows our webhook endpoint is able to make a POST request to our express server.
To stop this from causing any errors, what we have to do now is to verify that the requests are sent by Moralis using Moralis.Streams.verifySignature
.
Back to our express endpoint, we can add logic that allows only request coming from Moralis to go through.
Go to Moralis Admin Panel and copy your web3 api key.
Create an
.env
file.
APIKEY = 'YOUR_API_KEY'
Verify the request.
const express = require("express");
const Moralis = require("moralis").default;
require("dotenv").config();
const app = express();
const port = 3000;
app.use(express.json());
app.post("/webhook", async (req, res) => {
const { body, headers } = req;
try {
Moralis.Streams.verifySignature({
body,
signature: headers["x-signature"],
});
return res.status(200).json();
} catch (e) {
console.log("Not Moralis");
return res.status(400).json();
}
});
Moralis.start({
apiKey: process.env.APIKEY,
}).then(() => {
app.listen(port, () => {
console.log(`Listening to streams`);
});
});
Discord Bot Setup
We will now begin to setup our bot to send notifications to our discord server.
- Access Discord Developer Portal and create a new application.
- Add a new bot to your application.
- Add the scope and the permissions to your bot.
- Open the generated url in a new browser tab and invite the bot to your server.
- Back in the Bot section, Reset and copy the new token.
- Add the token and the channel id you wish to send the message to inside your
.env
file.
APIKEY = 'YOUR_API_KEY'
PASS = 'YOUR_BOT_TOKEN'
CHANNEL = 'CHANNEL_ID'
- Add the discord client to your
index.js
and setup the login to send messages.
const express = require("express");
const Moralis = require("moralis").default;
const discord = require("discord.js");
require("dotenv").config();
const app = express();
const port = 3000;
const client = new discord.Client({
intents: [],
});
client.login(process.env.PASS);
app.use(express.json());
app.post("/webhook", async (req, res) => {
const { body, headers } = req;
try {
Moralis.Streams.verifySignature({
body,
signature: headers["x-signature"],
});
let from = body.txs[0].fromAddress;
let amount = Number(body.txs[0].value / 1e18);
const channel = await client.channels.fetch(process.env.CHANNEL);
channel.send(
`New Donation submitted by ${from}, for ${amount.toFixed(2)} MATIC!!!!`
);
return res.status(200).json();
} catch (e) {
console.log("Not Moralis");
return res.status(400).json();
}
});
Moralis.start({
apiKey: process.env.APIKEY,
}).then(() => {
app.listen(port, () => {
console.log(`Listening to streams`);
});
});
Testing the bot
- Run your bot.
node index.js
- To test our bot, We can now call the donation function from our contract.
- We should see a new notification sent by our bot.