7 min read
Overview
You can leverage the power of Streams for onchain event alerts by setting up a filter inside your stream. Your filter can contain conditional logic that is evaluated against the streaming data, and also enables you to customize the payload that is sent to your stream destination. Filtering your stream ensures you only pay for the data you need.
Creating a Telegram bot that notifies you every time someone buys a specific ERC-20 token on Uniswap V2/V3 is a practical way to stay updated on the activity of the token.
In this guide, we'll use $PEPE as the example token. We'll set up a stream to monitor transfers, use a filter to detect buys of the token on Uniswap V2/V3, and directly integrate with Telegram to send notifications.
What You Will Do
- Create a Telegram bot
- Create a Stream on QuickNode
- Filter incoming Stream data and create a message payload to send to your Telegram bot
- Send the message payload directly to your Telegram bot
What You Will Need
- A QuickNode account
- Telegram
- Basic understanding of Ethereum transactions and events
Create a Telegram Bot
- You can get your Telegram bot token by messaging
/newbot
to@botfather
in Telegram and following the prompts. - Once you have your token, add the bot as an admin to the channel or group where you want the messages to appear. The token is
<bot_token>
. - There should be at least one message in the group/channel.
- After you have added the bot, visit this URL in the browser. Replace
<bot_token>
with your bot token:https://api.telegram.org/bot<bot_token>/getUpdates
- Look for the
chat
object in the response and copy itsid
- this is<your_chat_id>
- keep it handy, as you'll need it later.
Set Up the Stream
Navigate to QuickNode Streams page and click Create Stream button.
On the Stream settings page, align the Stream to the following configuration:
- Chain: Ethereum
- Network: Mainnet
- Dataset: Receipts
- Stream start: Latest
- Stream payload: Modify the Stream before streaming
Then, utilize the following code to Filter the Stream. The code filters transaction receipts containing Uniswap V2 & V3 swaps in which the Uniswap router sends the specific token, in this case $PEPE token, to an address. Feel free to modify the filter to suit your filtering criteria. The filter creates a payload out of the matching transfers that we will send to our Telegram bot. Make sure to replace <your_chat_id>
with your Telegram chat ID. Note: On blocks where a matching event does not occur, our code will return null
. This means that our Stream will only send data when matching events are detected in the Streaming data.
function main(data) {
const tokenContractAddress = "0x6982508145454Ce325dDbE47a25d4ec3d2311933";
const uniswapV3SwapTopicHash = "0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67";
const uniswapV2SwapTopicHash = "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822";
const transferTopicHash = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
const uniswapRouterAddress = "0x0000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fad";
const tokenName = "$PEPE"; // Name of the token
const decimals = 18; // Number of decimal places of the token
var messages = [];
var data = data.streamData;
data.forEach(receipt => {
var swaps = [];
var tokenTransfers = [];
// Filter for Uniswap V3 and V2 Swap events
swaps = receipt.logs.filter(log =>
log.topics[0] === uniswapV3SwapTopicHash ||
log.topics[0] === uniswapV2SwapTopicHash
);
// Filter for matching token Transfers
tokenTransfers = receipt.logs.filter(log =>
log.address.toLowerCase() === tokenContractAddress.toLowerCase() &&
log.topics[0].toLowerCase() === transferTopicHash.toLowerCase() &&
log.topics[1].toLowerCase() === uniswapRouterAddress.toLowerCase()
);
// Check if there are swaps and transfers in the same receipt
// Parse the matching transfers into the message
if (swaps.length > 0 && tokenTransfers.length > 0) {
tokenTransfers.forEach(transfer => {
let recipient = '0x' + transfer.topics[2].slice(26);
let amount = parseInt(transfer.data, 16);
let formattedAmount = (amount / Math.pow(10, decimals)).toFixed(decimals).replace(/\.?0+$/, ""); // Convert and format the amount with decimals
messages.push({
recipient,
amount: formattedAmount,
transactionHash: receipt.transactionHash
});
});
}
});
if (messages.length > 0) {
let formattedMessages = messages.map(msg => {
let addressLink = `[${msg.recipient}](https://etherscan.io/address/${msg.recipient})`;
let txHashLink = `[${msg.transactionHash}](https://etherscan.io/tx/${msg.transactionHash})`;
return `${addressLink} bought ${msg.amount} ${tokenName} in transaction ${txHashLink}!`;
});
return {
chat_id: "<your_chat_id>",
text: `** ${tokenName} Swaps detected!! **\n` + formattedMessages.join('\n'),
parse_mode: "Markdown"
};
} else {
return null;
}
}
You can click the Run Test button to ensure your filter is syntactically correct. You'll see an example response that tested your filter code on the Receipts dataset. You can set the block number for testing to 20040311
in which a $PEPE swap occurred.
For purposes of retrieving historical data, you don't need to enable the re-org handling option, however if you want to stream real-time data, you can enable the Latest block delay or Restream on reorg feature to handle re-orgs. You can learn more about re-orgs here. Once the page is finished, click Next and you'll need to configure your Stream destination.
Then, on the Stream destination page, set up the destination as Webhook and configure it to align with the following details below. If a field is not mentioned, you can leave it as-is.
- Destination URL: Input the URL to the Telegram API,
https://api.telegram.org/bot<your_bot_token>/sendMessage
, making sure to insert<your_bot_token>
as indicated. - Custom headers: Enable this option and include the following headers:
Content-Type: application/json
Before activating the Stream, use the Test Destination button to verify your setup. You can return to the previous step to adjust the block number (to one that meets your Filter criteria, for example - block 20019228). This allows you to test your bot with specific Streams data prior to going live.
To test again via CLI, we will send a curl request to test our Telegram bot. Open your Terminal app and send this curl request, which contains a sample payload and will trigger your Telegram bot if it's configured correctly. Please make sure to replace <your_bot_token>
and <your_chat_id>
in the curl request.
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"chat_id": "<your_chat_id>",
"parse_mode": "Markdown",
"text": "** $PEPE Swaps detected!! **\n[0x000000fee13a103a10d593b9ae06b3e05f2e7e1c](https://etherscan.io/address/0x000000fee13a103a10d593b9ae06b3e05f2e7e1c) bought 3265.647766725334804505 $PEPE in transaction [0xce33006642e3e3491171b1324c3692a0178d155af1c09732b6ceb2255d8c3d7e](https://etherscan.io/tx/0xce33006642e3e3491171b1324c3692a0178d155af1c09732b6ceb2255d8c3d7e)!\n[0x236a6a5b483df9fb61a477e70cf2a8a85e7e36d5](https://etherscan.io/address/0x236a6a5b483df9fb61a477e70cf2a8a85e7e36d5) bought 1302993.458923408761620522 $PEPE in transaction [0xce33006642e3e3491171b1324c3692a0178d155af1c09732b6ceb2255d8c3d7e](https://etherscan.io/tx/0xce33006642e3e3491171b1324c3692a0178d155af1c09732b6ceb2255d8c3d7e)!"
}' \
https://api.telegram.org/bot<your_bot_token>/sendMessage
Finally, click the Create a Stream button. Once the Stream has started, check the Telegram channel or group where you added your bot.
When $PEPE swaps are detected, you will see messages like this from your Telegram bot:
& that's it! You just created an end-to-end Telegram alerting system with Streams and filters. To learn more, check out the following resources below.
More resources
- How to Validate Incoming Streams Webhook Messages
- Visualizing Real-Time Blockchain Data With Streams and React
- Streams Documentation
Final Thoughts
If you have questions, please contact us directly. If you have any ideas or suggestions, such as new destinations, features, metrics, or datasets, you want us to support.
Also, stay up to date with the latest by following us on Twitter and joining our Discord and Telegram announcement channel.
We ❤️ Feedback!
Let us know if you have any feedback or requests for new topics. We'd love to hear from you.