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.
Available data feeds on Stellar
The following table shows all available data feeds on Stellar. Each feed is identified by its data_id (the Feed ID), which you pass to the proxy contract to read that feed's data.
Networks
Stellar Mainnet
Unlike EVM chains, Stellar uses a single proxy contract for all feeds. Instead of a per-feed contract address, you select a feed by its feed ID (data_id) shown below. See the Using Data Feeds on Stellar guide to learn how to read these feeds.
- Data Feeds proxy contract on Stellar Mainnet: CDQBHEUGLDHMSUHG4IH33RJBUTMNCZOT4JIAQR4WZFRDZW6DR6S32ZLZ
Prerequisites
Before you begin, you should have:
- Familiarity with Stellar and Soroban smart contracts
- Understanding of how Chainlink Data Feeds on Stellar work, including the
data_idaddressing scheme
Requirements
To complete this guide, you'll need:
-
Stellar CLI: Install the Stellar CLI. Run
stellar --versionto verify your installation. -
Node.js 18 or higher: Install Node.js. Run
node --versionto verify your installation.
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 proxy contract using the stellar contract invoke command with the --send=no flag. This does not submit a transaction and requires no XLM.
The proxy contract exposes a latest_round function that takes a data_id and a decimals parameter, and returns the most recent round for that feed. You pass the data_id as raw hex (without the 0x prefix), and 18 for the decimals parameter unless the feed is served at a reduced precision.
-
Run the following command, replacing
<SOURCE_ACCOUNT>with any Stellar account public key. The proxy contract on Stellar Testnet isCBUF6IADAWPWIDWRTHJNINKXHG2UTIQ6TU2F2HRAXWAI7OT3KJPKK6O4, and the BTC/USDdata_idis01a0b4d920000332000000000000000000000000000000000000000000000000:stellar contract invoke \ --id CBUF6IADAWPWIDWRTHJNINKXHG2UTIQ6TU2F2HRAXWAI7OT3KJPKK6O4 \ --source-account <SOURCE_ACCOUNT> \ --network testnet \ --send=no \ -- latest_round \ --data_id "01a0b4d920000332000000000000000000000000000000000000000000000000" \ --decimals 18Expect an output similar to the following:
{"answer":"84421629086034400000000","round_id":96,"timestamp":1790274329}Where:
answeris the latest BTC/USD price with 18 decimal places (84421629086034400000000= 84421.63).round_idis the unique identifier of the round.timestampis the observation timestamp in Unix seconds when the answer was produced.
You can find the
data_idfor 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.
-
Create a new directory for your project and initialize it:
mkdir stellar-offchain && cd stellar-offchain && npm init -y -
Install the Stellar JavaScript SDK:
npm install @stellar/stellar-sdk -
Create a
read-feed.jsfile with the following contents. This script queries the proxy contract'slatest_roundfunction for a givendata_id:const { contract } = require("@stellar/stellar-sdk") const proxy = "CBUF6IADAWPWIDWRTHJNINKXHG2UTIQ6TU2F2HRAXWAI7OT3KJPKK6O4" const dataId = "01a0b4d920000332000000000000000000000000000000000000000000000000" async function readLatestRound() { const client = await contract.Client.from({ contractId: proxy, rpcUrl: "https://soroban-testnet.stellar.org", networkPassphrase: "Test SDF Network ; September 2015", }) const result = await client.latest_round({ data_id: Buffer.from(dataId, "hex"), decimals: 18 }) const round = result.result.value console.log("Latest round:", { round_id: round.round_id.toString(), answer: round.answer.toString(), timestamp: round.timestamp.toString(), }) } readLatestRound().catch(console.error)The
data_idargument is a 32-byte value, passed as aBufferobject. Thedecimalsargument is required and requests the precision at which the answer is returned; pass18unless the feed is served at a reduced precision. Thelatest_roundfunction returns aRoundobject wrapped in anOkvalue, so you access it withresult.result.value. -
Run the script:
node read-feed.jsExpect an output similar to the following:
Latest round: { round_id: '96', answer: '84421629086034400000000', timestamp: '1790274329' }Where
answeris the latest BTC/USD price with 18 decimal places (84421629086034400000000= 84421.63).