Skip to main content

How to use Streams and Filters to get Telegram Alerts

Updated on
Jun 11, 2024

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


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 its id - 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

stream settings

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

Since we are using the URL of the Telegram API as our webhook destination, we can skip the test destination button in this step. The Telegram API requires a specific kind of payload in order to trigger a message, so 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:

telegram bot messages

& 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


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. You can upvote or create a new idea on our Streams Roadmap.

Also, check out the QuickNode Forum for more resources on blockchain. Stay up to date with the latest by following us on Twitter (@QuickNode) or Discord.

We ❤️ Feedback!

Let us know if you have any feedback or requests for new topics. We'd love to hear from you.

Share this guide