Using Data Feeds

The code for reading Data Feeds is the same across all EVM-compatible blockchains and Data Feed types. You choose different types of feeds for different uses, but the request and response format are the same. To read a feed, specify the following variables:

  • RPC endpoint URL: This determines which network that your smart contracts will run on. You can use a node provider service or point to your own client. If you are using a Web3 wallet, it is already configured with the RPC endpoints for several networks and the Remix IDE will automatically detect them for you.

  • Feed contract address: This determines which data feed your smart contract will read. Contract addresses are different for each network. You can find the available contract addresses on the following pages:

The examples in this document indicate these variables, but you can modify the examples to work on different networks and read different feeds.

This guide shows example code that reads data feeds using the following languages:

Reading data feeds on-chain

These code examples demonstrate how to deploy a consumer contract on-chain that reads a data feed and stores the value.

Solidity

To consume price data, your smart contract should reference AggregatorV3Interface, which defines the external functions implemented by Data Feeds.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

/**
 * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED
 * VALUES FOR CLARITY.
 * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */

interface AggregatorV3Interface {

  function decimals() external view returns (uint8);
  function description() external view returns (string memory);
  function version() external view returns (uint256);

  // getRoundData and latestRoundData should both raise "No data present"
  // if they do not have data to report, instead of returning unset values
  // which could be misinterpreted as actual reported values.
  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

}


contract DataConsumer {
    AggregatorV3Interface internal dataFeed;

    /**
     * Network: Bitlayer
     * Aggregator: BTC/USD
     * Address: 0x62d2c5dEe038FaEbc3F6ec498fD2Bbb3b0080B03
     */
    constructor() {
        dataFeed = AggregatorV3Interface(
            0x62d2c5dEe038FaEbc3F6ec498fD2Bbb3b0080B03
        );
    }

    /**
     * Returns the latest answer.
     */
    function getDataFeedLatestAnswer() public view returns (int) {
        // prettier-ignore
        (
        /* uint80 roundId */,
        int256 answer,
        /*uint256 startedAt*/,
        /*uint256 timeStamp*/,
        /*uint80 answeredInRound*/
        ) = dataFeed.latestRoundData();
        return answer;
    }

    /**
     * Returns decimals.
     */
    function getDecimals() public view returns (uint8) {
        uint8 decimals = dataFeed.decimals();
        return decimals;
    }
}

The latestRoundData function returns five values representing information about the latest price data. See the Data Feeds API Reference for more details.

Reading data feeds off-chain

These code examples demonstrate how to read data feeds directly off-chain using Web3 packages for each language.

Javascript

This example uses web3.js to retrieve feed data from the BTC / USD feed on the BitLayer testnet.

/**
 * THIS IS EXAMPLE CODE THAT USES HARDCODED VALUES FOR CLARITY.
 * THIS IS EXAMPLE CODE THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */

const Web3 = require("web3") // for nodejs only
const web3 = new Web3("https://testnet-rpc.bitlayer.org")
const aggregatorV3InterfaceABI = [
    {
        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",
    },
]
const addr = "0x62d2c5dEe038FaEbc3F6ec498fD2Bbb3b0080B03"
const priceFeed = new web3.eth.Contract(aggregatorV3InterfaceABI, addr)
priceFeed.methods
    .latestRoundData()
    .call()
    .then((roundData) => {
        // Do something with roundData
        console.log("Latest Round Data", roundData)
    })

Last updated