Using Data Feeds Offchain (Stellar)

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 Stellar Testnet offchain using a Soroban RPC simulation with the Stellar CLI and the Stellar JavaScript SDK. To learn how to use Data Feeds in your onchain Soroban contracts, see the Using Data Feeds Onchain guide.

To get the full list of Chainlink Data Feeds on Stellar, see the Price Feed Contract Addresses page with Stellar selected.

Requirements

Make sure you have the Stellar CLI installed. You can run stellar --version in your terminal to verify if the CLI is correctly installed.

You also need Node.js 18 or higher to run the JavaScript SDK example.

Read a feed with the Stellar CLI

You can read a Chainlink Data Feed offchain without deploying a contract by simulating a call to the cache contract using the stellar contract invoke command with the --send=no flag. This does not submit a transaction and requires no XLM.

The cache contract exposes a batched latest_round function that takes a vector of data_ids and returns a round for each. You pass the data_id as raw hex (without the 0x prefix).

  1. Run the following command, replacing <SOURCE_ACCOUNT> with any Stellar account public key. The cache contract on Stellar Testnet is CAVLZXJDRGOS6UZ7BHYTYW7STQMZIOCUJIVRMT7JE7T5F6JIA3LPAOVW, and the BTC/USD data_id is 01a0b4d920000332000000000000000000000000000000000000000000000000:

    stellar contract invoke \
    --id CAVLZXJDRGOS6UZ7BHYTYW7STQMZIOCUJIVRMT7JE7T5F6JIA3LPAOVW \
    --source-account <SOURCE_ACCOUNT> \
    --network testnet \
    --send=no \
    -- latest_round \
    --data_ids '["01a0b4d920000332000000000000000000000000000000000000000000000000"]'
    

    Expect an output similar to the following:

    [{"answer":"85965450000000000000000","ledger_seq":4795545,"primary":true,"round_id":47,"timestamp":1790001299}]
    

    Where:

    • answer is the latest BTC/USD price with 18 decimal places (85965450000000000000000 = 85965.45).
    • round_id is the unique identifier of the round.
    • timestamp is the Unix timestamp in seconds when the round was recorded.
    • ledger_seq is the Stellar ledger sequence at which the round was recorded.
    • primary indicates whether the round is the primary round for the feed.

    You can pass multiple data_ids in the array to read several feeds in one call. You can find the data_id for each feed on the Price Feed Contract Addresses page with Stellar selected.

Read a feed with the Stellar JavaScript SDK

You can also read a Chainlink Data Feed offchain using the Stellar JavaScript SDK with a Soroban RPC query. This example uses the contract.Client API available in SDK v17 and later.

  1. Create a new directory for your project and initialize it:

    mkdir stellar-offchain && cd stellar-offchain && npm init -y
    
  2. Install the Stellar JavaScript SDK:

    npm install @stellar/stellar-sdk
    
  3. Create a read-feed.js file with the following contents. This script queries the cache contract's latest_round function for a given data_id:

    const { contract } = require("@stellar/stellar-sdk")
    
    const cache = "CAVLZXJDRGOS6UZ7BHYTYW7STQMZIOCUJIVRMT7JE7T5F6JIA3LPAOVW"
    const dataId = "01a0b4d920000332000000000000000000000000000000000000000000000000"
    
    async function readLatestRound() {
      const client = await contract.Client.from({
        contractId: cache,
        rpcUrl: "https://soroban-testnet.stellar.org",
        networkPassphrase: "Test SDF Network ; September 2015",
      })
      const result = await client.latest_round({ data_ids: [Buffer.from(dataId, "hex")] })
      const round = result.result.value[0]
      console.log("Latest round:", {
        round_id: round.round_id.toString(),
        answer: round.answer.toString(),
        timestamp: round.timestamp.toString(),
        ledger_seq: round.ledger_seq,
        primary: round.primary,
      })
    }
    
    readLatestRound().catch(console.error)
    

    The data_ids argument is an array of 32-byte values, passed as Buffer objects. The latest_round function returns a vector of rounds, one per requested data_id.

  4. Run the script:

    node read-feed.js
    

    Expect an output similar to the following:

    Latest round: {
      round_id: '47',
      answer: '85965450000000000000000',
      timestamp: '1790001299',
      ledger_seq: 4795545,
      primary: true
    }
    

    Where answer is the latest BTC/USD price with 18 decimal places (85965450000000000000000 = 85965.45).

What's next

Get the latest Chainlink content straight to your inbox.