How to build a Telegram bot to show Chainlink price feeds
The main idea of this tutorial is to show an example of how to develop a Telegram bot that consumes Chainlink price feeds for BTC/USD and ETH/USD pair of assets from Ethereum, Polygon and Binance Smart Chain mainnets.
The progam language used is python
Useful documentation
Source code of python-telegram-bot https://github.com/python-telegram-bot/python-telegram-bot
Price feeds https://docs.chain.link/docs/reference-contracts/
Introduction to Telegram Bot API
This library provides a pure Python, lightweight interface for the Telegram Bot API. It’s compatible with Python versions 3.6.8+. PTB-Raw might also work on PyPy, though there have been a lot of issues before. Hence, PyPy is not officially supported.
python-telegram-bot-raw is part of the python-telegram-bot ecosystem and provides the pure API functionality extracted from PTB. It therefore does not have independent release schedules, changelogs or documentation. Please consult the PTB resources.
Screenshot
Install from github repo
git clone https://github.com/apronotti/telegram-bot-to-show-chainlink-price-feeds.git
cd telegram-bot-to-show-chainlink-price-feeds
pip install -r requirements.txt
Generate your bot and Access Token
To generate an Access Token, you have to talk to @BotFather and follow a few simple steps (described here).
Config
With the bot Access TOKEN obtained in the former step:
- Copy or rename the file config.json.example as config.json
- Edit config.json file and replace the word TOKEN for the current Telegram Access TOKEN value
- Obtain and replace the project ids in congig.json for the RPC providers (example: Infura, Alchemy) to access the Ethereum and Polygon networks
Runing the bot
python3 btc_eth_query_prices_n_blockchains.py
Installing the bot in your Telegram App
Once the bot was generated in the former step titled “Generate your bot and Access Token”, in Telegram app click on https://t.me/[NAME_OF_THE_BOT]
(You need to replace NAME_OF_THE_BOT with your bot name)
or
if you want, you can try the example bot at https://t.me/btc_eth_cl_query_prices_bot
Using the bot
- In the Telegram App message field type /start, this command is used only one time to initialize the bot
- Each time you want to query prices type /pricefeeds
- Choose one of the options “BTC/USD price” or “ETH/USD price”
- And wait the results
Aditional information on how it works
Step by step, how to query a Chainink price feed in python
- Go to https://docs.chain.link/docs/reference-contracts/
- Click on the chosen chain for example Ethereum
- Copy the ETH/USD Proxy contract address 0x9326BFA02ADD2366b30bacB125260Af641031331 and use it in the next example.
This example uses Web3 module to retrieve feed data from the ETH / USD feed on the Ethereum network.
In a terminal execute the fololowing commands:
# pip install web3# python3
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from web3 import Web3
>>> web3 = Web3(Web3.HTTPProvider('https://kovan.infura.io/v3/<infura_project_id>'))
>>> abi = '[{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint80","name":"_roundId","type":"uint80"}],"name":"getRoundData","outputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestRoundData","outputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]'
>>> addr = '0x9326BFA02ADD2366b30bacB125260Af641031331'
>>> contract = web3.eth.contract(address=addr, abi=abi)
>>> latest_data = contract.functions.latestRoundData().call()
>>> print(int(round(latest_data[1] / 10 ** 8, 0)))
2952
Chainlink price queries are implemented in the following part of the source code of the bot
...# Interface of Chainlink Price Feed Proxy contract
ABI_CL_PRICE_FEED= '[{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint80","name":"_roundId","type":"uint80"}],"name":"getRoundData","outputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestRoundData","outputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]'# Read configuration from config.json
config = Configuration.load_json('config.json')
web3_ethereum = Web3(Web3.HTTPProvider(config.ethereum.apiprovider))...
def hours_from_timestamp(self, timestampValue) -> str:
# convert timestamp to string of datetime format
date = str(dt.datetime.fromtimestamp(timestampValue))
# extract hours without seconds
hours = date[-8:][:-3]
return hours
# Query the price of ETH/USD from Ethereum, Polygon and Bsc networks
def get_eth(self) -> str:
# Address of Chainlink Price Feed Proxy contract
addr = self.config.ethereum.cl_contract_address.etherusd contract = self.web3Ethereum.eth.contract(address=addr, abi=self.ABI_CL_PRICE_FEED) # ETH/USD price query from Ethereum mainnet
latest_data = contract.functions.latestRoundData().call()
ethereum_data = (
'Ethereum', latest_data[1], self.hours_from_timestamp(latest_data[2]))...
This development was intended as an example to learn how to get prices from Chainlink in a simple way. If someone has in mind to put this bot into production environment I suggest implementing the price requests in asynchronous calls, the simplified cache in this code could be replaced by REDIS as a better tunable cache and it’s a good practice to refactor get_eth and get_btc functions into another more generic function to cover more price feeds.
About Chainlink
About Chainlink
Chainlink is the industry standard for building, accessing, and selling oracle services needed to power hybrid smart contracts on any blockchain. Chainlink oracle networks provide smart contracts with a way to reliably connect to any external API and leverage secure off-chain computations for enabling feature-rich applications. Chainlink currently secures fifty-nine of billions dollars across DeFi, insurance, gaming, and other major industries, and offers global enterprises and leading data providers a universal gateway to all blockchains.
Learn more about Chainlink by visiting chain.link or read the documentation at docs.chain.link. To discuss an integration, reach out to an expert.
Website | Twitter | Discord | Reddit | YouTube | Telegram | Events | GitHub | Price Feeds | DeFi
About me
I’m an experienced and passionate Systems Engineer with a demostrated history in development of technology enterprise products . Skilled in backend and middleware development, Sr software engineer, agile practices and team working. Strong entrepreneurial mindset and self-management with good practices to facilitate collaborative development.
Blockchain knowledge: development of smart contracts in EVM compatible networks, Web3 middleware development for DApps, expert in Chainlink Oracles.
You can contact me by email to apronotti@gmail.com. Follow me on Twitter https://twitter.com/alepronotti and social media for future updates:
Twitter | LinkedIn | GitHub
Ten articles before and after
Simple Telegram Bot using API’s. A Simple Telegram Bot which can respond… – Telegram 中文版
Making our First Telegram Bot [Part -2] – Telegram 中文版
Bots! What are they? Let’s make a Telegram Bot [Part -1] – Telegram 中文版
How I Create “Sembako Bot” using Google Cloud – Telegram 中文版
Send APK automatically to Telegram using Dart/Flutter – Telegram 中文版
IntruderDet —An Intruder Detection Bot for my Appartment – Telegram 中文版
Телеграм бот для уведомлений об ордерах Binance – Telegram 中文版
How to create a Telegram bot with Python in under 10 min! – Telegram 中文版