NEW

Join us at SmartCon 2023—where Web3 gets real. Get your ticket.

Using Data Feeds Off-Chain (Solana)

Chainlink Data Feeds are the quickest way to access market prices for real-world assets. This guide demonstrates how to read Chainlink Data Feeds on the Solana Devnet using off-chain examples in the Chainlink Solana Starter Kit. To learn how to use Data Feeds in your on-chain Solana programs, see the Using Data Feeds On-Chain guide.

To get the full list of Chainlink Data Feeds on Solana, see the Solana Feeds page.

The program that contains the logic required for the storing and retrieval of Chainlink Data Feeds data on both Devnet and Mainnet is cjg3oHmg9uuPsP8D6g29NWvhySJkdYdAo9D25PRbKXJ. This is the program ID that you use to read price data from off-chain. You can find the source code for this program in the smartcontractkit/chainlink-solana on GitHub.

You can add data feeds to an existing off-chain project or use the Solana Starter Kit.

Adding Data Feeds to an existing off-chain project

You can read Chainlink Data Feeds off-chain in your existing project by using the Chainlink Solana NPM library.

Install the necessary components and include the example code in your project. Optionally, you can run the example code by itself to learn how it works before you integrate it with your project.

  1. Install the latest Mainnet version of the Solana CLI and export the path to the CLI:

    sh -c "$(curl -sSfL https://release.solana.com/v1.13.6/install)" &&
    export PATH="~/.local/share/solana/install/active_release/bin:$PATH"

    Run solana --version to make sure the Solana CLI is installed correctly.

    solana --version
  2. Install Node.js 14 or higher. Run node --version to verify which version you have installed:

    node --version
  3. Change to your project directory or create a new directory.

    mkdir off-chain-project && cd off-chain-project
  4. Optionally install Yarn to use as a package manager and initialize yarn if your project does not already have a package.json file:

    npm install -g yarn && yarn init
  5. Add the Anchor library to your project:

    npm i @project-serum/anchor
  6. Add the Chainlink Solana NPM library to your project:

    npm i -g @chainlink/solana-sdk
  7. Create a temporary Solana wallet to use for this example. Alternatively, if you have an existing wallet that you want to use, locate the path to your keypair file and use it as the keypair for the rest of this guide.

    solana-keygen new --outfile ./id.json
  8. Set the Anchor environment variables. Anchor uses these to determine which wallet to use and how to get a connection to a Solana cluster. Because this example does not generate or sign any transactions, no lamports are required. The wallet is required only by the Anchor library. For a list of available networks and endpoints, see the Solana Cluster RPC Endpoints documentation.

    export ANCHOR_PROVIDER_URL=https://api.devnet.solana.com &&
    export ANCHOR_WALLET=./id.json
  9. Copy the sample code into your project. This example queries price data off-chain. By default, the script reads the SOL/USD feed, but you can change the CHAINLINK_FEED_ADDRESS variable to point to the feed account addresses that you want to query. You can take the components of these code samples and integrate them with your existing project. Because these examples read data feeds without making any on-chain changes, no lamports are required to run them.

    /**
     * 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 anchor = require("@project-serum/anchor")
    const chainlink = require("@chainlink/solana-sdk")
    const provider = anchor.AnchorProvider.env()
    
    async function main() {
      anchor.setProvider(provider)
    
      const CHAINLINK_FEED_ADDRESS = "99B2bTijsU6f1GCT73HmdR7HCFFjGMBcPZY6jZ96ynrR"
      const CHAINLINK_PROGRAM_ID = new anchor.web3.PublicKey("cjg3oHmg9uuPsP8D6g29NWvhySJkdYdAo9D25PRbKXJ")
      const feedAddress = new anchor.web3.PublicKey(CHAINLINK_FEED_ADDRESS) //SOL-USD Devnet Feed
    
      //load the data feed account
      let dataFeed = await chainlink.OCR2Feed.load(CHAINLINK_PROGRAM_ID, provider)
      let listener = null
    
      //listen for events agains the price feed, and grab the latest rounds price data
      listener = dataFeed.onRound(feedAddress, (event) => {
        console.log(event.answer.toNumber())
      })
    
      //block execution and keep waiting for events to be emitted with price data
      await new Promise(function () {})
    }
    
    main().then(
      () => process.exit(),
      (err) => {
        console.error(err)
        process.exit(-1)
      }
    )
    
    /**
     * 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.
     */
    
    import * as anchor from "@project-serum/anchor"
    import { OCR2Feed } from "@chainlink/solana-sdk"
    
    async function main() {
      const provider = anchor.AnchorProvider.env()
      anchor.setProvider(provider)
    
      const CHAINLINK_FEED_ADDRESS = "99B2bTijsU6f1GCT73HmdR7HCFFjGMBcPZY6jZ96ynrR"
      const CHAINLINK_PROGRAM_ID = new anchor.web3.PublicKey("cjg3oHmg9uuPsP8D6g29NWvhySJkdYdAo9D25PRbKXJ")
      const feedAddress = new anchor.web3.PublicKey(CHAINLINK_FEED_ADDRESS) //SOL-USD Devnet Feed
    
      //load the data feed account
      let dataFeed = await OCR2Feed.load(CHAINLINK_PROGRAM_ID, provider)
      let listener: null | number = null
    
      //listen for events agains the price feed, and grab the latest rounds price data
      listener = dataFeed.onRound(feedAddress, (event) => {
        console.log(event.answer.toNumber())
      })
    
      //block execution and keep waiting for events to be emitted with price data
      await new Promise(function () {})
    }
    
    main().then(
      () => process.exit(),
      (err) => {
        console.error(err)
        process.exit(-1)
      }
    )
    

    You can run these examples using the following commands:

    node javascript-example.js

To learn more about Solana and Anchor, see the Solana Documentation and the Anchor Documentation.

Using the Solana Starter Kit

This example reads price data from an off-chain client using the Solana Starter Kit.

Install the required tools

Before you begin, set up your environment for development on Solana:

  1. Install Git if it is not already configured on your system.

  2. Install the latest Mainnet version of the Solana CLI and export the path to the CLI:

    sh -c "$(curl -sSfL https://release.solana.com/v1.13.6/install)" &&
    export PATH="~/.local/share/solana/install/active_release/bin:$PATH"

    Run solana --version to make sure the Solana CLI is installed correctly.

    solana --version
  3. Install Node.js 14 or higher. Run node --version to verify which version you have installed:

    node --version
  4. Install Anchor. On some operating systems, you might need to build and install Anchor locally. See the Anchor documentation for instructions.

  5. Install Yarn to simplify package management and run code samples in the Starter Kit.

    npm install -g yarn

Run the example program

After you install the required tools, clone the example code from the solana-starter-kit repository.

  1. In a terminal, clone the solana-starter-kit repository and change to the solana-starter-kit directory:

    git clone https://github.com/smartcontractkit/solana-starter-kit &&
    cd ./solana-starter-kit

    You can see the complete code for the example on GitHub.

  2. In the ./solana-starter-kit directory, install Node.js dependencies defined in the package.json file:

    yarn install
  3. Create a temporary Solana wallet file to use for this example. Because your application runs off-chain and does not run any functions or alter data on-chain, the wallet does not require any SOL tokens to function.

    solana-keygen new --outfile ./id.json
  4. Set the Anchor environment variables. Anchor uses these to determine which wallet to use and Solana cluster to use. Take note that because we are not generating or signing any transactions, the wallet isn't used, it's just required by the Anchor library. For a list of available networks and endpoints, see the Solana Cluster RPC Endpoints documentation.

    export ANCHOR_PROVIDER_URL=https://api.devnet.solana.com &&
    export ANCHOR_WALLET=./id.json
  5. Run the example:

    node read-data.js

    The example code retrieves and prints the current price feed data until you close the application:

    4027000000
    4026439929
    4026476542
    4023000000

To learn more about Solana and Anchor, see the Solana Documentation and the Anchor Documentation.

What's next

Stay updated on the latest Chainlink news