Retrieve current price data off-chain with Chainlink Data Feeds
Learn how to retrieve asset price data using Chainlink Price Feeds
Introduction
In this tutorial, you will learn how to retrieve current price data off-chain for various cryptocurrencies and real-world assets by using Chainlink Data Feeds. You will retrieve data from Chainlink's deployed Verified Price Feed smart contracts on Polygon Mainnet using an RPC endpoint and web3.js, a widely-used JavaScript library for Ethereum. Chainlink Data Feeds gather and publish aggregated data from a variety of sources on-chain, utilizing Chainlink's decentralized oracle network.
Prerequisites
- Installation of Node.js (version 18 or above)
- A text editor (such as Visual Studio Code)
- Basic knowledge of Ethereum and smart contracts
- Installation of the AWS Command Line Interface (CLI).
- Run the command
aws configureto set the variables for your IAM User’sAccess Key ID,Secret Access Key, andRegion.- Ensure that this User has the appropriate IAM permissions.
- Run the command
Step 1: Setting up the project
- Create a new directory for your project and change into it by running the following command:
mkdir chainlinkPriceFeeds && cd chainlinkPriceFeeds
- Run the following command to install the necessary dependencies:
npm install web3 dotenv
Web3 enables blockchain interactions, and dotenv handles storage for your Polygon Mainnet RPC endpoint.
Step 2: Polygon RPC Endpoint Configuration
Create a .env file in your project root and add your Polygon Mainnet RPC endpoint (from Alchemy, Infura, QuickNode, etc:
POLYGON_MAINNET_RPC_URL=YOUR_RPC_URL
Step 3: Write the Chainlink Price Feeds Script
Create a new file (e.g priceFeeds.js) and copy the following code:
const { Web3 } = require('web3')
require('dotenv').config();
const web3 = new Web3(process.env.POLYGON_MAINNET_RPC_URL);
const abi = [{ "inputs": [{ "internalType": "address", "name": "_aggregator", "type": "address" }, { "internalType": "address", "name": "_accessController", "type": "address" }], "stateMutability": "nonpayable", "type": "constructor" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "int256", "name": "current", "type": "int256" }, { "indexed": true, "internalType": "uint256", "name": "roundId", "type": "uint256" }, { "indexed": false, "internalType": "uint256", "name": "updatedAt", "type": "uint256" }], "name": "AnswerUpdated", "type": "event" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "uint256", "name": "roundId", "type": "uint256" }, { "indexed": true, "internalType": "address", "name": "startedBy", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "startedAt", "type": "uint256" }], "name": "NewRound", "type": "event" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }], "name": "OwnershipTransferRequested", "type": "event" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }], "name": "OwnershipTransferred", "type": "event" }, { "inputs": [], "name": "acceptOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "accessController", "outputs": [{ "internalType": "contract AccessControllerInterface", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "aggregator", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "_aggregator", "type": "address" }], "name": "confirmAggregator", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "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": "uint256", "name": "_roundId", "type": "uint256" }], "name": "getAnswer", "outputs": [{ "internalType": "int256", "name": "", "type": "int256" }], "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": [{ "internalType": "uint256", "name": "_roundId", "type": "uint256" }], "name": "getTimestamp", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "latestAnswer", "outputs": [{ "internalType": "int256", "name": "", "type": "int256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "latestRound", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "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": "latestTimestamp", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint16", "name": "", "type": "uint16" }], "name": "phaseAggregators", "outputs": [{ "internalType": "contract AggregatorV2V3Interface", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "phaseId", "outputs": [{ "internalType": "uint16", "name": "", "type": "uint16" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "_aggregator", "type": "address" }], "name": "proposeAggregator", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "proposedAggregator", "outputs": [{ "internalType": "contract AggregatorV2V3Interface", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint80", "name": "_roundId", "type": "uint80" }], "name": "proposedGetRoundData", "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": "proposedLatestRoundData", "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": [{ "internalType": "address", "name": "_accessController", "type": "address" }], "name": "setController", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "_to", "type": "address" }], "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "version", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }]
//Contract addresses for Chainlink Data Feeds on Polygon Mainnet
const contracts = [
{ name: 'Bitcoin', address: '0xc907E116054Ad103354f2D350FD2514433D57F6f' },
{ name: 'Ethereum', address: '0xF9680D99D6C9589e2a93a78A04A279e509205945' },
{ name: 'Polygon', address: '0xAB594600376Ec9fD91F8e885dADF0CE036862dE0' },
{ name: 'XAU (Gold)', address: '0x0C466540B2ee1a31b441671eac0ca886e051E410' },
{ name: 'GBP/USD', address: '0x099a2540848573e94fb1Ca0Fa420b00acbBc845a' }
];
const getDecimals = async (priceFeed) => {
return await priceFeed.methods.decimals().call();
}
const getLatestRoundData = async (priceFeed) => {
return await priceFeed.methods.latestRoundData().call();
}
async function main() {
for (const contract of contracts) {
try {
const priceFeed = new web3.eth.Contract(abi, contract.address);
const decimals = await getDecimals(priceFeed);
const roundData = await getLatestRoundData(priceFeed);
const balanceNumber = Number(roundData.answer) / (10 ** Number(decimals));
const formattedBalanceString = balanceNumber.toLocaleString('en-US', {
style: 'currency',
currency: 'USD'
});
console.log(`${contract.name} Price: ${formattedBalanceString}`);
} catch (error) {
console.error(`An error occurred with ${contract.name}:`, error);
}
}
}
main();
Run the script with the following command:
node priceFeeds.js
You will see the current prices in USD for Bitcoin, Ethereum, Polygon, gold (in ounces), and the Great Britain Pound. This data was saved in a decentralized manner to Chainlink’s on-chain Verified Price Feeds. If you would like to incorporate price feed data for other assets, you can refer to Chainlink’s extensive list of Price Feed Contract Addresses.
Conclusion
You have successfully utilized Chainlink Price Feeds to fetch real time prices of various assets from off-chain using web3.js. If you would like to learn more about Chainlink Price Feeds, you can refer to the official documentation. Remember to prioritize security, especially with sensitive data such as your RPC endpoint.
Please leave a comment below if you have any questions.
- Topics
- Blockchain
- Tags
- Blockchain
- Language
- English
Relevant content
- asked 6 years ago
- asked 2 years ago
AWS OFFICIALUpdated 2 years ago