# https://docs.chain.link/data-streams llms-full.txt
## Chainlink Data Streams
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Chainlink Data Streams](https://docs.chain.link/data-streams\#overview)
Chainlink Data Streams delivers low-latency market data offchain, which you can verify onchain. This approach provides decentralized applications (dApps) with on-demand access to high-frequency market data backed by decentralized, fault-tolerant, and transparent infrastructure.
Traditional push-based oracles update onchain data at set intervals or when certain price thresholds are met. In contrast, Chainlink Data Streams uses a pull-based design that preserves trust-minimization with onchain verification.
## [Sub-Second Data and Commit-and-Reveal](https://docs.chain.link/data-streams\#sub-second-data-and-commit-and-reveal)
Chainlink Data Streams supports sub-second data resolution for latency-sensitive use cases by retrieving data only when needed. You can combine the data with any transaction in near real time. A “commit-and-reveal” approach mitigates frontrunning by making trade data and stream data visible atomically on-chain.
## [Comparison to push-based oracles](https://docs.chain.link/data-streams\#comparison-to-push-based-oracles)
Chainlink's push-based oracles regularly publish price data onchain. By contrast, Chainlink Data Streams relies on a pull-based design, letting you retrieve a report and verify it onchain whenever you need it. Verification confirms that the decentralized oracle network (DON) agreed on and signed the data. Some applications only need onchain data at fixed intervals, which suits push-based oracles. However, others require higher-frequency updates and lower latency. Pull-based oracles meet these needs and still provide cryptographic guarantees about data accuracy.

Pull-based oracles also operate more efficiently by retrieving data only when necessary. For example, a decentralized exchange might fetch a Data Streams report and verify it onchain only when a user executes a trade, rather than continuously pushing updates that might not be immediately used.
## [Comprehensive market insights](https://docs.chain.link/data-streams\#comprehensive-market-insights)
Chainlink Data Streams offers price points such as mid prices and [Liquidity-Weighted Bid and Ask](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices) (LWBA) for Crypto Streams. LWBA prices reflect current order book conditions, providing deeper insight into market liquidity and depth. With additional parameters, such as volatility and liquidity metrics, Data Streams helps protocols enhance trading accuracy, improve onchain risk management, and dynamically adjust margins or settlement conditions in response to real-time market shifts.
## [High availability and resilient infrastructure](https://docs.chain.link/data-streams\#high-availability-and-resilient-infrastructure)
Data Streams API services use an [active-active multi-site deployment](https://docs.chain.link/data-streams/architecture#active-active-multi-site-deployment) model across multiple distributed and isolated origins. This architecture ensures continuous operations even if one origin fails, delivering robust fault tolerance and high availability.
## [Use cases](https://docs.chain.link/data-streams\#use-cases)
Access to low-latency, high-frequency data enables a variety of onchain applications:
- **Perpetual Futures:** Sub-second data and frontrunning mitigation allow onchain perpetual futures protocols to compete with centralized exchanges on performance while retaining transparency and decentralization.
- **Options:** Pull-based oracles provide timely settlement of options contracts with the added benefit of market liquidity data to support dynamic onchain risk management.
- **Prediction Markets:** High-frequency updates let participants act on real-time data, ensuring quick reactions to events and accurate settlement.
## [Data Streams implementations](https://docs.chain.link/data-streams\#data-streams-implementations)
### [Streams Trade](https://docs.chain.link/data-streams\#streams-trade)
Streams Trade combines Chainlink Data Streams with Chainlink Automation to deliver automated trade execution with frontrunning mitigation. This approach suits dApps that require automated, trust-minimized trade execution and high-frequency market data. Chainlink Automation ensures near-instant onchain access to data while keeping the execution of user transactions fair and reliable.
[Learn more about Streams Trade](https://docs.chain.link/data-streams/streams-trade)
### [Streams Direct](https://docs.chain.link/data-streams\#streams-direct)
Streams Direct provides direct access to Data Streams through SDKs and APIs. This solution suits applications that need programmatic data retrieval and verification, whether for offchain display or onchain settlement. It delivers high-frequency, low-latency data for any custom use case.
[Learn more about Streams Direct](https://docs.chain.link/data-streams/streams-direct)
## What's next
- [\> Learn how to retrieve Data Streams reports with the Streams Trade implementation](https://docs.chain.link/data-streams/getting-started)
- [\> Learn how to fetch and decode Data Streams reports with the Streams Direct API](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api)
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
- [\> Find the schema of data to expect from Data Streams reports](https://docs.chain.link/data-streams/reference/report-schema)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Data Streams Billing
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Data Streams Billing](https://docs.chain.link/data-streams/billing\#overview)
You pay to verify reports from Data Streams onchain using the verifier contract. You pay per report verified. If you verify multiple reports in a batch, you pay for all of the reports included in that batch.
The verification price is 0.35 USD per report. Chainlink Data Streams supports fee payments in LINK and in alternative assets, which currently includes native blockchain gas tokens and their ERC20-wrapped version. Payments made in alternative assets have a 10% surcharge when compared to LINK payments.
[Contact us](https://chainlinkcommunity.typeform.com/datastreams?#ref_id=docs) to learn more about Mainnet pricing.
## What's next
- [\> Learn the basics about how to retrieve Data Streams reports in the Getting Started guide.](https://docs.chain.link/data-streams/getting-started)
- [\> Find the list of available Stream IDs.](https://docs.chain.link/data-streams/crypto-streams)
- [\> Find the schema of data to expect from Data Streams reports.](https://docs.chain.link/data-streams/reference/report-schema)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Data Streams Architecture
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Data Streams Architecture](https://docs.chain.link/data-streams/architecture\#overview)
## [High Level Architecture](https://docs.chain.link/data-streams/architecture\#high-level-architecture)
Chainlink Data Streams has the following core components:
- **A Chainlink Decentralized Oracle Network (DON):** This DON operates similarly to the DONs that power [Chainlink Data Feeds](https://docs.chain.link/data-feeds), but the key difference is that it signs and delivers reports to the Chainlink Data Streams Aggregation Network rather than delivering answers onchain directly. This allows the Data Streams DON to deliver reports more frequently for time-sensitive applications. Nodes in the DON retrieve data from many different data providers, reach a consensus about the median price of an asset, sign a report including that data, and deliver the report to the Data Streams Aggregation Network.
- **The Chainlink Data Streams Aggregation Network:** The Data Streams Aggregation Network stores the signed reports and makes them available for retrieval. The network uses an [active-active multi-site deployment](https://docs.chain.link/data-streams/architecture#active-active-multi-site-deployment) to ensure high availability and robust fault tolerance by operating multiple active sites in parallel. The network delivers these reports to Chainlink Automation upon request ( [Streams Trade](https://docs.chain.link/data-streams/architecture#streams-trade-architecture)) or provide direct access via the API ( [Streams Direct](https://docs.chain.link/data-streams/architecture#streams-direct-architecture)).
- **The Chainlink Verifier Contract:** This contract verifies the signature from the DON to cryptographically guarantee that the report has not been altered from the time that the DON reached consensus to the point where you use the data in your application.
## [Streams Trade Architecture](https://docs.chain.link/data-streams/architecture\#streams-trade-architecture)
Using Chainlink Automation with Data Streams automates trade execution and mitigates frontrunning by executing the transaction before the data is recorded onchain. Chainlink Automation requests data from the Data Streams Aggregation Network. It executes transactions only in response to the data and the verified report, so the transaction is executed correctly and independently from the decentralized application itself.

### [Example trading flow using Streams Trade](https://docs.chain.link/data-streams/architecture\#example-trading-flow-using-streams-trade)
One example of how to use Data Streams with Automation is in a decentralized exchange. An example flow might work using the following process:

1. A user initiates a trade by confirming an `initiateTrade` transaction in their wallet.
2. The onchain contract for the decentralized exchange responds by emitting a [log trigger](https://docs.chain.link/chainlink-automation/concepts/automation-concepts#upkeeps-and-triggers) event.
3. The Automation upkeep monitors the contract for the event. When Automation detects the event, it runs the `checkLog` function specified in the upkeep contract. The upkeep is defined by the decentralized exchange.
4. The `checkLog` function uses a `revert` with a custom error called `StreamsLookup`. This approach aligns with [EIP-3668](https://eips.ethereum.org/EIPS/eip-3668#use-of-revert-to-convey-call-information) and conveys the required information through the data in the `revert` custom error.
5. Automation monitors the `StreamsLookup` custom error that triggers Data Streams to process the offchain data request. Data Streams then returns the requested signed report in the `checkCallback` function for Automation.
6. Automation passes the report to the Automation Registry, which executes the `performUpkeep` function defined by the decentralized exchange. The report is included as a variable in the `performUpkeep` function.
7. The `performUpkeep` function calls the `verify` function on the Data Streams onchain verifier contract and passes the report as a variable.
8. The verifier contract returns a `verifierResponse` bytes value to the upkeep.
9. If the response indicates that the report is valid, the upkeep executes the user's requested trade. If the response is invalid, the upkeep rejects the trade and notifies the user.
This is one example of how you can combine Data Streams and Automation, but the systems are highly configurable. You can write your own log triggers or [custom logic triggers](https://docs.chain.link/chainlink-automation/guides/register-upkeep) to initiate Automation upkeeps for a various array of events. You can configure the `StreamsLookup` to retrieve multiple reports. You can configure the `performUpkeep` function to perform a wide variety of actions using the report.
Read the [Getting Started](https://docs.chain.link/data-streams/getting-started) guide to learn how to build your own smart contract that retrieves reports from Data Streams using the Streams Trade implementation.
**Note**: Before implementing Streams Trade, ensure that Chainlink Automation is available on your desired network by checking the [Automation Supported Networks page](https://docs.chain.link/chainlink-automation/overview/supported-networks).
## [Streams Direct Architecture](https://docs.chain.link/data-streams/architecture\#streams-direct-architecture)
### [Example of offchain price updates with Streams Direct](https://docs.chain.link/data-streams/architecture\#example-of-offchain-price-updates-with-streams-direct)
Streams Direct enables seamless offchain price updates through a mechanism designed for real-time data delivery. Here is an example of how your Client will benefit from low-latency market data directly from the Data Streams Aggregation Network.
1. The Client opens a WebSocket connection to the Data Streams Aggregation Network to subscribe to new reports with low latency.
2. The Data Streams Aggregation Network streams price reports via WebSocket, which gives the Client instant access to updated market data.
3. The Client stores the price reports in a cache for quick access and use, which preserves data integrity over time.
4. The Client regularly queries the Data Streams Aggregation Network for any missed reports to ensure data completeness.
5. The Aggregation Network sends back an array of reports to the Client.
6. The Client updates its cache to backfill any missing reports, ensuring the data set remains complete and current.

## [Active-Active Multi-Site Deployment](https://docs.chain.link/data-streams/architecture\#active-active-multi-site-deployment)
Active-active is a system configuration strategy where redundant systems remain active simultaneously to serve requests. Incoming requests are distributed across all active resources and load-balanced to provide high availability, scalability, and fault tolerance. This strategy is the opposite of active-passive where a secondary system remains inactive until the primary system fails.
The Data Streams API services use an active-active setup as a highly available and resilient architecture across multiple distributed and fully isolated origins. This setup ensures that the services are operational even if one origin fails, which provides robust fault tolerance and high availability. This configuration applies to both the [REST API](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api) and the [WebSocket API](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws). A global load balancer seamlessly manages the system to provide automated and transparent failovers. For advanced use cases, the service publishes available origins using HTTP headers, which enables you to interact directly with specific origin locations if necessary.
### [Active-Active Setup](https://docs.chain.link/data-streams/architecture\#active-active-setup)
The API services are deployed across multiple distributed data centers. Each active deployment is fully isolated and capable of handling requests independently. This redundancy ensures that the service can withstand the failure of any single site without interrupting service availability.
### [Global Load Balancer](https://docs.chain.link/data-streams/architecture\#global-load-balancer)
A global load balancer sits in front of the distributed deployments. The load balancer directs incoming traffic to the healthiest available site based on real-time health checks and observed load.
- **Automated Failover:** In the event of a site failure, traffic is seamlessly rerouted to operational sites without user intervention.
- **Load Distribution:** Requests are balanced across all active sites to optimize resource usage and response times.
### [Origin Publishing](https://docs.chain.link/data-streams/architecture\#origin-publishing)
To enable advanced interactions, the service includes the origin information for all of the available origins in the HTTP headers of API responses. This feature allows customers to explicitly target specific deployments if desired. It also allows for concurrent WebSocket consumption from multiple sites, ensuring fault tolerant WebSocket subscriptions, low-latency, and minimized risk of report gaps.
### [Example Failover Scenarios](https://docs.chain.link/data-streams/architecture\#example-failover-scenarios)
Automatic failover handles availability and traffic routing in the following scenarios:
- **Automatic Failover:** If one of the origins becomes unavailable, the global load balancer automatically reroutes traffic to the next available origin. This process is transparent to the user and ensures uninterrupted service. During automatic failover, WebSockets experience a reconnect. Failed REST requests must be retried.
- **Manual Traffic Steering:** If you want to bypass the load balancer and target a specific site, you can use the origin headers to direct your requests. This manual targeting does not affect the automated failover capabilities provided by the load balancer, so a request will succeed even if the specified origin is unavailable.
- **Multi-origin concurrent WebSocket subscriptions:** In order to maintain a highly available and fault tolerant report stream, you can subscribe to up to two available origins simultaneously. This compares the latest consumed timestamp for each stream and discards duplicate reports before merging the report stream locally.
## What's next
- [\> Find the list of available Stream IDs.](https://docs.chain.link/data-streams/crypto-streams)
- [\> Find the schema of data to expect from Data Streams reports.](https://docs.chain.link/data-streams/reference/report-schema)
## Get the latest Chainlink content straight to your inbox.
Email Address
[iframe](https://td.doubleclick.net/td/rul/346357746?random=1746471455772&cv=11&fst=1746471455772&fmt=3&bg=ffffff&guid=ON&async=1&gcl_ctr=1>m=45be5510v891173849z8847174275za201zb882454074&gcd=13l3l3l3l1l1&dma=0&tag_exp=101509156~103101747~103101749~103116025~103200001~103233424~103251618~103251620~103252644~103252646&ptag_exp=101509156~103101750~103101752~103116026~103200004~103233424~103251618~103251620~103252644~103252646&u_w=1280&u_h=1024&url=https%3A%2F%2Fdocs.chain.link%2Fdata-streams%2Farchitecture&label=_duuCKn_k4cYEPL_k6UB&hn=www.googleadservices.com&frm=0&tiba=Data%20Streams%20Architecture%20%7C%20Chainlink%20Documentation&value=0&bttype=purchase&npa=0&pscdl=noapi&auid=523693848.1746471455&uaa=x86&uab=64&uafvl=Chromium%3B136.0.7103.59%7CGoogle%2520Chrome%3B136.0.7103.59%7CNot.A%252FBrand%3B99.0.0.0&uamb=0&uam=&uap=Linux%20x86_64&uapv=6.6.72&uaw=0&fledge=1&capi=1&_tu=Cg&ct_cookie_present=0)
## Chainlink Data Streams
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Interfaces](https://docs.chain.link/data-streams/reference/interfaces\#overview)
Data Streams require several interfaces in order to retrieve and verify reports.
- Automation interfaces:
- [StreamsLookupCompatibleInterface](https://docs.chain.link/chainlink-automation/reference/automation-interfaces#streamslookupcompatibleinterface)
- [ILogAutomation](https://docs.chain.link/chainlink-automation/reference/automation-interfaces#ilogautomation)
- Data Streams interfaces:
- IVerifierProxy
- IReportHandler
In the current code example for using Data Streams with Automation, these interfaces are specified in the example itself. Imports for these interfaces will be available in the future.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Common} from "@chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol";
import {StreamsLookupCompatibleInterface} from "@chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol";
import {ILogAutomation, Log} from "@chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol";
import {IRewardManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol";
import {IVerifierFeeManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol";
import {IERC20} from "@chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol";
/**
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE FOR DEMONSTRATION PURPOSES.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
// Custom interfaces for IVerifierProxy and IFeeManager
interface IVerifierProxy {
/**
* @notice Verifies that the data encoded has been signed.
* correctly by routing to the correct verifier, and bills the user if applicable.
* @param payload The encoded data to be verified, including the signed
* report.
* @param parameterPayload Fee metadata for billing. For the current implementation this is just the abi-encoded fee token ERC-20 address.
* @return verifierResponse The encoded report from the verifier.
*/
function verify(
bytes calldata payload,
bytes calldata parameterPayload
) external payable returns (bytes memory verifierResponse);
function s_feeManager() external view returns (IVerifierFeeManager);
}
interface IFeeManager {
/**
* @notice Calculates the fee and reward associated with verifying a report, including discounts for subscribers.
* This function assesses the fee and reward for report verification, applying a discount for recognized subscriber addresses.
* @param subscriber The address attempting to verify the report. A discount is applied if this address
* is recognized as a subscriber.
* @param unverifiedReport The report data awaiting verification. The content of this report is used to
* determine the base fee and reward, before considering subscriber discounts.
* @param quoteAddress The payment token address used for quoting fees and rewards.
* @return fee The fee assessed for verifying the report, with subscriber discounts applied where applicable.
* @return reward The reward allocated to the caller for successfully verifying the report.
* @return totalDiscount The total discount amount deducted from the fee for subscribers
*/
function getFeeAndReward(
address subscriber,
bytes memory unverifiedReport,
address quoteAddress
) external returns (Common.Asset memory, Common.Asset memory, uint256);
function i_linkAddress() external view returns (address);
function i_nativeAddress() external view returns (address);
function i_rewardManager() external view returns (address);
}
contract StreamsUpkeep is ILogAutomation, StreamsLookupCompatibleInterface {
error InvalidReportVersion(uint16 version); // Thrown when an unsupported report version is provided to verifyReport.
/**
* @dev Represents a data report from a Data Streams stream for v3 schema (crypto streams).
* The `price`, `bid`, and `ask` values are carried to either 8 or 18 decimal places, depending on the stream.
* For more information, see https://docs.chain.link/data-streams/crypto-streams and https://docs.chain.link/data-streams/reference/report-schema
*/
struct ReportV3 {
bytes32 feedId; // The stream ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median price (8 or 18 decimals).
int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation (8 or 18 decimals).
int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation (8 or 18 decimals).
}
/**
* @dev Represents a data report from a Data Streams stream for v4 schema (RWA streams).
* The `price` value is carried to either 8 or 18 decimal places, depending on the stream.
* The `marketStatus` indicates whether the market is currently open. Possible values: `0` (`Unknown`), `1` (`Closed`), `2` (`Open`).
* For more information, see https://docs.chain.link/data-streams/rwa-streams and https://docs.chain.link/data-streams/reference/report-schema-v4
*/
struct ReportV4 {
bytes32 feedId; // The stream ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median benchmark price (8 or 18 decimals).
uint32 marketStatus; // The DON's consensus on whether the market is currently open.
}
struct Quote {
address quoteAddress;
}
IVerifierProxy public verifier;
address public FEE_ADDRESS;
string public constant DATASTREAMS_FEEDLABEL = "feedIDs";
string public constant DATASTREAMS_QUERYLABEL = "timestamp";
int192 public lastDecodedPrice;
// This example reads the ID for the ETH/USD report.
// Find a complete list of IDs at https://docs.chain.link/data-streams/crypto-streams.
string[] public feedIds = [\
"0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782"\
];
constructor(address _verifier) {
verifier = IVerifierProxy(_verifier);
}
// This function uses revert to convey call information.
// See https://eips.ethereum.org/EIPS/eip-3668#rationale for details.
function checkLog(
Log calldata log,
bytes memory
) external returns (bool upkeepNeeded, bytes memory performData) {
revert StreamsLookup(
DATASTREAMS_FEEDLABEL,
feedIds,
DATASTREAMS_QUERYLABEL,
log.timestamp,
""
);
}
/**
* @notice this is a new, optional function in streams lookup. It is meant to surface streams lookup errors.
* @return upkeepNeeded boolean to indicate whether the keeper should call performUpkeep or not.
* @return performData bytes that the keeper should call performUpkeep with, if
* upkeep is needed. If you would like to encode data to decode later, try `abi.encode`.
*/
function checkErrorHandler(
uint256 /*errCode*/,
bytes memory /*extraData*/
) external pure returns (bool upkeepNeeded, bytes memory performData) {
return (true, "0");
// Hardcoded to always perform upkeep.
// Read the StreamsLookup error handler guide for more information.
// https://docs.chain.link/chainlink-automation/guides/streams-lookup-error-handler
}
// The Data Streams report bytes is passed here.
// extraData is context data from stream lookup process.
// Your contract may include logic to further process this data.
// This method is intended only to be simulated offchain by Automation.
// The data returned will then be passed by Automation into performUpkeep
function checkCallback(
bytes[] calldata values,
bytes calldata extraData
) external pure returns (bool, bytes memory) {
return (true, abi.encode(values, extraData));
}
// function will be performed onchain
function performUpkeep(bytes calldata performData) external {
// Decode the performData bytes passed in by CL Automation.
// This contains the data returned by your implementation in checkCallback().
(bytes[] memory signedReports, bytes memory extraData) = abi.decode(
performData,
(bytes[], bytes)
);
bytes memory unverifiedReport = signedReports[0];
(, /* bytes32[3] reportContextData */ bytes memory reportData) = abi
.decode(unverifiedReport, (bytes32[3], bytes));
// Extract report version from reportData
uint16 reportVersion = (uint16(uint8(reportData[0])) << 8) |
uint16(uint8(reportData[1]));
// Validate report version
if (reportVersion != 3 && reportVersion != 4) {
revert InvalidReportVersion(uint8(reportVersion));
}
// Report verification fees
IFeeManager feeManager = IFeeManager(address(verifier.s_feeManager()));
IRewardManager rewardManager = IRewardManager(
address(feeManager.i_rewardManager())
);
address feeTokenAddress = feeManager.i_linkAddress();
(Common.Asset memory fee, , ) = feeManager.getFeeAndReward(
address(this),
reportData,
feeTokenAddress
);
// Approve rewardManager to spend this contract's balance in fees
IERC20(feeTokenAddress).approve(address(rewardManager), fee.amount);
// Verify the report
bytes memory verifiedReportData = verifier.verify(
unverifiedReport,
abi.encode(feeTokenAddress)
);
// Decode verified report data into the appropriate Report struct based on reportVersion
if (reportVersion == 3) {
// v3 report schema
ReportV3 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV3)
);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
} else if (reportVersion == 4) {
// v4 report schema
ReportV4 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV4)
);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
}
}
}
```
[Open in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/StreamsUpkeep.sol&autoCompile=true) [What is Remix?](https://docs.chain.link/getting-started/conceptual-overview#what-is-remix)
## Get the latest Chainlink content straight to your inbox.
Email Address
[iframe](https://td.doubleclick.net/td/rul/346357746?random=1746471455297&cv=11&fst=1746471455297&fmt=3&bg=ffffff&guid=ON&async=1&gcl_ctr=1>m=45be5521h2v891173849z8847174275za200zb882454074&gcd=13l3l3l3l1l1&dma=0&tag_exp=101509157~103101750~103101752~103116026~103200004~103233427~103251618~103251620~103252644~103252646&ptag_exp=101509157~103101747~103101749~103116025~103130498~103130500~103200001~103233427~103251618~103251620~103252644~103252646&u_w=1280&u_h=1024&url=https%3A%2F%2Fdocs.chain.link%2Fdata-streams%2Freference%2Finterfaces&label=_duuCKn_k4cYEPL_k6UB&hn=www.googleadservices.com&frm=0&tiba=Interfaces%20%7C%20Chainlink%20Documentation&value=0&bttype=purchase&npa=0&pscdl=noapi&auid=462033825.1746471455&uaa=x86&uab=64&uafvl=Chromium%3B136.0.7103.59%7CGoogle%2520Chrome%3B136.0.7103.59%7CNot.A%252FBrand%3B99.0.0.0&uamb=0&uam=&uap=Linux%20x86_64&uapv=6.6.72&uaw=0&ec_mode=a&fledge=1&capi=1&_tu=Cg&em=tv.1&ct_cookie_present=0)
## Crypto Streams Overview
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Data Streams Crypto streams](https://docs.chain.link/data-streams/crypto-streams?page=1\#overview)
To learn how to use Data Streams, see the [Data Streams Getting Started](https://docs.chain.link/data-streams/getting-started) page.
For LINK token and Faucet details, see the [LINK Token Contracts](https://docs.chain.link/resources/link-token-contracts?parent=dataFeeds) page.
## [Streams Verifier Network Addresses](https://docs.chain.link/data-streams/crypto-streams?page=1\#streams-verifier-network-addresses)
Apechain
+
Arbitrum
+
Avalanche
+
Base
+
Berachain
+
Blast
+
BNB Chain
+
Bob
+
Botanix
+
Ethereum
+
Gnosis
+
HashKey Chain
+
Hyperliquid
+
Ink
+
Lens
+
Linea
+
Mantle
+
MegaETH
+
Monad
+
opBNB
+
OP
+
Ronin
+
Scroll
+
Shibarium
+
Soneium
+
Sonic
+
Solana
+
Taiko
+
Unichain
+
World Chain
+
ZKSync
+
## [Mainnet Crypto Streams](https://docs.chain.link/data-streams/crypto-streams?page=1\#mainnet-crypto-streams)
| Stream | Details |
| --- | --- |
| 1INCH/USD | 0x0003fb80bf0e043e7bcc6e9808c9f62e722117afddb2b760ad6c58f6cc614444
Full name:1INCH/USD-RefPrice-DS-Premium-Global-003
Asset name:1inch Network
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AAVE/USD | 0x0003481a2f7fe21c01d427f39035541d2b7a53db9c76234dc36082e6ad6db7f5
Full name:AAVE/USD-RefPrice-DS-Premium-Global-003
Asset name:AAVE
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ACE/USD | 0x000306560d458ac3d101b500e0dd3e4a17e2f41065839e2182f8fd9f74a5a84c
Full name:ACE/USD-RefPrice-DS-Premium-Global-003
Asset name:Fusionist
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ADA/USD | 0x00038580225b924c69e28ea101d4723d90c1b44ab83548a995c3d86ad9e92eb0
Full name:ADA/USD-RefPrice-DS-Premium-Global-003
Asset name:Cardano
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AERO/USD | 0x00038458999fd77d9deece17154ee687193b328cf7a53670501dd8ccad906ff6
Full name:AERO/USD-RefPrice-DS-Premium-Global-003
Asset name:Aerodrome Finance
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AEVO/USD | 0x00032b4e4b9c9c2aa5a3675628ed71e7682c50b11fe6c7df4cb625510f7732aa
Full name:AEVO/USD-RefPrice-DS-Premium-Global-003
Asset name:Aevo
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AI/USD | 0x0003f5944427d0ea4f638aad72526552ee4b93fc2cafb703421df1d5d2a6816a
Full name:AI/USD-RefPrice-DS-Premium-Global-003
Asset name:Sleepless AI
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AI16Z/USD | 0x0003aa72a9b718ab413209e03abb04233846991294336169fc6a7a03081adb70
Full name:AI16Z/USD-RefPrice-DS-Premium-Global-003
Asset name:ai16z
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
Prev
Showing 1 to 8 of 231 entries
Next
## [Testnet Crypto Streams](https://docs.chain.link/data-streams/crypto-streams?page=1\#testnet-crypto-streams)
| Stream | Details |
| --- | --- |
| 1INCH/USD | 0x00039e3a2f120539378fe688b38581a5740cfa1db8d7df9e5aa58dade9bde8a2
Asset name:1inch Network
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AAVE/USD | 0x0003c8e550d2fc5304993010112de9b69798297e4cc11990ee6250e464daf760
Asset name:AAVE
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ACE/USD | 0x0003eae0c3b5d771005374779c42de0f5dbacc1f940c86e205557a05c6c7103f
Asset name:Fusionist
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ADA/USD | 0x00033470b2bb164a50c5a6fda879ddabcf8fb91fcfca048ac81a6bd5763fa1e3
Asset name:Cardano
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AERO/USD | 0x00033cf9f3040c301dcbfbf6d2827e49dc78e361b947eefe2dd870c86b950ca9
Asset name:Aerodrome Finance
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AEVO/USD | 0x00034eff2911861c2f4a9465862ce553a98657d2097246857d24b989c95064f0
Asset name:Aevo
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AI/USD | 0x000312c72545b1fae56a2695a83ea82bdfc25c63811ebf9ede3650fb37d94060
Asset name:Sleepless AI
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AI16Z/USD | 0x000392a1f1f563887ab7e4e81d67f4f08fecef6c399cc098c5e044d04b30b4f6
Asset name:ai16z
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AIXBT/USD | 0x00035ed1b74dba4751689d69adaa6924e0d17556d8b038c36a419749eaa34973
Asset name:aixbt by Virtuals
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| FTM/USD | 0x0003bdc4ead3b5dde544a0080c525c40ab00e256f04867267ef8cc1ab8b28c44
Asset name:Algorand
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ALT/USD | 0x0003398ed0506420b3e03018937c93c5cb0b059ce0a315167dfea81beda06e7f
Asset name:Altlayer
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| / | 0x0003369f7f042ba1e180cc8d260ba60c53cf786fdc80ec60077a7d4527110859
Asset name:ANIME
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ANKR/USD | 0x0003474e3067d8ad87594f4d368b20f5f170cb037f973a998e3c65c6b79a1225
Asset name:Ankr
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| APE/USD | 0x00035e67fb5b7fda97e43ba4f97983426c16b82a421a43b9f6cc0d136a33ae7d
Asset name:APECoin
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| APT/USD | 0x0003e78d7e9dc688cdc06620629fcd5ee7427f36f8740bea66588596e7dc085e
Asset name:Aptos
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AR/USD | 0x0003f5986c45a49cff2a92d19147dca956c23ced6f809034fdd5df2eac497038
Asset name:Arweave
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ARB/USD | 0x0003c90f4d0e133914a02466e44f3392560c86248925ce651ef8e44f1ec2ef4a
Asset name:Arbitrum
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ARKM/USD | 0x0003f750ef427258f6418fea439a4972ceea5b92d1011f28b4816599e72d368d
Asset name:Arkham
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ASTR/USD | 0x000321a87e74af3dd766d1a5d730d777fad4650e4bdbe13313cefd3f8e060e1f
Asset name:Astra
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ATH/USD | 0x000352feb960e13de30a438c627c573db5ffa93e379d831b40c7969900479ad2
Asset name:Aethir
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ATOM/USD | 0x000325ad17b53e588bc2c9ced633c5444f7291f3d5b071a7ad0ebec8891659e2
Asset name:Cosmos
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AVAX/USD | 0x0003735a076086936550bd316b18e5e27fc4f280ee5b6530ce68f5aad404c796
Asset name:Avalanche
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AXL/USD | 0x00034c281803ce6dadfa74014e5192b7ccfc5131d005a5f9427576cab0407205
Asset name:Axelar
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| AXS/USD | 0x0003d148367c356befdf05efc852e5fcadc7e56a586db3789d62e650bd4a9a19
Asset name:Axie Infinity
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BAL/USD | 0x0003e5103d1148cad083416f0b29d43a656df68b399e7a0ed1deded0e9c4ed1f
Asset name:Balancer
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BAT/USD | 0x00035281da4fff05e7ae0df77961b3bd1ce7867966d2ae298e01c4be87a353f4
Asset name:Basic Attention Token
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BB/USD | 0x0003650fbe3ad3d70afd7882e75470068ecffdc11061bb5d973955b4983ef440
Asset name:BounceBit
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BCH/USD | 0x00038dfa2d0ae0617193210c1e6a4a9c4c263453ecb8147091a9be5a79b6de7f
Asset name:Bitcoin Cash
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BEAM/USD | 0x00037a9777e8310ac58efc758c19c1874c7bd2a464d792d4632afbacb6b5f3b5
Asset name:Beam
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BERA/USD | 0x000376d1131aa62825b57c71399fdbf6d8deb26dd0866f25d441c5d53aeabb15
Asset name:Berachain
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BGB/USD | 0x0003c396c0d80fe96ba00dfe31faded532f1a2ee7c8389e89af245499578367f
Asset name:Bitget Token
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BIGTIME/USD | 0x0003760cfc2bcef4156b2a923f2709cd41b8b27ed2f8f5d3648282a6387b26ec
Asset name:Big Time
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BLAST/USD | 0x0003a42d6d1630d710596b921b798de5c8d06fca8e4e9bdb451654c9d4aa232d
Asset name:Blast
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BLUR/USD | 0x0003e3ee31113681cb710760fc76bba72e3ba91283c92a5d95fa26759c439991
Asset name:Blur
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BNB/USD | 0x000387d7c042a9d5c97c15354b531bd01bf6d3a351e190f2394403cf2f79bde9
Asset name:BNB
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BNSOL/USD | 0x0003a300deb31f0ea6c422058fccd67da24691b3291b1bb1dcdbf6624ff4b9b5
Asset name:Binance Staked SOL
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BOME/USD | 0x000334804e73a610f60a53672839e735e6ed171afb21ff41f3f46033cb7d50ea
Asset name:BOOK OF MEME
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BONE/USD | 0x00035f89075b1474f6784885e98caa531b8115d76671c629dc8b0e78cb9a9b93
Asset name:Bone Shibaswap
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BONK/USD | 0x0003a1da5a2672b83a70fb2c01b93a89c170f5fab3f2b4f67b95dd89b4a763cf
Asset name:Bonk
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BRETT/USD | 0x0003068e97ac1cb3467c765201c1b0b95e1291786f259a9d560498037fcbedbc
Asset name:Brett
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BTC/USD | 0x00037da06d56d083fe599397a4769a042d63aa73dc4ef57709d31e9971a5b439
Asset name:Bitcoin
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| BTT/USD | 0x0003e654f054cc2f1a52e11b31bc373fa9c42dd918bba0708aaacd2111bbaa18
Asset name:BitTorrent
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| C98/USD | 0x00033ab90ca006fea41ae0187577f0fc8fe87de0e94cc39237b33facce3a571e
Asset name:Coin98
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| CAKE/USD | 0x00034e10fa7071a296001846ffe7503d114747de7bfbeae45436476bb2a88c19
Asset name:PancakeSwap
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| CATI/USD | 0x00032491288ac275347f64e5ded7246c6c86a1dc198211c557561b309fc0f66d
Asset name:Catizen
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| CELO/USD | 0x0003a0ac3d5ff355a5bd3d9a8b168ca7d4bf5d70b1a2f3ab17de1d4e417161fc
Asset name:Celo
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| CFX/USD | 0x0003482eace9228ee130e15a6c3cbeb97de80fbb510eee4561230effcd0fa057
Asset name:Conflux
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| CHR/USD | 0x0003f35c936f109e6f832888f7abed2bdd7c02543492e8ac0663c6e6d0b21562
Asset name:Chromia
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| CHZ/USD | 0x00037125729795bb3ec738f3a721213382d928754ec587473670afbfd95fd895
Asset name:Chiliz
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| COMP/USD | 0x00032de845ff83aa5e5bff081b6478305fc5f8bb61561221f975f3d5fb9b88f5
Asset name:Compound
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| COQ/USD | 0x0003db2a5bda4095987fcea41978035d56a039ec4189108745ee1846c3c01339
Asset name:Coq Inu
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| CORE/USD | 0x0003dee64439e1f21803d6e1269741b1e2dcdd19f54133ba7a49c7e46c3a989f
Asset name:Core
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| CRV/USD | 0x00037c41d40228ff337f3c7339e635906bb60552d748654fe6f9ebfa6a83fc0e
Asset name:Curve DAO Token
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| CYBER/USD | 0x00030e319b66ece431917d99ec892abdbd985d89bfa5a541162dedff537a99d0
Asset name:CYBER
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| DAI/USD | 0x0003649272a19e143a7f4c2d98905b413e98dce81fb09287dcf4c513cba5cc72
Asset name:DAI
Asset class:Crypto - Stablecoin
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| DASH/USD | 0x00037950dccc8711f0494d45d7c256676544a74714fc6d52ee923f53900c8f91
Asset name:DASH
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| DODO/USD | 0x00036a2333294f826d58872c1f86934e6cef260199713d488420e674983103b5
Asset name:DODO
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| DOGE/USD | 0x00032057c7f224d0266b4311a81cdc3e38145e36442713350d3300fb12e85c99
Asset name:Dogecoin
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| DOGS/USD | 0x0003279d185cd1960ac86496e7ccaca1422c1878edc44278ac558334ffc5a55a
Asset name:DOGS
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| DOLO/USD | 0x0003a4126bd36a3d72316c2718a98bb285e8ad314902dcf4f5756562d2d0b746
Asset name:Dolomite
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| DOT/USD | 0x0003f87966ed1dfa11732a80d5d3633152f93be3b579c49501279bad15102232
Asset name:Polkadot
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| DRIFT/USD | 0x00037f989bfe95fe3e923231e33105917b79de9b83c80267410c86b29cdef2aa
Asset name:Drift Protocol
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| DUSK/USD | 0x00033ac5ee60621a957e2d97940742bec52b0f77e03853ae8365193a676ab355
Asset name:Dusk
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| DYDX/USD | 0x0003f8e0f04a13e4f469ef7f238f083549c22afbfbac4ef14c8b9c142ab048c9
Asset name:dYdX
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| DYM/USD | 0x00031fa2f26a98e5ea3fae9f995afbfab5ed27307e8bfd4dc5cb3f56d0701838
Asset name:Dymension
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| EDU/USD | 0x0003aa71b97030b8c8e83d78f78e8415cfccea225c551064c40cfa1eca84fe33
Asset name:Open Campus
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| EGLD/USD | 0x00032ad6ca67c3d505a67bd24a0eac6cf1b7fcf3ff4c9f05ec23cbf02d3aa249
Asset name:MultiversX
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| EIGEN/USD | 0x0003b9b77396e9c706cde5b35257da9e47ac7967665057d85590edee322a6b78
Asset name:Eigenlayer
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ENA/USD | 0x0003f04d6244b2fb6bb366b405f63d87fa3550647acbc1c93f9c116df4645772
Asset name:Ethena
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ENS/USD | 0x0003ec61df18ffc997b7e56b58b3cf9e0250a85fff478db19b1689da531a7a81
Asset name:Ethereum Name Service
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| EOS/USD | 0x000315831c3959d4b817c832cc1cc3954387863e7a3fb0028cabdd51ab1b114c
Asset name:Eos
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ETC/USD | 0x00038c2628907d2c35b5dcc7a7d2ad143580261b1b56dcb535828d8e32ee58c6
Asset name:Ethereum Classic
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ETH/USD | 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
Asset name:Ethereum
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ETHFI/USD | 0x000394e70cb2a1e036fe4e0b1b4a53c5fdb0713eff1eee41483757e7a878a9be
Asset name:Ether.fi
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| FARTCOIN/USD | 0x00031f882aba7dd7a82da178cb7cb465d5a5bec9936f28f4eb959fba205aa373
Asset name:Fartcoin
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| FET/USD | 0x00035122398062eea784e25499ffd83a63ca11358569e5e61cfe64543d1c6881
Asset name:Artificial Superintelligence Alliance
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| FIL/USD | 0x000363af8867422027b90720ad9f20e7fee02e5e8f1686a115da29e020e45de2
Asset name:Filecoin
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| FLOKI/USD | 0x0003e35ba9242261003459b8c97933127cdff9b727b9492ab017de9484fdc6b9
Asset name:Floki Inu
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| FLOW/USD | 0x000389f0215ca85f6fc14ac6bf567dfe691838ea1c5f89481dda66c4a39159ec
Asset name:FLOW (dapper labs)
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| FLR/USD | 0x0003022635f1d8a1a419fa39bce3cc1c49068875d66ad74f6cfc6cd99c0a24dd
Asset name:Flare
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| FXS/USD | 0x0003dab9cb8a8519a25bb04db32a8aa8d1b1c6986e720df49db4571f16ad3a22
Asset name:Frax Share
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| GALA/USD | 0x000361a5174a8f49f69804340bca283dfeb7275f3923a86a2fbdf6680354d7f9
Asset name:Gala
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| GMT/USD | 0x00032f5509d6e79cf5c2fd16c2494fa7fa914ff0113c1ac5e0367f2c9ad29c23
Asset name:Stepn
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| GMX/USD | 0x00036bc01bddd458520622f9275d97385d2c47e3ff6fe9ec83ca3c39e62fd0d8
Asset name:GMX
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| GNS/USD | 0x00030fbf24cdecf85ba968da71a954a71588a6be2b267274513f5b2dfca8a7a4
Asset name:Gains Network
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| GOAT/USD | 0x000334c34c551a16f20b60cd43809658f7a1d2e4f73c7970e08045a09bb53c30
Asset name:Goatseus Maximus
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| GRIFFAIN/USD | 0x00039d9c826918e1399afdb9d878f20fa39aeb255000a847bd8182fd509eea80
Asset name:GRIFFAIN
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| GRT/USD | 0x0003b34289d9e313900c2e5a994598665b14c955360a6bb8bb6f8125894daf1c
Asset name:The Graph
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| HBAR/USD | 0x000393df2b8d3fdc6ddd4286db25be18c58506d9a1f79feb6622db19f18e1fa1
Asset name:Hedera Hashgraph
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| HMSTR/USD | 0x0003ed0cf9a08cc2bafa8111ae5372553dea8aeb054ccd1d382ebaae3d0141f0
Asset name:Hamster Kombat
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| HNT/USD | 0x00037f1e5e63866dbc3e87af679111c62e31a6bc7cafb41662f04e2788a11019
Asset name:Helium Network Token
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| HOOK/USD | 0x000302d6552e3b5470256ac49e0a24f26e724fe194d66a01da6155ef00743977
Asset name:Hooked Protocol
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| HOT/USD | 0x00037cb1fa6273af7d260e2b47b41b2fd6d356e58cd0ae583c22bdefaf984735
Asset name:Holo
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| HYPE/USD | 0x0003cbac760d50c462267f3127374f5fa039eb971dd4a58a2b4f2b664769f8ea
Asset name:Hyperliquid
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ICP/USD | 0x000377ac7b6d9c76bb728aacd39179e3e5884cc64b88e0198593e151f771185c
Asset name:Internet Computer Protocol
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ID/USD | 0x000328a3557bdd473dd07adc9829408e2af0c31f4e962e29804e0809a978647b
Asset name:SPACE ID
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ILV/USD | 0x0003b693c8b4d26ebcf3766ae1d59a3c02a7736ae4a4e8cb999fac2ded720d1d
Asset name:Illuvium
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| IMX/USD | 0x0003d4b797096d4861bdc7c9968ed1860498a550c7f30c478f630d72bbbca233
Asset name:Immutable
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| INJ/USD | 0x0003c94e392a52263b47a98d2898cc099eb88c44d25ea694af5e15b93b9cf380
Asset name:Injective Protocol
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| IO/USD | 0x00032e0065a9b72535bd63e8a3680fb63c57d241e253b69598529e62548af8e1
Asset name:io.net
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| IOTX/USD | 0x0003e8a2f576d864eb29b74080ea62011e2285f7ac5dd7a5f9afe5d0ca18842a
Asset name:IoTeX
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| IP/USD | 0x0003193b4360683e43c715862649760db06004d816d24ad54015fe57c813b891
Asset name:Story
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| IQ/USD | 0x0003412f9a8944aab69ca1cf93d3600cf19169794d6671db468c509908836fce
Asset name:IQ
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| JOE/USD | 0x0003666caf3d67a91e6e4e917e90d0cce92229e8ebdb292e6390bde5e2e4f063
Asset name:Trader Joe
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| JTO/USD | 0x000396c6add917a353b365034437f527e2b43e6db586d13c7eaa0c3f819354a9
Asset name:Jito
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| JUP/USD | 0x0003a808fe2efaa5a870c3ca103cdbb31a8ccbf34a10843b6f968d5a3dc57bf3
Asset name:Jupiter
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| KAVA/USD | 0x00037fd67a60c277757f8ab9d95010251466c044250b7afedc385684f5745f32
Asset name:Kava
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| KMNO/USD | 0x00030fe66005315e3d51c4ea239edea04f0e106b4a12ebea8d0c03651ba2e8c1
Asset name:Kamino
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| KSM/USD | 0x00034c3f4f53df1f10ea46aadfbce9695136241d8edaa99da35a343963d07692
Asset name:Kusama
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| LDO/USD | 0x0003fdc62b679158fbd230eb6ef1f350368f5de603af0ea4369bd3940d5312a3
Asset name:Lido DAO
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| LINK/USD | 0x00036fe43f87884450b4c7e093cd5ed99cac6640d8c2000e6afc02c8838d0265
Asset name:Chainlink
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| LISTA/USD | 0x0003caa902df98e2fa41f5fedab9bde12b2884bdce262f4ffada25dad317616f
Asset name:Lista DAO
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| LQTY/USD | 0x0003a6498d7575d5c2054721614f66184a61c6dd3b5073c4ffae2276eb58d131
Asset name:Liquity
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| LTC/USD | 0x0003c915006ba88731510bb995c190e80b5c9cfe8cd8a19aaf00e0ed61d0b3bc
Asset name:LiteCoin
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MANA/USD | 0x00037fb7bd67de87512590c8cce20382152b31329309a335bcff78a3f74689b2
Asset name:Decentraland
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MANTA/USD | 0x0003d88401aac003cf0e68a7787401c23ecf3a84f67439acd07fdbc456329bfe
Asset name:Manta Network
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MAV/USD | 0x0003cd1b6c8577d28360a97f486c74522caf14a56d70ad3230da0abff750cd15
Asset name:Maverick Protocol
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MEME/USD | 0x000342f0cdf6daaf33ffedb7a43e0ba4309e1e9f9521e91d3671cab64a9b0fde
Asset name:Memecoin
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MERL/USD | 0x0003fc55aa2af75a6d136cfd4b3bb7e36ea42ce718d3d5c444a64acb42375f47
Asset name:Merlin Chain
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| METIS/USD | 0x00039775c32cbfa8a21be74c471dcdf813b4f5b4c11850cec7dce3defe6c0a31
Asset name:metis
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MEW/USD | 0x00031d1fa02a2356d253bc6e6429d845012fbc663b9bff5fe27fbb6a6882b82f
Asset name:cat in a dogs world
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MICHI/USD | 0x0003735f9cc25fd52a95584f000085ebd28dd93fc328c10c541388702dbca23c
Asset name:michi
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MINA/USD | 0x0003636754d5a06ce8594072ada3b412f44033ae9766a95e6419b5f26f8ae6e2
Asset name:Mina
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MKR/USD | 0x00039953129f4c0a1e32340ee640b94781344831394694f3fb78a09d9c171947
Asset name:Maker
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MOG/USD | 0x00038ff275ccc4f503b3cdf6f510e222c3eb7753ffda3e8dc4389ebadc4d1be5
Asset name:Mog Coin
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MOODENG/USD | 0x000390435939e60e4bc171cadadaf24129a64bb251442cf8b3b5a629320d98a2
Asset name:Moo Deng
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| MORPHO/USD | 0x000388652164377f56ea1064ef41c3f8646998d241a694b7a06b4c81a4c227c3
Asset name:Morpho
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| NEAR/USD | 0x0003d64b0bdb0046a65e4ebb0a9866215044634524673c65bff4096a197fcff5
Asset name:NEAR Protocol
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| NEIROETH/USD | 0x0003e1499adb55c9ec3e603084e75095f11b6e01cb05d86e330fa93a5b484085
Asset name:Neiro
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| NOT/USD | 0x00032d877bb0afeeb8c03731f989d32025c48394840c4856b5e90cb410051f27
Asset name:Notcoin
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| OM/USD | 0x0003c409d09be7dd14995ac2cc8c6cffba458323563bffc0efe9b68136b656e0
Asset name:MANTRA
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| OMG/USD | 0x0003fdabb1c1113bbae5e5ad653c0b4b65c28bb3962161cc9696f2c63611d825
Asset name:OMG Network
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| OMNI/USD | 0x00033de02f2c025f08eaca30df8f3d416efe4328a9f95355a5c0c32f3bec64d1
Asset name:Omni Network
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ONDO/USD | 0x000380fd590efd03f8368469267e187c251231fcf42bdf4c6ff08f56fe495b71
Asset name:Ondo
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| OP/USD | 0x000305a183fedd7f783d99ac138950cff229149703d2a256d61227ad1e5e66ea
Asset name:Optimism
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ORCA/USD | 0x000350cee2e6bcf70cfc16fa8795ca44ae6a26f98b9dac0b6e56be61ce80cc9d
Asset name:Orca
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ORDER/USD | 0x00032c9876ca5fa80b431a79f1d0f6356220084b14c94c65455a8d3f3aa78757
Asset name:Orderly Network
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ORDI/USD | 0x0003082efd3fb60ac36251d02b7efdc3b1ec5fbe2f93a67f193b51a2e241ae0b
Asset name:ORDI
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| PAXG/USD | 0x00034f89517f4dc9594face46c10c8bbfcf4733822908ebdbc6395d7b3a2e5c8
Asset name:PAX Gold
Asset class:Crypto - Pegged Asset
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| PENDLE/USD | 0x0003eaad4d4b02c2fb606e29db22c5fbbc1ac29ae6e79c4703b924e473abf9fb
Asset name:Pendle
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| PENGU/USD | 0x00038e9b9fe9e6aa44fb43de71d4a24944dcbc0c851b17ef9e96f9055b5a94d0
Asset name:Pudgy Penguins
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| PEOPLE/USD | 0x0003e9677596fe90c40dfc6f59102f621dc9810d534141c65b1bf1634bf3b0f6
Asset name:ConstitutionDAO
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| PEPE/USD | 0x0003c8541bf8517752d466f6efc2057b54a9e189e45f08fa37a4db73452df4d4
Asset name:PEPE
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| PIXEL/USD | 0x000352f097cc90e50daa8f380b199a95d4e6bfb5509d4496c74947a402ec09bb
Asset name:Pixels
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| PNUT/USD | 0x00034b48959304994306fa2df9e0ed1f4f2004381377ab8a0a0eaee828ebc7c7
Asset name:Peanut the Squirrel
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| POL/USD | 0x0003675e8721a97b94f3ed48cbec8c7990ddeea9608e8823e22d5566b6592529
Asset name:Polygon
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| POLYX/USD | 0x0003a63b444bcac04bc1b446216c5317e67dadb89cdacc38b93db022e31635c5
Asset name:Polymesh
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| PONKE/USD | 0x0003a3793bda07a36ed196db0445a7cb77dcbf3c9b94f7881b125f1b61fb38a3
Asset name:PONKE
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| POPCAT/USD | 0x0003fd87f5c75aa038a93563a4a0f4989af98541ebf692cde20a2b519d52d98f
Asset name:POPCAT
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| PYTH/USD | 0x0003e643b756a52041254937f3fb9655e87cdc74ed961b19a4e00a478852adb4
Asset name:Pyth Network
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| PYUSD/USD | 0x000359c3cb7a49be8a9b88c3358f507e8c76cffeec105881cd3bbb4511b31a79
Asset name:PayPal USD
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| QNT/USD | 0x000357bf3c6333bbbcc8030d821b13b6de8f4fd04abbc9955c8f40ea97c3ca9e
Asset name:Quant
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| QTUM/USD | 0x00036efb51b6b0b4073e95bbb78c49baab58c4d77175905b333495aa348f8b1c
Asset name:Qtum
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| RAY/USD | 0x0003591f81db04a6862ec09a1e55d3d0f92adba40de36527094e52d19eb8f338
Asset name:Raydium
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| RDNT/USD | 0x0003da1dfac0c568049f39060450ff74425b5ee63fd0a0e27a8b78ee585bf5df
Asset name:Radiant Capital
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| RENDER/USD | 0x0003ea9ea9bd6d9ce89165185d25d02e606aece110d3897516f4d629433944ff
Asset name:Render
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| REZ/USD | 0x00034a349348320221a9865fa61e85a4baac1936c79b2440440f6899d84985c3
Asset name:Renzo
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| S/USD | 0x00036b6fe24c00d5891b1dcee9d7d90f3e0b562a632d0cacdc364406f8b4878f
Asset name:Sonic
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SAND/USD | 0x0003848ff7303b5cfb231e7f2f58abe8a0cb5db5f861b8cb99c7ab8969c69566
Asset name:The Sandbox
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SATS/USD | 0x000396dc3ebaac7b01a0b3ec04aad5d90f7f98bafbae08cdbf62009c333ab5d0
Asset name:SATS (Ordinals)
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SCR/USD | 0x00032a7b88d38a154bc125fe5a1f7be291ac9a7ece982ae9c3be4de996404a64
Asset name:Scroll
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SEI/USD | 0x0003dba2d8553dfd7afe35c2bfe217ef5106d7805e5272c04a08940ddb868117
Asset name:Sei
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SHIB/USD | 0x0003e5dfcb9c8fda20285c89ab6b289926b17dde5e704a1c228a8b468913f56a
Asset name:Shiba Inu
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SKL/USD | 0x00034251eaee85f8e8c53e03d13825f1a8c5a9a96132c18770834dd37821fcfe
Asset name:SKALE
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SNX/USD | 0x000316d1e1fefaba71033e214c79b1f7c3442cdbde7f9f267748bfc005fdf5af
Asset name:Synthetix Network
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SOL/USD | 0x0003d338ea2ac3be9e026033b1aa601673c37bab5e13851c59966f9f820754d6
Asset name:Solana
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SPX/USD | 0x00035b6d827b855f3f5b9cb3954e990851cc3c08b7d21cdbb7a7436f268fa474
Asset name:SPX6900
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| STG/USD | 0x0003f90741ae620f25bd64ced0dd136f91290225829f4058639ab2b91cf7bd26
Asset name:Stargate Finance
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| STORJ/USD | 0x0003223b5871055e8b47575c63ac89b7e17efcf57cdc53bd35603bc9077e98bd
Asset name:Storj
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| STRK/USD | 0x0003eb58aa670ff9c8ed2c36df4733012d87d373c59020b42fdbe0e78161ef9e
Asset name:Starknet
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| STX/USD | 0x0003d63e80ff4a4db92a06e3490ba30ab01dadcc082bb39735ee9c37802078dc
Asset name:Stacks
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SUI/USD | 0x00034881db604b551ff226aa414ba73dd5b2be0a06834124dafa9bf66871ce89
Asset name:Sui
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SUSHI/USD | 0x00033b3d46366619564d8d43d339874ea4a2b0e3dec7eee35687951263d45112
Asset name:Sushi
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| SYN/USD | 0x0003b1267e14217710860fa35289098cb8c19b76bc5f4f34e6c30621c00501fb
Asset name:Synapse
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| TAO/USD | 0x00039bacff0b43ef3cb1bffa0cb2bcc403b2349a3db41ecd656dfaff9dfa7d4b
Asset name:Bittensor
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| TIA/USD | 0x00036173437e26ef8dc971c19070b2c05f6575bdb484c2c45e06e99fec290bd2
Asset name:Celestia
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| TNSR/USD | 0x0003ac344d8854481d0214b23b34165b0dab71f05b595d52e1565c7e0cea7e85
Asset name:Tensor
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| TOKEN/USD | 0x000344b4993ccdc50f2c78a7929f8b4ad1ce2adc1afd48a34182738f09c075e8
Asset name:TokenFi
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| TON/USD | 0x0003167e54377caae2bdbefbefabb839916ed73e70468519a3b6a26b9c54e2f2
Asset name:Toncoin
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| TRB/USD | 0x0003bb2b4884ee845cbfebfa8faa05da3ae60898f87b1aca6380d26b566b9753
Asset name:Tellor Tributes
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| TRU/USD | 0x00038f45bfa32f683a9d85c08edbf1bf008f1c31a07d9ccb23fac5fc0db4f135
Asset name:TrueFi
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| TRX/USD | 0x0003ae19a5ecabaa16492790f460098851cd7bfa2378464da2fdee842d9944a3
Asset name:Tron
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| TURBO/USD | 0x0003684ea93c43ed7bd00ab3bb189bb62f880436589f1ca58b599cd97d6007fb
Asset name:Turbo
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| UNI/USD | 0x00032b6edb94b883e95693b8fdae3deeedab2c48dd699cafa43a8d134d344813
Asset name:UniSwap
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| USDC/USD | 0x0003dc85e8b01946bf9dfd8b0db860129181eb6105a8c8981d9f28e00b6f60d9
Asset name:Circle USD
Asset class:Crypto - Stablecoin
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| USDT/USD | 0x00032874077216155926e26c159c1c20a572921371d9de605fe9633e48d136f9
Asset name:Tether USD
Asset class:Crypto - Stablecoin
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| USUAL/USD | 0x0003a53c52c900d5a5fa7c470f09eb2465a7e549e2c7f40bfcf3f86f9d7e99e9
Asset name:Usual
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| VET/USD | 0x0003c8fe4ec85f747f293425dcb7f1d6e5055ad1cd6a095357bc2c53a92fd2db
Asset name:VeChain
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| VIRTUAL/USD | 0x000374afc737ea4e5601a915f135a676f383e44d501d270f0785a814ce263a9c
Asset name:Virtuals Protocol
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| VVV/USD | 0x0003dc0265d4419472f5a4cd68e8bcbaf9b01be500507b05fe7063626913c2e0
Asset name:Venice Token
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| WEN/USD | 0x0003729b18978d1f4767e69666a3a499819a4e29b9a743ea0e852f19a0300a27
Asset name:WEN
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| WIF/USD | 0x0003d60c5bedb0cac1e875bb2766f1a589766705ae0e5324fa1db8648e3cb538
Asset name:dogwifhat
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| WLD/USD | 0x00035f53bfb39e634d28d9c00cdc6ae53bdd9ad83a692341c2495aa5a24cc245
Asset name:Worldcoin
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| WOO/USD | 0x0003a2d8358fc5cb6471343415c382baeb2afab6b1b2577e3bc789a6ae7f75b1
Asset name:WOO
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| XAI/USD | 0x0003a74878ba11e8e3dbad2729c0ee8777271b5ead4651de353a14b5ca252738
Asset name:Xai
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| XAUT/USD | 0x00037cb759f585268f12517980a82882bafaf6172e1f5071a9e3d0c6b69ccf2e
Asset name:Tether Gold
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| XDC/USD | 0x0003fe42f9c20310dee00c8288f28fd6ed411f8993e6834aa5f165da57a6c1da
Asset name:XDC Network
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| XLM/USD | 0x00037dfe3b67b7552cf15e10ee5fb0c0ab6d658b20eb558effe2ae4579d24c58
Asset name:Stellar
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| XPR/USD | 0x00032791c0c1dcf942d60e6204b80b403057fdf03566ae435639f91dd92199ec
Asset name:XPR Network
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| XRP/USD | 0x00035e3ddda6345c3c8ce45639d4449451f1d5828d7a70845e446f04905937cd
Asset name:Ripple
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| XTZ/USD | 0x0003130b5ee1f5d5f4e81007e41ec0653d66f089878c0627226ec4c83a4810bf
Asset name:Tezos Token
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ZBTC/USD | 0x0003d2a38d45c91b6659606a4d2057f895b95a0179a8ff4aa68042407cf4530a
Asset name:Zeus Network ZBTC
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ZEC/USD | 0x00039c0417ee6ffb4bae0964e2093d1d7ecd69628aac53f1f8f00d04e115d3cf
Asset name:ZCash
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ZEREBRO/USD | 0x0003aa42ceb1125ff9f0635ac837af79250a380bb6d4e8d1848b8a39d752322d
Asset name:Zerebro
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ZIL/USD | 0x0003c6ae4070e38a436837dd99a16bf4ca60760507d7551dbcfc9afa09a20da3
Asset name:Zilliqa
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ZK/USD | 0x0003594c3deb069ee2eae4e14df66fe593a2f63bb302a8709dddb5a0c55628c6
Asset name:ZKsync
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| ZRO/USD | 0x0003a298a69e06f226760e8de637e249d572047ec88ab826aa649f1c328dd941
Asset name:LayerZero
Asset class:Crypto
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
| stETH/USD | 0x00032062e05ef90877d833e4d44d585cb7bf76c18944fd45e5c098dd5d76f654
Asset name:Lido Staked ETH
Asset class:Crypto - Pegged Asset
Market hours:[Crypto](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[Crypto Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) |
## Get the latest Chainlink content straight to your inbox.
Email Address
## Automated Trade Execution
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Streams Trade Implementation](https://docs.chain.link/data-streams/streams-trade\#overview)
The Streams Trade implementation combines Chainlink Data Streams with [Chainlink Automation](https://docs.chain.link/chainlink-automation) to enable automated trade execution. This implementation allows decentralized applications to automate trade execution, mitigate frontrunning, and limit bias or adverse incentives in executing non-user-triggered orders.

Read more about the [Streams Trade Architecture](https://docs.chain.link/data-streams/architecture#streams-trade-architecture) and an [example trading flow](https://docs.chain.link/data-streams/architecture#example-trading-flow-using-streams-trade).
## [Getting Started](https://docs.chain.link/data-streams/streams-trade\#getting-started)
To implement Streams Trade in your application:
1. First, ensure Streams Trade is available on your desired network by checking the [Supported Networks](https://docs.chain.link/data-streams/supported-networks) page.
2. Review the [Architecture Documentation](https://docs.chain.link/data-streams/architecture#streams-trade-architecture) to understand the system components.
3. See an [Example Trading Flow](https://docs.chain.link/data-streams/architecture#example-trading-flow-using-streams-trade) to understand how trades are executed.
4. Follow our [Getting Started Guide](https://docs.chain.link/data-streams/getting-started) to set up your first integration.
## [Common Use Cases](https://docs.chain.link/data-streams/streams-trade\#common-use-cases)
Streams Trade is particularly well-suited for:
- **Perpetual Futures Protocols**: Enable high-performance onchain perpetual futures that can compete with centralized exchanges
- **Automated Market Making**: Implement sophisticated market making strategies with real-time price updates
- **Options Protocols**: Enable precise and timely settlement of options contracts
- **Prediction Markets**: Allow quick responses to real-time events with accurate settlement data
## [Learn More](https://docs.chain.link/data-streams/streams-trade\#learn-more)
- [Getting Started Guide](https://docs.chain.link/data-streams/getting-started)
- [Architecture Overview](https://docs.chain.link/data-streams/architecture#streams-trade-architecture)
- [Example Trading Flows](https://docs.chain.link/data-streams/architecture#example-trading-flow-using-streams-trade)
- [Available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
- [Report Schemas](https://docs.chain.link/data-streams/reference/report-schema)
## What's next
- [\> Learn how to get started with Streams Trade](https://docs.chain.link/data-streams/getting-started)
- [\> Understand the Streams Trade architecture](https://docs.chain.link/data-streams/architecture#streams-trade-architecture)
- [\> View example trading flows](https://docs.chain.link/data-streams/architecture#example-trading-flow-using-streams-trade)
- [\> Check supported networks](https://docs.chain.link/chainlink-automation/overview/supported-networks)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Data Streams Market Hours
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Data Streams Market Hours](https://docs.chain.link/data-streams/market-hours\#overview)
Markets for several assets are actively traded only during certain hours. Listed streams include an attribute describing their market hours.
## [Market hours](https://docs.chain.link/data-streams/market-hours\#market-hours)
| Asset class | Hours |
| --- | --- |
| **Crypto** | 24/7/365 - No market close. |
| **Forex** | 18:00 ET Sunday to 17:00 ET Friday.
The feeds also follow the global Forex market Christmas and New Year's Day holiday schedule. Many non-G12 currencies primarily trade during local market hours. It is recommended to use those feeds only during local trading hours. |
| **Precious Metals** | 18:00 ET Sunday to 17:00 ET Friday with a one-hour break Monday through Thursday from 17:00 to 18:00.
The feeds also follow the global Forex market holiday schedule for Christmas and New Year's Day. |
## [Real World Asset market status](https://docs.chain.link/data-streams/market-hours\#real-world-asset-market-status)
Reports for Real World Asset (RWA) streams include the `marketStatus` value, which reflects the DON'S consensus on whether the market is currently open. For additional information, refer to the [RWA report schema](https://docs.chain.link/data-streams/reference/report-schema-v4) page.
## What's next
- [\> Find the list of available Crypto streams](https://docs.chain.link/data-streams/crypto-streams)
- [\> Find the list of available RWA streams](https://docs.chain.link/data-streams/rwa-streams)
- [\> Find the schema of data to expect from Data Streams reports](https://docs.chain.link/data-streams/reference/report-schema)
## Get the latest Chainlink content straight to your inbox.
Email Address
## RWA Streams Overview
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Data Streams Real World Asset streams](https://docs.chain.link/data-streams/rwa-streams?page=1\#overview)
To learn how to use Data Streams, see the [Data Streams Getting Started](https://docs.chain.link/data-streams/getting-started) page.
For LINK token and Faucet details, see the [LINK Token Contracts](https://docs.chain.link/resources/link-token-contracts?parent=dataFeeds) page.
## [Streams Verifier Network Addresses](https://docs.chain.link/data-streams/rwa-streams?page=1\#streams-verifier-network-addresses)
Apechain
+
Arbitrum
+
Avalanche
+
Base
+
Berachain
+
Blast
+
BNB Chain
+
Bob
+
Botanix
+
Ethereum
+
Gnosis
+
HashKey Chain
+
Hyperliquid
+
Ink
+
Lens
+
Linea
+
Mantle
+
MegaETH
+
Monad
+
opBNB
+
OP
+
Ronin
+
Scroll
+
Shibarium
+
Soneium
+
Sonic
+
Solana
+
Taiko
+
Unichain
+
World Chain
+
ZKSync
+
## [Mainnet RWA Streams](https://docs.chain.link/data-streams/rwa-streams?page=1\#mainnet-rwa-streams)
| Stream | Details |
| --- | --- |
| AUD/USD | 0x000463a76b4a354b411a69c16990d01fd634e201a9f62d90bc67538469036b15
Full name:AUD/USD-RefPrice-DS-Premium-Global-004
Asset name:Australian Dollar
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| EUR/USD | 0x0004ce7bd717133dc3d5280e917e4c875bc51b5250af08207f88d2188183b999
Full name:EUR/USD-RefPrice-DS-Premium-Global-004
Asset name:Euro
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| GBP/USD | 0x0004ce879f7472b32164e11840547335635efee82495ce45cf017f2db3a20a7b
Full name:GBP/USD-RefPrice-DS-Premium-Global-004
Asset name:Pound Sterling
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| USD/CAD | 0x0004b4b4040ed61886724cec5d5d45f1953291228bf5f175a9fd7d3a8996fcea
Full name:USD/CAD-RefPrice-DS-Premium-Global-004
Asset name:USD
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| USD/CHF | 0x0004ab23e157405625b66f539d308771ab2b2a72162a449ab75c06dde5ace893
Full name:USD/CHF-RefPrice-DS-Premium-Global-004
Asset name:USD
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| USD/CNH | 0x0004ebedd3d52428f16fd7bd9e8e618ce260bfc0696e05bd96c142799fa19e36
Full name:USD/CNH-RefPrice-DS-Premium-Global-004
Asset name:USD
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| USD/JPY | 0x000492e10be89ed2f991d2c3ea57ac8dc4fdba9c0e19a0d40b6239560a6619b0
Full name:USD/JPY-RefPrice-DS-Premium-Global-004
Asset name:USD
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| XAG/USD | 0x0004c9a0b273bddd0c81c4de406290de805f712d1a9298c82fa265fe5a9999d1
Full name:XAG/USD-RefPrice-DS-Premium-Global-004
Asset name:Silver
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
Prev
Showing 1 to 8 of 9 entries
Next
## [Testnet RWA Streams](https://docs.chain.link/data-streams/rwa-streams?page=1\#testnet-rwa-streams)
| Stream | Details |
| --- | --- |
| AUD/USD | 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea
Asset name:Australian Dollar
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| EUR/USD | 0x0004b9905d8337c34e00f8dbe31619428bac5c3937e73e6af75c71780f1770ce
Asset name:Euro
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| GBP/USD | 0x00041eb2c13d227ff1e2888829a577be3d1fe708c5b8f75bd2af62d3ad70a82c
Asset name:Pound Sterling
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| USD/CAD | 0x000465640194893c34dcc38679866b78bdce1e9f4d4b873195a02eecc6f00e91
Asset name:USD
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| USD/CHF | 0x0004985dee9ef345e92513b7d88755fe90c02f3dd3e67b73d8e40550febbbea3
Asset name:USD
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| USD/CNH | 0x000486013d3ad6ea4a7019c5f3fe650ba7cdf6f9fc5612e0a4967ba4c0067113
Asset name:USD
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| USD/JPY | 0x00046ab03823e37bebe5f228d923ce27110e554b12d7fd476a4ae652f5bf7788
Asset name:USD
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| XAG/USD | 0x0004be5896c7bcdde3983c4b242e45c69b306a00acce0e177603ec258e4dd988
Asset name:Silver
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
| XAU/USD | 0x0004d7479d777c0090b7130f3e15e1e895a2932abc6f6dc26e022f8848834654
Asset name:Gold
Asset class:Forex
Market hours:[Forex](https://docs.chain.link/data-streams/market-hours)
Decimals:18
Report Schema:[RWA Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4) |
## Get the latest Chainlink content straight to your inbox.
Email Address
[iframe](https://td.doubleclick.net/td/rul/346357746?random=1746471462835&cv=11&fst=1746471462835&fmt=3&bg=ffffff&guid=ON&async=1&gcl_ctr=1>m=45be5510v891173849z8847174275za201zb882454074&gcd=13l3l3l3l1l1&dma=0&tag_exp=101509156~103101750~103101752~103116025~103200001~103233424~103251618~103251620~103252644~103252646&ptag_exp=101509157~103101750~103101752~103116026~103200004~103233427~103251618~103251620~103252644~103252646&u_w=1280&u_h=1024&url=https%3A%2F%2Fdocs.chain.link%2Fdata-streams%2Frwa-streams%3Fpage%3D1&label=_duuCKn_k4cYEPL_k6UB&hn=www.googleadservices.com&frm=0&tiba=Data%20Streams%20Real%20World%20Asset%20streams%20%7C%20Chainlink%20Documentation&value=0&bttype=purchase&npa=0&pscdl=noapi&auid=1430861288.1746471462&uaa=x86&uab=64&uafvl=Chromium%3B136.0.7103.59%7CGoogle%2520Chrome%3B136.0.7103.59%7CNot.A%252FBrand%3B99.0.0.0&uamb=0&uam=&uap=Linux%20x86_64&uapv=6.6.72&uaw=0&fledge=1&capi=1&_tu=Cg&ct_cookie_present=0)
## Chainlink Data Streams Guide
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Getting Started with Chainlink Data Streams (Remix)](https://docs.chain.link/data-streams/getting-started\#overview)
## Guide Versions
This guide is available in multiple versions. Choose the one that matches your needs.
Remix
[Remix](https://docs.chain.link/data-streams/getting-started) [Hardhat](https://docs.chain.link/data-streams/getting-started-hardhat)
This guide shows you how to read data from a Data Streams stream, verify the answer onchain, and store it.
This example uses the _[Streams Trade](https://docs.chain.link/data-streams/streams-trade) implementation_, with a [Chainlink Automation Log Trigger](https://docs.chain.link/chainlink-automation/guides/log-trigger) to check for events that require data. For this example, the log trigger comes from a simple emitter contract. Chainlink Automation then uses `StreamsLookup` to retrieve a signed report from the Data Streams Aggregation Network, return the data in a callback, and run the [`performUpkeep` function](https://docs.chain.link/chainlink-automation/reference/automation-interfaces#performupkeep-function-for-log-triggers) on your registered upkeep contract. The `performUpkeep` function calls the `verify` function on the verifier contract.
Note: To learn how to use the _[Streams Direct](https://docs.chain.link/data-streams/streams-direct) implementation_ of Data Streams, see the [Fetch and decode reports via a REST API](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api) guide or the [Stream and decode reports via WebSocket](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws) guide.
## [Before you begin](https://docs.chain.link/data-streams/getting-started\#before-you-begin)
- [Contact\\
us](https://chainlinkcommunity.typeform.com/datastreams?typeform-source=docs.chain.link#ref_id=docs) to request
mainnet or testnet access.
- If you are new to smart contract development, learn how to [Deploy Your First Smart Contract](https://docs.chain.link/quickstarts/deploy-your-first-contract) so you are familiar with the tools that are necessary for this guide:
- The [Solidity](https://soliditylang.org/) programming language
- The [MetaMask](https://metamask.io/) wallet
- The [Remix](https://remix.ethereum.org/) development environment
- This guide requires testnet ETH and LINK on _Arbitrum Sepolia_. Both are available at [faucets.chain.link](https://faucets.chain.link/arbitrum-sepolia).
- Learn how to [Fund your contract with LINK](https://docs.chain.link/resources/fund-your-contract).
## [Tutorial](https://docs.chain.link/data-streams/getting-started\#tutorial)
### [Deploy the Chainlink Automation upkeep contract](https://docs.chain.link/data-streams/getting-started\#deploy-the-chainlink-automation-upkeep-contract)
Deploy an upkeep contract that is enabled to retrieve data from Data Streams. For this example, you will read from the ETH/USD stream on Arbitrum Sepolia. This stream ID is `0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782`. See the [Data Streams Crypto streams](https://docs.chain.link/data-streams/crypto-streams) page for a complete list of available crypto assets.
1. [Open the StreamsUpkeep.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/StreamsUpkeep.sol) contract in Remix.
[Open in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/StreamsUpkeep.sol&autoCompile=true) [What is Remix?](https://docs.chain.link/getting-started/conceptual-overview#what-is-remix)
2. Select the `StreamsUpkeep.sol` contract in the **Solidity Compiler** tab.

3. Compile the contract. You can ignore the warning messages for this example.
4. Open MetaMask and set the network to _Arbitrum Sepolia_. If you need to add Arbitrum Sepolia to your wallet, you can find the chain ID and the LINK token contract address on the [LINK Token Contracts](https://docs.chain.link/resources/link-token-contracts#arbitrum-sepolia-testnet) page.
- [Arbitrum Sepolia testnet and LINK token contract](https://docs.chain.link/resources/link-token-contracts#arbitrum-sepolia-testnet)
5. On the **Deploy & Run Transactions** tab in Remix, select _Injected Provider - MetaMask_ in the **Environment** list. Remix will use the MetaMask wallet to communicate with _Arbitrum Sepolia_.

6. In the **Contract** section, select the `StreamsUpkeep` contract and fill in the Arbitrum Sepolia **verifier proxy address**: `0x2ff010DEbC1297f19579B4246cad07bd24F2488A`. You can find the verifier proxy addresses on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.

7. Click the **Deploy** button to deploy the contract. MetaMask prompts you to confirm the transaction. Check the transaction details to ensure you deploy the contract to _Arbitrum Sepolia_.
8. After you confirm the transaction, the contract address appears under the **Deployed Contracts** list in Remix. Save this contract address for later.

### [Deploy the emitter contract](https://docs.chain.link/data-streams/getting-started\#deploy-the-emitter-contract)
This contract emits logs that trigger the upkeep. This code can be part of your dApp. For example, you might emit log triggers when your users initiate a trade or other action requiring data retrieval. For this Getting Started guide, use a very simple emitter so you can test the upkeep and data retrieval.
1. [Open the LogEmitter.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/LogEmitter.sol) contract in Remix.
[Open in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/LogEmitter.sol&autoCompile=true) [What is Remix?](https://docs.chain.link/getting-started/conceptual-overview#what-is-remix)
2. Under the **Solidity Compiler** tab, select the `0.8.19` Solidity compiler and click the **Compile LogEmitter.sol** button to compile the contract.

3. Open MetaMask and make sure the network is still set to _Arbitrum Sepolia_.
4. On the **Deploy & Run Transactions** tab in Remix, ensure the **Environment** is still set to _Injected Provider - MetaMask_.

5. Click the **Deploy** button to deploy the contract. MetaMask prompts you to confirm the transaction. Check the transaction details to ensure you deploy the contract to _Arbitrum Sepolia_.

6. After you confirm the transaction, the contract address appears in the **Deployed Contracts** list. Save this contract address for later.

### [Register the upkeep](https://docs.chain.link/data-streams/getting-started\#register-the-upkeep)
Register a new **Log trigger** upkeep. See [Automation Log Triggers](https://docs.chain.link/chainlink-automation/guides/log-trigger) to learn more about how to register Log Trigger upkeeps.
01. Go to the [Chainlink Automation UI](https://automation.chain.link/arbitrum-sepolia) for _Arbitrum Sepolia_ and connect your browser wallet.
02. Click **Register new Upkeep**.
03. Select the **Log trigger** upkeep type and click **Next**.
04. Specify the upkeep contract address you saved earlier as the **Contract to automate**. In this example, you can ignore the warning about the Automation compatible contract verification. Click **Next**.
05. Specify the emitter contract address that you saved earlier. This tells Chainlink Automation what contracts to watch for log triggers. Then click **Next**.
06. Provide the ABI if the contract is not validated. To find the ABI of your contract in Remix, navigate to the **Solidity Compiler** tab. Then, copy the ABI to your clipboard using the button at the bottom of the panel.

07. Select the `Log` event as the triggering event in the **Emitted log** dropdown. **Log index topic filters** are optional filters to narrow the logs you want to trigger your upkeep. For this example, leave the field blank. Click **Next**.
08. Specify a name for the upkeep.
09. Specify a **Starting balance** of 1 testnet LINK for this example. You can retrieve unused LINK later.
10. Leave the **Check data** value and other fields blank for now, and click **Register Upkeep**. MetaMask prompts you to confirm the transaction. Wait for the transaction to complete.
### [Fund the upkeep contract](https://docs.chain.link/data-streams/getting-started\#fund-the-upkeep-contract)
In this example, the upkeep contract pays for onchain verification of reports from Data Streams. The Automation subscription does not cover the cost.
Open MetaMask and send 1 testnet LINK on _Arbitrum Sepolia_ to the upkeep contract address you saved earlier.

### [Emit a log](https://docs.chain.link/data-streams/getting-started\#emit-a-log)
You can use your emitter contract to emit a log and initiate the upkeep, which retrieves data for the specified stream ID.
1. In Remix, on the **Deploy & Run Transactions** tab, expand your emitter contract under the **Deployed Contracts** section.

2. Click the `emitLog` button to call the function and emit a log. MetaMask prompts you to accept the transaction.
After the transaction is complete, the log is emitted, and the upkeep is triggered. You can find the upkeep transaction hash in the [Chainlink Automation UI](https://automation.chain.link/arbitrum-sepolia). Check to make sure the transaction is successful.

### [View the retrieved price](https://docs.chain.link/data-streams/getting-started\#view-the-retrieved-price)
The retrieved price is stored in the `lastDecodedPrice` storage variable.
1. On the **Deploy & Run Transactions** tab in Remix, expand the details of your upkeep contract in the **Deployed Contracts** section.
2. Click the `lastDecodedPrice` getter function to view the retrieved price. The answer on the ETH/USD stream uses 18 decimal places, so an answer of `248412100000000000` indicates an ETH/USD price of 2,484.121. Some streams may use a different number of decimal places for answers. See the [Data Streams Crypto streams](https://docs.chain.link/data-streams/crypto-streams) page for more information.

## [Examine the code](https://docs.chain.link/data-streams/getting-started\#examine-the-code)
The example code you deployed has all the interfaces and functions required to work with Chainlink Automation as an upkeep contract. It follows a similar flow to the trading flow in the [Architecture](https://docs.chain.link/data-streams/architecture#example-trading-flow-using-streams-trade) documentation but uses a basic log emitter to simulate the client contract that would initiate a `StreamsLookup`. After the contract receives and verifies the report, `performUpkeep` stores the price from the report in the `lastDecodedPrice` variable. You could modify this to use the data in a way that works for your specific use case and application.
The code example uses `revert` with `StreamsLookup` to convey call information about what streams to retrieve. See the [EIP-3668 rationale](https://eips.ethereum.org/EIPS/eip-3668#rationale) for more information about how to use `revert` in this way.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Common} from "@chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol";
import {StreamsLookupCompatibleInterface} from "@chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol";
import {ILogAutomation, Log} from "@chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol";
import {IRewardManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol";
import {IVerifierFeeManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol";
import {IERC20} from "@chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol";
/**
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE FOR DEMONSTRATION PURPOSES.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
// Custom interfaces for IVerifierProxy and IFeeManager
interface IVerifierProxy {
/**
* @notice Verifies that the data encoded has been signed.
* correctly by routing to the correct verifier, and bills the user if applicable.
* @param payload The encoded data to be verified, including the signed
* report.
* @param parameterPayload Fee metadata for billing. For the current implementation this is just the abi-encoded fee token ERC-20 address.
* @return verifierResponse The encoded report from the verifier.
*/
function verify(
bytes calldata payload,
bytes calldata parameterPayload
) external payable returns (bytes memory verifierResponse);
function s_feeManager() external view returns (IVerifierFeeManager);
}
interface IFeeManager {
/**
* @notice Calculates the fee and reward associated with verifying a report, including discounts for subscribers.
* This function assesses the fee and reward for report verification, applying a discount for recognized subscriber addresses.
* @param subscriber The address attempting to verify the report. A discount is applied if this address
* is recognized as a subscriber.
* @param unverifiedReport The report data awaiting verification. The content of this report is used to
* determine the base fee and reward, before considering subscriber discounts.
* @param quoteAddress The payment token address used for quoting fees and rewards.
* @return fee The fee assessed for verifying the report, with subscriber discounts applied where applicable.
* @return reward The reward allocated to the caller for successfully verifying the report.
* @return totalDiscount The total discount amount deducted from the fee for subscribers
*/
function getFeeAndReward(
address subscriber,
bytes memory unverifiedReport,
address quoteAddress
) external returns (Common.Asset memory, Common.Asset memory, uint256);
function i_linkAddress() external view returns (address);
function i_nativeAddress() external view returns (address);
function i_rewardManager() external view returns (address);
}
contract StreamsUpkeep is ILogAutomation, StreamsLookupCompatibleInterface {
error InvalidReportVersion(uint16 version); // Thrown when an unsupported report version is provided to verifyReport.
/**
* @dev Represents a data report from a Data Streams stream for v3 schema (crypto streams).
* The `price`, `bid`, and `ask` values are carried to either 8 or 18 decimal places, depending on the stream.
* For more information, see https://docs.chain.link/data-streams/crypto-streams and https://docs.chain.link/data-streams/reference/report-schema
*/
struct ReportV3 {
bytes32 feedId; // The stream ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median price (8 or 18 decimals).
int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation (8 or 18 decimals).
int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation (8 or 18 decimals).
}
/**
* @dev Represents a data report from a Data Streams stream for v4 schema (RWA streams).
* The `price` value is carried to either 8 or 18 decimal places, depending on the stream.
* The `marketStatus` indicates whether the market is currently open. Possible values: `0` (`Unknown`), `1` (`Closed`), `2` (`Open`).
* For more information, see https://docs.chain.link/data-streams/rwa-streams and https://docs.chain.link/data-streams/reference/report-schema-v4
*/
struct ReportV4 {
bytes32 feedId; // The stream ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median benchmark price (8 or 18 decimals).
uint32 marketStatus; // The DON's consensus on whether the market is currently open.
}
struct Quote {
address quoteAddress;
}
IVerifierProxy public verifier;
address public FEE_ADDRESS;
string public constant DATASTREAMS_FEEDLABEL = "feedIDs";
string public constant DATASTREAMS_QUERYLABEL = "timestamp";
int192 public lastDecodedPrice;
// This example reads the ID for the ETH/USD report.
// Find a complete list of IDs at https://docs.chain.link/data-streams/crypto-streams.
string[] public feedIds = [\
"0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782"\
];
constructor(address _verifier) {
verifier = IVerifierProxy(_verifier);
}
// This function uses revert to convey call information.
// See https://eips.ethereum.org/EIPS/eip-3668#rationale for details.
function checkLog(
Log calldata log,
bytes memory
) external returns (bool upkeepNeeded, bytes memory performData) {
revert StreamsLookup(
DATASTREAMS_FEEDLABEL,
feedIds,
DATASTREAMS_QUERYLABEL,
log.timestamp,
""
);
}
/**
* @notice this is a new, optional function in streams lookup. It is meant to surface streams lookup errors.
* @return upkeepNeeded boolean to indicate whether the keeper should call performUpkeep or not.
* @return performData bytes that the keeper should call performUpkeep with, if
* upkeep is needed. If you would like to encode data to decode later, try `abi.encode`.
*/
function checkErrorHandler(
uint256 /*errCode*/,
bytes memory /*extraData*/
) external pure returns (bool upkeepNeeded, bytes memory performData) {
return (true, "0");
// Hardcoded to always perform upkeep.
// Read the StreamsLookup error handler guide for more information.
// https://docs.chain.link/chainlink-automation/guides/streams-lookup-error-handler
}
// The Data Streams report bytes is passed here.
// extraData is context data from stream lookup process.
// Your contract may include logic to further process this data.
// This method is intended only to be simulated offchain by Automation.
// The data returned will then be passed by Automation into performUpkeep
function checkCallback(
bytes[] calldata values,
bytes calldata extraData
) external pure returns (bool, bytes memory) {
return (true, abi.encode(values, extraData));
}
// function will be performed onchain
function performUpkeep(bytes calldata performData) external {
// Decode the performData bytes passed in by CL Automation.
// This contains the data returned by your implementation in checkCallback().
(bytes[] memory signedReports, bytes memory extraData) = abi.decode(
performData,
(bytes[], bytes)
);
bytes memory unverifiedReport = signedReports[0];
(, /* bytes32[3] reportContextData */ bytes memory reportData) = abi
.decode(unverifiedReport, (bytes32[3], bytes));
// Extract report version from reportData
uint16 reportVersion = (uint16(uint8(reportData[0])) << 8) |
uint16(uint8(reportData[1]));
// Validate report version
if (reportVersion != 3 && reportVersion != 4) {
revert InvalidReportVersion(uint8(reportVersion));
}
// Report verification fees
IFeeManager feeManager = IFeeManager(address(verifier.s_feeManager()));
IRewardManager rewardManager = IRewardManager(
address(feeManager.i_rewardManager())
);
address feeTokenAddress = feeManager.i_linkAddress();
(Common.Asset memory fee, , ) = feeManager.getFeeAndReward(
address(this),
reportData,
feeTokenAddress
);
// Approve rewardManager to spend this contract's balance in fees
IERC20(feeTokenAddress).approve(address(rewardManager), fee.amount);
// Verify the report
bytes memory verifiedReportData = verifier.verify(
unverifiedReport,
abi.encode(feeTokenAddress)
);
// Decode verified report data into the appropriate Report struct based on reportVersion
if (reportVersion == 3) {
// v3 report schema
ReportV3 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV3)
);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
} else if (reportVersion == 4) {
// v4 report schema
ReportV4 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV4)
);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
}
}
}
```
[Open in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/StreamsUpkeep.sol&autoCompile=true) [What is Remix?](https://docs.chain.link/getting-started/conceptual-overview#what-is-remix)
### [Initializing the upkeep contract](https://docs.chain.link/data-streams/getting-started\#initializing-the-upkeep-contract)
When you deploy the contract, you define the verifier proxy address. You can find this address on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page. The `IVerifierProxy` interface provides the following functions:
- The `s_feeManager` function to estimate the verification fees.
- The `verify` function to verify the report onchain.
### [Emitting a log, retrieving, and verifying the report](https://docs.chain.link/data-streams/getting-started\#emitting-a-log-retrieving-and-verifying-the-report)
After registering your upkeep contract with Chainlink Automation with a log trigger, you can emit a log with the `emitLog` function from your emitter contract.
1. The emitted log triggers the Chainlink Automation upkeep.
2. Chainlink Automation then uses `StreamsLookup` to retrieve a signed report from the Data Streams Aggregation Network, returns the data in a callback ( `checkCallback`), and runs the `performUpkeep` function on your registered upkeep contract.
3. The `performUpkeep` function calls the `verify` function on the verifier contract to verify the report onchain.
4. In this example, the `performUpkeep` function also stores the price from the report in the `lastDecodedPrice` state variable.
### [Viewing the retrieved price](https://docs.chain.link/data-streams/getting-started\#viewing-the-retrieved-price)
The `lastDecodedPrice` getter function of your upkeep contract retrieves the last price stored by the `performUpkeep` function in the `lastDecodedPrice` state variable of the `StreamsUpkeep` contract.
### [Feed ID types and conversion](https://docs.chain.link/data-streams/getting-started\#feed-id-types-and-conversion)
Chainlink Data Streams uses different data types for feed IDs at different stages of the process:
- The [`StreamsLookup` error](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol#L6) requires feed IDs to be provided as an array of `string`,
- The decoded reports within the contract use `bytes32` types for feed IDs (see the [Report Schemas](https://docs.chain.link/data-streams/reference/report-schema) reference).
If your application needs to compare the feed ID(s) sent in the `StreamsLookup` with those received in the report(s), you must convert between `string` and `bytes32` types.
### [Optional: Handle Data Streams fetching errors offchain with `checkErrorHandler`](https://docs.chain.link/data-streams/getting-started\#optional-handle-data-streams-fetching-errors-offchain-with-checkerrorhandler)
When Automation detects the triggering event, it runs the `checkLog` function of your upkeep contract, which includes a `StreamsLookup` revert custom error. The `StreamsLookup` revert enables your upkeep to fetch a report from the Data Streams Aggregation Network. If the report is fetched successfully, the `checkCallback` function is evaluated offchain. Otherwise, the `checkErrorHandler` function is evaluated offchain to determine what Automation should do next.
In this example, the `checkErrorHandler` is set to always return `true` for `upkeepNeeded`. This implies that the upkeep is always triggered, even if the report fetching fails. You can modify the `checkErrorHandler` function to handle errors offchain in a way that works for your specific use case. Read more about [using the StreamsLookup error handler](https://docs.chain.link/chainlink-automation/guides/streams-lookup-error-handler).
## What's next
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
- [\> Find the schema of data to expect from Data Streams reports](https://docs.chain.link/data-streams/reference/report-schema)
- [\> Learn more about Log Trigger upkeeps](https://docs.chain.link/chainlink-automation/guides/log-trigger/)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Developer Responsibilities Overview
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Developer Responsibilities: Market Integrity and Application Code Risks](https://docs.chain.link/data-streams/developer-responsibilities\#overview)
Chainlink Data Streams provide access to high-frequency market data backed by decentralized, fault-tolerant, and transparent infrastructure, where offchain data can be pulled onchain and verified by Chainlink's Verify Contract, as needed by your application. The assets priced by Chainlink Data Streams are subject to market conditions beyond the ability of Chainlink node operators to control. As such, developers are responsible for understanding market conditions and other external risks and how they can impact their products and services.
When integrating Chainlink Data Streams, developers must understand that the performance of individual Streams is subject to risks associated with both market integrity and application code.
- **Market Integrity Risks** are those associated with external market conditions impacting price behavior and data quality in unanticipated ways. Developers are solely responsible for monitoring and mitigating any potential market integrity risks.
- **Application Code Risks** are those associated with the quality, reliability, and dependencies of the code on which an application operates. Developers are solely responsible for monitoring and mitigating any potential application code risks related to their own products and services.
See the [Market Manipulation vs. Oracle Exploits](https://chain.link/education-hub/market-manipulation-vs-oracle-exploits) article for information about market integrity risks and how developers can protect their applications.
## [Developer Responsibilities](https://docs.chain.link/data-streams/developer-responsibilities\#developer-responsibilities)
Developers are responsible for maintaining the security and user experience of their applications. They must also securely manage all interactions between their applications and third-party services.
In particular, developers implementing Chainlink Data Streams in their code and applications are responsible for their application's market integrity and code risks that may cause unanticipated pricing data behavior. These are described below in more detail:
### [Market Integrity Risks](https://docs.chain.link/data-streams/developer-responsibilities\#market-integrity-risks)
Market conditions can impact the pricing behavior of assets in ways beyond the ability of Chainlink node operators to predict or control.
Market integrity risk factors can include, but are not limited to, [market manipulation](https://chain.link/education-hub/market-manipulation-vs-oracle-exploits) such as Spoofing, Ramping, Bear Raids, Cross-Market Manipulation, Washtrading, and Frontrunning. Developers are solely responsible for accounting for such risk factors when integrating Chainlink Data Streams into their applications. Developers should understand the market risks around the assets they intend their application to support before integrating associated Chainlink Data Streams and inform their end users about applicable market risks.
Developers should be aware that some assets, particularly those with low liquidity, may experience significant price volatility due to factors such as wider price spreads among exchanges. In such conditions, large trades can significantly move an asset's price, causing unexpected price oscillations.
#### [Traditional Market Assets](https://docs.chain.link/data-streams/developer-responsibilities\#traditional-market-assets)
Among other assets, Data Streams supports foreign exchange (FX) spot markets for major currencies against USD, gold and silver spot against USD, and WTI oil spot contracts. In traditional finance, these markets are some of the most liquid instruments and are traded across most financial centers including London, New York, Tokyo, and Singapore. Unlike Crypto markets, most traditional markets do not trade 24/7 and therefore liquidity and spreads can vary during the day and trading week. For assets traded within traditional markets, Chainlink Data Streams provides developers with an indication of the market's status (either open or closed), such as via a market status flag in price reports, which can be used by applications as applicable.
The market status provided on Streams serves as an indication of the open and close hours for traditional market assets based on historical practice; it is provided for referential purposes only. Developers are responsible for independently assessing the risks associated with trading at these times, particularly at opening and closing price levels. Developers are solely responsible for determining the actual status of markets for any streams they utilize. Protocol developers are advised to proceed with caution and make trading decisions at their own risk.
Under the shared responsibility model, developers must thoroughly understand the methodologies, trading behaviors, and market liquidity patterns related to traditional asset classes and instruments, particularly during and around market opening and closing hours. Developers should be aware of unique risks such as price volatility, sudden liquidity shifts, and trading halts that can affect data reliability and availability. A comprehensive understanding of these factors will help developers better anticipate and address potential issues, resulting in more resilient and trustworthy integrations for end users.
**Data Streams developers are solely responsible for defining and implementing their own risk procedures and systems, including being aware of market open and closing times, and bank holidays, when integrating associated Chainlink Data Streams.**
#### [DEX-based Assets](https://docs.chain.link/data-streams/developer-responsibilities\#dex-based-assets)
Data Streams also provides pricing data related to assets that trade, primarily, on decentralized exchanges (DEXs). Under the Shared Responsibility model, it is essential that developers understand the methodology and risks associated with such DEX-based assets. The risks include, but are not limited to:
- Data may be sourced by reading the state of onchain contracts and estimating the price at which trades in a certain asset pool could be executed. The accuracy of prices may be hindered by such factors as:
- Slippage: The movement of prices between (i) the time of observation, and (ii) the time of execution, caused by other transactions changing the state of the respective smart contract.
- Price Impact: The movement of price caused by the volume of trades being settled on a respective pool.
- Certain assets may not trade actively—if data is based on traded prices, it may not reflect the current state of the respective pool, and/or the current realizable price.
- There is a certain level of latency between (i) the observability of price data on DEXs, and (ii) the price data being reflected in our streams. This can increase the risk of frontrunning.
#### [New Token Data Streams](https://docs.chain.link/data-streams/developer-responsibilities\#new-token-data-streams)
When a token is newly launched, the historical data required to implement a rigorous data quality and risk analysis is unavailable. Consistent price discovery may involve an indeterminate amount of time. Developers are responsible for understanding the market and volatility risks inherent with such assets when choosing to integrate them into any products or services.
Newly issued tokens may have limited trading activity at launch. Thin order books can lead to substantial price fluctuation resulting in significant volatility. Developers are responsible for being aware, when choosing to integrate such tokens into any products or services, of the inherent volatility, potential for illiquidity, and significant price fluctuation that often characterize newly issued tokens as market attempts to find a clearing level, i.e equilibrium price.
Token prices may exhibit oscillations between two or more price points within regular intervals due to price disagreements across exchanges. In early trading sessions, wide bid and ask spreads may reflect uncertainty about the token market value. Developers are responsible for understanding the possibility of token price oscillation of this nature when choosing to integrate newly issued tokens into any products or services.
Developers implementing Chainlink New Token Data Streams are responsible for independently verifying the liquidity, quality and stability of the assets pricing when integrating them in their use cases
#### [Custom Data Streams](https://docs.chain.link/data-streams/developer-responsibilities\#custom-data-streams)
Custom Data Streams are built to serve a specific use case and might not be suitable for general use or your use case's risk parameters. Users must evaluate the properties of a feed to make sure it aligns with their intended use case. [Contact the Chainlink Labs team](https://chain.link/contact?ref_id=DataStreams) if you want more detail on any specific feeds in this category.
### [Application Code Risks](https://docs.chain.link/data-streams/developer-responsibilities\#application-code-risks)
Developers implementing Chainlink Data Streams are solely responsible for instituting risk mitigations, including, but not limited to, data quality checks, circuit breakers, and appropriate contingency logic for their use case. Some general guidelines include:
- **Code quality and reliability:** Developers must execute code using Chainlink Data Streams only if their code meets the quality and reliability requirements for their use case and application.
- **Code and application audits:** Developers are responsible for auditing their code and applications before deploying to production. Developers must determine the quality of any audits and ensure that they meet the requirements for their application.
- **Code dependencies and imports:** Developers are responsible for ensuring the quality, reliability, and security of any dependencies or imported packages that they use with Chainlink Data Streams, and review and audit these dependencies and packages.
- **Implementing Contingency Logic:** In extreme circumstances, including situations beyond the control of Chainlink node operators, Chainlink Data Streams may experience periods of unavailability or performance degradation. When a WebSocket connection is dropped, user systems must manage reconnections effectively. Developers are responsible for creating contingency plans tailored to their specific application needs, such as:
- Implementing the [Streams Direct Architecture](https://docs.chain.link/data-streams/architecture#streams-direct-architecture),
- Adopting an [active-active](https://docs.chain.link/data-streams/architecture#active-active-multi-site-deployment) deployment strategy and [configuring the SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk#config-struct) to support multiple concurrent WebSocket connections,
- Retrieving any potentially missing reports via the [REST API](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api).
### [Additional Considerations on Data Usage and Verification](https://docs.chain.link/data-streams/developer-responsibilities\#additional-considerations-on-data-usage-and-verification)
- **Combined Data Sources:** Mixing data from Data Streams with other pricing sources introduces additional complexity and risk. It may result in unforeseen results, potentially impacting application performance or reliability. Developers are solely responsible for any such outcomes, and it is imperative that thorough risk assessments and comprehensive testing protocols are implemented.
- **Bypassing Data Verification:** Verifying against the Chainlink Verifier Contract is essential for ensuring data integrity. Bypassing or improperly implementing it increases the risk of data manipulation and should be avoided.
Developers are responsible for understanding and managing all additional risk factors. Implementing proper risk assessment and mitigation strategies is crucial to maintaining the integrity and reliability of applications that rely on external data sources.
## What's next
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
- [\> Find the schema of data to expect from Data Streams reports](https://docs.chain.link/data-streams/reference/report-schema)
- [\> Learn the basics about how to retrieve Data Streams reports using the Streams Trade implementation](https://docs.chain.link/data-streams/getting-started)
- [\> Learn how to fetch and decode Data Streams reports using the Streams Direct API](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api)
## Get the latest Chainlink content straight to your inbox.
Email Address
[iframe](https://td.doubleclick.net/td/rul/346357746?random=1746471454973&cv=11&fst=1746471454973&fmt=3&bg=ffffff&guid=ON&async=1&gcl_ctr=1>m=45be5510v891173849z8847174275za201zb882454074&gcd=13l3l3l3l1l1&dma=0&tag_exp=101509156~102015666~103101747~103101749~103116025~103200001~103233424~103251618~103251620~103252644~103252646&ptag_exp=101509156~103101750~103101752~103116026~103200004~103233424~103251618~103251620~103252644~103252646&u_w=1280&u_h=1024&url=https%3A%2F%2Fdocs.chain.link%2Fdata-streams%2Fdeveloper-responsibilities&label=_duuCKn_k4cYEPL_k6UB&hn=www.googleadservices.com&frm=0&tiba=Developer%20Responsibilities%3A%20Market%20Integrity%20and%20Application%20Code%20Risks%20%7C%20Chainlink%20Documentation&value=0&bttype=purchase&npa=0&pscdl=noapi&auid=468069873.1746471455&uaa=x86&uab=64&uafvl=Chromium%3B136.0.7103.59%7CGoogle%2520Chrome%3B136.0.7103.59%7CNot.A%252FBrand%3B99.0.0.0&uamb=0&uam=&uap=Linux%20x86_64&uapv=6.6.72&uaw=0&fledge=1&capi=1&_tu=Cg&ct_cookie_present=0)
## Chainlink Streams Direct
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Streams Direct Implementation](https://docs.chain.link/data-streams/streams-direct\#overview)
The Streams Direct implementation provides direct access to Chainlink Data Streams through SDKs and APIs, allowing you to build custom solutions with low-latency, high-frequency data. This implementation enables you to fetch reports or subscribe to report updates from the Data Streams Aggregation Network and verify their authenticity onchain. For instance, you can use Chainlink Data Streams with the Streams Direct implementation to display indicative pricing offchain on your front end or with your bot to settle trades onchain.

## [Key Features](https://docs.chain.link/data-streams/streams-direct\#key-features)
- **Direct API Access**: Fetch data directly using REST API or WebSocket connections
- **Multiple SDK Options**: Choose between Go and Rust SDKs for seamless integration
- **Flexible Implementation**: Build custom solutions for both offchain display and onchain settlement
- **Onchain Verification**: Verify data authenticity when needed
## [Getting Started](https://docs.chain.link/data-streams/streams-direct\#getting-started)
To implement Streams Direct in your application:
1. Review the [Architecture Documentation](https://docs.chain.link/data-streams/architecture#streams-direct-architecture) to understand the system components
2. Choose your preferred SDK:
- [Go SDK Documentation](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk)
- [Rust SDK Documentation](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk)
3. Follow our [API Tutorial](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api) to learn how to fetch and decode reports
4. Implement [onchain verification](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification) for your use case
## [Common Use Cases](https://docs.chain.link/data-streams/streams-direct\#common-use-cases)
Streams Direct is particularly well-suited for:
- **Custom Trading Bots**: Build automated trading systems with direct access to high-frequency data
- **Front-end Price Display**: Show real-time indicative pricing in your dApp interface
- **Custom Settlement Logic**: Implement specialized settlement mechanisms using verified data
- **Market Analysis Tools**: Create tools for market analysis and monitoring
## [Integration Options](https://docs.chain.link/data-streams/streams-direct\#integration-options)
### [REST API](https://docs.chain.link/data-streams/streams-direct\#rest-api)
Use the REST API to fetch individual reports on demand. This is ideal for:
- One-time data queries
- Periodic updates at custom intervals
- Integration with existing REST-based systems
### [WebSocket Connection](https://docs.chain.link/data-streams/streams-direct\#websocket-connection)
Subscribe to continuous updates via WebSocket for:
- Real-time price updates
- Streaming market data
- Immediate notification of new reports
## [Learn More](https://docs.chain.link/data-streams/streams-direct\#learn-more)
- [API Tutorial](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api)
- [Go SDK Documentation](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk)
- [Rust SDK Documentation](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk)
- [Onchain Verification](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification)
- [Available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
- [Report Schemas](https://docs.chain.link/data-streams/reference/report-schema)
## What's next
- [\> Learn how to fetch and decode Data Streams reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api)
- [\> Explore the Go SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk)
- [\> Explore the Rust SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk)
- [\> Learn about onchain verification](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Chainlink Data Streams Updates
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Release Notes](https://docs.chain.link/data-streams/release-notes\#overview)
## [2025-05-04 - Added support to Data Streams](https://docs.chain.link/data-streams/release-notes\#2025-05-04-added-support-to-data-streams)
New Data Streams available on all [supported networks](https://docs.chain.link/data-streams/crypto-streams):
- [Dolomite (DOLO / USD)](https://data.chain.link/streams/dolo-usd)
## [2025-04-27 - Added support to Data Streams](https://docs.chain.link/data-streams/release-notes\#2025-04-27-added-support-to-data-streams)
New Data Streams available on all [supported networks](https://docs.chain.link/data-streams/crypto-streams):
- [ANIME (ANIME / USD)](https://data.chain.link/streams/anime-usd)
- [Binance Staked SOL (BNSOL / USD)](https://data.chain.link/streams/bnsol-usd)
- [BlazeStake Staked SOL (BSOL / USD)](https://data.chain.link/streams/bsol-usd)
- [frax (FRAX / USD)](https://data.chain.link/streams/frax-usd)
- [Helius Staked SOL (HSOL / USD)](https://data.chain.link/streams/hsol-usd)
- [Jito Staked SOL (JITOSOL / USD)](https://data.chain.link/streams/jitosol-usd)
- [Marinade Staked SOL (MSOL / USD)](https://data.chain.link/streams/msol-usd)
- [metis (METIS / USD)](https://data.chain.link/streams/metis-usd)
- [OMG Network (OMG / USD)](https://data.chain.link/streams/omg-usd)
- [PayPal USD (PYUSD / USD)](https://data.chain.link/streams/pyusd-usd)
- [Sanctum Inifnity (INF / USD)](https://data.chain.link/streams/inf-usd)
- [Tether Gold (XAUT / USD)](https://data.chain.link/streams/xaut-usd)
- [The Vault Staked SOL (VSOL / USD)](https://data.chain.link/streams/vsol-usd)
- [XPR Network (XPR / USD)](https://data.chain.link/streams/xpr-usd)
## [2025-04-20 - Added support to Data Streams](https://docs.chain.link/data-streams/release-notes\#2025-04-20-added-support-to-data-streams)
New Data Streams available on all [supported networks](https://docs.chain.link/data-streams/crypto-streams):
- [Australian Dollar (AUD / USD)](https://data.chain.link/streams/aud-usd)
- [Euro (EUR / USD)](https://data.chain.link/streams/eur-usd)
- [Gold (XAU / USD)](https://data.chain.link/streams/xau-usd)
- [Pound Sterling (GBP / USD)](https://data.chain.link/streams/gbp-usd)
- [Silver (XAG / USD)](https://data.chain.link/streams/xag-usd)
- [USD (USD / JPY)](https://data.chain.link/streams/usd-jpy)
- [USD (USD / CHF)](https://data.chain.link/streams/usd-chf)
- [USD (USD / CAD)](https://data.chain.link/streams/usd-cad)
- [USD (USD / CNH)](https://data.chain.link/streams/usd-cnh)
## [2025-04-17 - Data Streams on Gnosis](https://docs.chain.link/data-streams/release-notes\#2025-04-17-data-streams-on-gnosis)
Chainlink Data Streams is available on Gnosis. The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2025-04-13 - Added support to Data Streams](https://docs.chain.link/data-streams/release-notes\#2025-04-13-added-support-to-data-streams)
New Data Streams available on all [supported networks](https://docs.chain.link/data-streams/crypto-streams):
- [Bitcoin SV (BSV / USD)](https://data.chain.link/streams/bsv-usd)
- [Coinbase Wrapped BTC (cbBTC / USD)](https://data.chain.link/streams/cbbtc-usd)
- [Creditcoin (CTC / USD)](https://data.chain.link/streams/ctc-usd)
- [Ethena Staked USDE (SUSDE / USD)](https://data.chain.link/streams/susde-usd)
- [Ethena USDe (USDe / USD)](https://data.chain.link/streams/usde-usd)
- [First Digital USD (FDUSD / USD)](https://data.chain.link/streams/fdusd-usd)
- [GHO (GHO / USD)](https://data.chain.link/streams/gho-usd)
- [Grass (GRASS / USD)](https://data.chain.link/streams/grass-usd)
- [JasmyCoin (JASMY / USD)](https://data.chain.link/streams/jasmy-usd)
- [Jupiter Perpetuals LP token (JLP / USD)](https://data.chain.link/streams/jlp-usd)
- [Jupiter Staked SOL (JUPSOL / USD)](https://data.chain.link/streams/jupsol-usd)
- [KuCoin (KCS / USD)](https://data.chain.link/streams/kcs-usd)
- [Kudai (KUDAI / USD)](https://data.chain.link/streams/kudai-usd)
- [Liquity USD (LUSD / USD)](https://data.chain.link/streams/lusd-usd)
- [Livepeer (LPT / USD)](https://data.chain.link/streams/lpt-usd)
- [LOMBARD STAKED BTC (LBTC / USD)](https://data.chain.link/streams/lbtc-usd)
- [Loopring (LRC / USD)](https://data.chain.link/streams/lrc-usd)
- [Treasure (MAGIC) (MAGIC / USD)](https://data.chain.link/streams/magic-usd)
- [Mantle (MNT / USD)](https://data.chain.link/streams/mnt-usd)
- [Mask Network (MASK / USD)](https://data.chain.link/streams/mask-usd)
- [Monero (XMR / USD)](https://data.chain.link/streams/xmr-usd)
- [Neo (NEO / USD)](https://data.chain.link/streams/neo-usd)
- [Pi Network (PI / USD)](https://data.chain.link/streams/pi-usd)
- [Ravencoin (RVN / USD)](https://data.chain.link/streams/rvn-usd)
- [Renzo Restaked ETH (ezETH / USD)](https://data.chain.link/streams/ezeth-usd)
- [Safe (SAFE / USD)](https://data.chain.link/streams/safe-usd)
- [Sky Dollar (USDS / USD)](https://data.chain.link/streams/usds-usd)
- [SuperVerse (SUPER / USD)](https://data.chain.link/streams/super-usd)
- [tBTC (TBTC / USD)](https://data.chain.link/streams/tbtc-usd)
- [Theta (THETA / USD)](https://data.chain.link/streams/theta-usd)
- [Thorchain (RUNE / USD)](https://data.chain.link/streams/rune-usd)
- [Wrapped Bitcoin (wBTC / USD)](https://data.chain.link/streams/wbtc-usd)
- [Wrapped eETH (WEETH / USD)](https://data.chain.link/streams/weeth-usd)
- [Wrapped stETH (WSTETH / USD)](https://data.chain.link/streams/wsteth-usd)
- [Yearn Finance (YFI / USD)](https://data.chain.link/streams/yfi-usd)
- [Zetachain (ZETA / USD)](https://data.chain.link/streams/zeta-usd)
## [2025-04-10 - Data Streams Expands to New Blockchains](https://docs.chain.link/data-streams/release-notes\#2025-04-10-data-streams-expands-to-new-blockchains)
Chainlink Data Streams is available for new blockchains:
- Apechain Mainnet
- Apechain Testnet
- Taiko Alethia (Mainnet)
- Taiko Hekla (Testnet)
The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2025-04-04 - Data Streams on Lens](https://docs.chain.link/data-streams/release-notes\#2025-04-04-data-streams-on-lens)
Chainlink Data Streams is available on Lens. The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2025-03-30 - Added support to Data Streams](https://docs.chain.link/data-streams/release-notes\#2025-03-30-added-support-to-data-streams)
New Data Streams available on all [supported networks](https://docs.chain.link/data-streams/crypto-streams):
- [Balancer (BAL / USD)](https://data.chain.link/streams/bal-usd)
- [Beam (BEAM / USD)](https://data.chain.link/streams/beam-usd)
- [Bitget Token (BGB / USD)](https://data.chain.link/streams/bgb-usd)
- [BitTorrent (BTT / USD)](https://data.chain.link/streams/btt-usd)
- [Conflux (CFX / USD)](https://data.chain.link/streams/cfx-usd)
- [Core (CORE / USD)](https://data.chain.link/streams/core-usd)
- [Drift Protocol (DRIFT / USD)](https://data.chain.link/streams/drift-usd)
- [Flare (FLR / USD)](https://data.chain.link/streams/flr-usd)
- [Gains Network (GNS / USD)](https://data.chain.link/streams/gns-usd)
- [Kusama (KSM / USD)](https://data.chain.link/streams/ksm-usd)
- [Mina (MINA / USD)](https://data.chain.link/streams/mina-usd)
- [Orca (ORCA / USD)](https://data.chain.link/streams/orca-usd)
- [PONKE (PONKE / USD)](https://data.chain.link/streams/ponke-usd)
- [Qtum (QTUM / USD)](https://data.chain.link/streams/qtum-usd)
- [SKALE (SKL / USD)](https://data.chain.link/streams/skl-usd)
- [Stepn (GMT / USD)](https://data.chain.link/streams/gmt-usd)
- [Storj (STORJ / USD)](https://data.chain.link/streams/storj-usd)
- [Sushi (SUSHI / USD)](https://data.chain.link/streams/sushi-usd)
- [Trader Joe (JOE / USD)](https://data.chain.link/streams/joe-usd)
- [Zilliqa (ZIL / USD)](https://data.chain.link/streams/zil-usd)
## [2025-03-19 - Data Streams on MegaETH Testnet](https://docs.chain.link/data-streams/release-notes\#2025-03-19-data-streams-on-megaeth-testnet)
Chainlink Data Streams is available in Early Access on MegaETH Testnet. The verifier proxy address and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2025-03-18 - Data Streams Expands to New Blockchains](https://docs.chain.link/data-streams/release-notes\#2025-03-18-data-streams-expands-to-new-blockchains)
Chainlink Data Streams is available in Early Access for new blockchains:
- BNB Chain Mainnet
- BNB Chain Testnet
- Hyperliquid Mainnet
- Hyperliquid Testnet
The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2025-02-19 - Data Streams Expands to New Blockchains](https://docs.chain.link/data-streams/release-notes\#2025-02-19-data-streams-expands-to-new-blockchains)
Chainlink Data Streams is available in Early Access for new blockchains:
- Bob Mainnet
- Bob Sepolia Testnet
- Linea Mainnet
- Linea Sepolia Testnet
- Unichain Mainnet
- Unichain Sepolia Testnet
The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2025-02-18 - Data Streams on Hashkey Chain Testnet](https://docs.chain.link/data-streams/release-notes\#2025-02-18-data-streams-on-hashkey-chain-testnet)
Chainlink Data Streams is available in Early Access on Hashkey Chain Testnet. The verifier proxy address and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2025-02-12 - Data Streams Expands to New Blockchains](https://docs.chain.link/data-streams/release-notes\#2025-02-12-data-streams-expands-to-new-blockchains)
Chainlink Data Streams is available in Early Access for new blockchains:
- Botanix Testnet
- Ink Sepolia Testnet
- Monad Testnet
- World Chain Mainnet
- World Chain Sepolia Testnet
The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2025-02-11 - Data Streams Expands to New Blockchains](https://docs.chain.link/data-streams/release-notes\#2025-02-11-data-streams-expands-to-new-blockchains)
Chainlink Data Streams is available in Early Access for new blockchains:
- Berachain Mainnet
- Berachain bArtio Testnet
- Blast Mainnet
- Blast Sepolia Testnet
The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2025-02-10 - Data Streams Expands to New Blockchains](https://docs.chain.link/data-streams/release-notes\#2025-02-10-data-streams-expands-to-new-blockchains)
Chainlink Data Streams is available in Early Access for new blockchains:
- Ethereum Mainnet
- Ethereum Sepolia
- HashKey Chain Mainnet
- Ink Mainnet
- Ronin Mainnet
- Ronin Saigon Testnet
The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2025-02-07 - Data Streams Expands to New Blockchains](https://docs.chain.link/data-streams/release-notes\#2025-02-07-data-streams-expands-to-new-blockchains)
Chainlink Data Streams is available in Early Access for new blockchains:
- Mantle
- Soneium
- zkSync
The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2025-01-29 - Data Streams on Scroll](https://docs.chain.link/data-streams/release-notes\#2025-01-29-data-streams-on-scroll)
Chainlink Data Streams is available in Early Access on Scroll. The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2024-12-19 - Data Streams on Shibarium](https://docs.chain.link/data-streams/release-notes\#2024-12-19-data-streams-on-shibarium)
Chainlink Data Streams is available in Early Access on Shibarium. The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2024-12-17 - Data Streams Verifier Programs on Solana](https://docs.chain.link/data-streams/release-notes\#2024-12-17-data-streams-verifier-programs-on-solana)
Onchain Verifier Programs are now available on Solana, providing both onchain and offchain integration approaches while maintaining strong security guarantees.
Verifier Program IDs for both Devnet and Mainnet environments are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2024-11-26 - Data Streams on Optimism](https://docs.chain.link/data-streams/release-notes\#2024-11-26-data-streams-on-optimism)
Chainlink Data Streams is available in Early Access on Optimism. The verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
## [2024-10-29 - Real World Asset streams - Testnet](https://docs.chain.link/data-streams/release-notes\#2024-10-29-real-world-asset-streams-testnet)
Real World Asset (RWA) streams are now available on testnet.
- RWA streams use the [V4 report schema](https://docs.chain.link/data-streams/reference/report-schema-v4).
- Verifier proxy addresses and RWA stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/rwa-streams) page.
## [2024-10-28 - Data Streams on Solana](https://docs.chain.link/data-streams/release-notes\#2024-10-28-data-streams-on-solana)
Chainlink Data Streams is available in Early Access on Solana. [Contact us](https://chainlinkcommunity.typeform.com/datastreams?typeform-source=docs.chain.link#ref_id=docs) to talk to an expert about integrating Chainlink Data Streams on Solana.
## [2024-10-25 - Data Streams on opBNB](https://docs.chain.link/data-streams/release-notes\#2024-10-25-data-streams-on-opbnb)
Chainlink Data Streams is available in Early Access on opBNB. The verifier proxy addresses and feed IDs are available on the [Data Streams Feed IDs](https://docs.chain.link/data-streams/stream-ids) page.
## [2024-10-22 - Data Streams on Soneium Minato](https://docs.chain.link/data-streams/release-notes\#2024-10-22-data-streams-on-soneium-minato)
Chainlink Data Streams is available in Early Access on Soneium Minato. The verifier proxy address and feed IDs are available on the [Data Streams Feed IDs](https://docs.chain.link/data-streams/stream-ids) page.
## [2024-08-15 - Data Streams on Base](https://docs.chain.link/data-streams/release-notes\#2024-08-15-data-streams-on-base)
Chainlink Data Streams is available in Early Access on Base Mainnet and Base Sepolia testnet. Verifier proxy addresses and Feed IDs are available on the [Data Streams Feed IDs](https://docs.chain.link/data-streams/stream-ids) page.
## [2024-08-02 - Data Streams SDK for Go](https://docs.chain.link/data-streams/release-notes\#2024-08-02-data-streams-sdk-for-go)
The [Data Streams SDK](https://docs.chain.link/data-streams/tutorials/streams-direct/) for Go is now available. See the [Fetch and Decode](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api) guide to get started with the SDK.
## [2024-06-27 - Data Streams on Avalanche](https://docs.chain.link/data-streams/release-notes\#2024-06-27-data-streams-on-avalanche)
Chainlink Data Streams is available in Early Access on Avalanche mainnet and Fuji testnet. Verifier proxy addresses and Feed IDs are available on the [Data Streams Feed IDs](https://docs.chain.link/data-streams/stream-ids) page.
## [2024-01-25 - Data Streams on Arbitrum Sepolia](https://docs.chain.link/data-streams/release-notes\#2024-01-25-data-streams-on-arbitrum-sepolia)
Chainlink Data Streams is available in Early Access on Arbitrum Sepolia. Verifier proxy addresses and Feed IDs are available on the [Data Streams Feed IDs](https://docs.chain.link/data-streams/stream-ids) page.
## [2023-10-02 - Data Streams Early Access](https://docs.chain.link/data-streams/release-notes\#2023-10-02-data-streams-early-access)
Chainlink Data Streams is available in Early Access on Arbitrum Mainnet and Arbitrum Goerli. [Read the docs](https://docs.chain.link/data-streams/) to get started.
## What's next
- [\> Learn the basics about how to retrieve Data Streams reports in the Getting Started guide.](https://docs.chain.link/data-streams/getting-started)
- [\> Find the list of available feed IDs.](https://docs.chain.link/data-streams/crypto-streams)
- [\> Find the schema of data to expect from Data Streams reports.](https://docs.chain.link/data-streams/reference/report-schema)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Chainlink Data Streams Networks
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Supported Networks](https://docs.chain.link/data-streams/supported-networks\#overview)
Chainlink Data Streams has two primary implementations: [Streams Direct](https://docs.chain.link/data-streams/streams-direct) and [Streams Trade](https://docs.chain.link/data-streams/streams-trade). Network support differs between these two implementations.
## [Streams Direct (Offchain Access)](https://docs.chain.link/data-streams/supported-networks\#streams-direct-offchain-access)
Streams Direct provides data access directly via API or WebSocket for offchain use cases. It involves [verifying report integrity](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification) against onchain verifier proxy contracts.
Streams Direct is available on any network listed on the following pages, where you can find the necessary Verifier Proxy addresses:
- [Cryptocurrency Streams](https://docs.chain.link/data-streams/crypto-streams)
- [Real World Asset (RWA) Streams](https://docs.chain.link/data-streams/rwa-streams)
## [Streams Trade (Onchain Lookup)](https://docs.chain.link/data-streams/supported-networks\#streams-trade-onchain-lookup)
Streams Trade allows smart contracts to access Data Streams onchain using the [`StreamsLookup`](https://docs.chain.link/data-streams/getting-started) capability integrated with [Chainlink Automation](https://docs.chain.link/chainlink-automation).
Streams Trade is currently available on the following networks:
- Arbitrum
- Avalanche
- Base
- BNB Chain
- Ethereum
- Optimism
## Get the latest Chainlink content straight to your inbox.
Email Address
## Report Schemas Overview
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
On this page
# [Report Schemas](https://docs.chain.link/data-streams/reference/report-schema\#overview)
## Available Report Schemas
Choose the schema version you want to explore.
Cryptocurrency Report Schema (v3)
[Cryptocurrency Report Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) [Real World Asset (RWA) Report Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4)
Cryptocurrency streams adhere to the report schema outlined below.
## [Schema Fields](https://docs.chain.link/data-streams/reference/report-schema\#schema-fields)
| Field | Type | Description |
| --- | --- | --- |
| `feedID` | `bytes32` | Unique identifier for the data stream |
| `validFromTimestamp` | `uint32` | Start timestamp of price validity period |
| `observationsTimestamp` | `uint32` | End timestamp of price validity period |
| `nativeFee` | `uint192` | Verification cost in native blockchain tokens |
| `linkFee` | `uint192` | Verification cost in LINK tokens |
| `expiresAt` | `uint32` | Timestamp when this report expires |
| `price` | `int192` | DON consensus median price (18 decimal places) |
| `bid` | `int192` | Simulated buy impact price at X% liquidity depth |
| `ask` | `int192` | Simulated sell impact price at X% liquidity depth |
**Note**: Future Cryptocurrency streams may use different report schemas.
## Get the latest Chainlink content straight to your inbox.
Email Address
## Chainlink Data Streams Guide
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Getting Started with Chainlink Data Streams (Hardhat CLI)](https://docs.chain.link/data-streams/getting-started-hardhat\#overview)
## Guide Versions
This guide is available in multiple versions. Choose the one that matches your needs.
Hardhat
[Remix](https://docs.chain.link/data-streams/getting-started) [Hardhat](https://docs.chain.link/data-streams/getting-started-hardhat)
This guide shows you how to read data from a Data Streams stream, verify the answer onchain, and store it.
This example uses the _[Streams Trade](https://docs.chain.link/data-streams/streams-trade) implementation_, with a [Chainlink Automation Log Trigger](https://docs.chain.link/chainlink-automation/guides/log-trigger) to check for events that require data. For this example, the log trigger comes from a simple emitter contract. Chainlink Automation then uses `StreamsLookup` to retrieve a signed report from the Data Streams Aggregation Network, return the data in a callback, and run the [`performUpkeep` function](https://docs.chain.link/chainlink-automation/reference/automation-interfaces#performupkeep-function-for-log-triggers) on your registered upkeep contract. The `performUpkeep` function calls the `verify` function on the verifier contract.
Note: To learn how to use the _[Streams Direct](https://docs.chain.link/data-streams/streams-direct) implementation_ of Data Streams, see the [Fetch and decode reports via a REST API](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api) guide or the [Stream and decode reports via WebSocket](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws) guide.
## [Before you begin](https://docs.chain.link/data-streams/getting-started-hardhat\#before-you-begin)
- [Contact\\
us](https://chainlinkcommunity.typeform.com/datastreams?typeform-source=docs.chain.link#ref_id=docs) to request
mainnet or testnet access.
- This guide uses the [Hardhat](https://hardhat.org/) development environment to deploy and interact with the contracts. To learn more about Hardhat, read the [Hardhat Documentation](https://hardhat.org/hardhat-runner/docs/getting-started).
### [Requirements](https://docs.chain.link/data-streams/getting-started-hardhat\#requirements)
- **Git**: Make sure you have Git installed. You can check your current version by running `git --version` in your terminal and download the latest version from the official [Git website](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) if necessary.
- **Nodejs** and **npm**: [Install the latest release of Node.js 20](https://nodejs.org/en/download/). Optionally, you can use [nvm](https://github.com/nvm-sh/nvm/blob/master/README.md) to switch between installed Node.js versions with `nvm use 20`. To ensure you are running the correct version in a terminal, type `node -v`.

```bash
$ node -v
v20.11.0
```
- **Testnet funds**: This guide requires testnet ETH and LINK on Arbitrum Sepolia. Both are available at [faucets.chain.link](https://faucets.chain.link/arbitrum-sepolia).
## [Tutorial](https://docs.chain.link/data-streams/getting-started-hardhat\#tutorial)
### [Setup](https://docs.chain.link/data-streams/getting-started-hardhat\#setup)
1. Clone the [repository](https://github.com/smartcontractkit/smart-contract-examples) that contains the Hardhat project setup for this guide. This repository contains the Solidity contracts and the Hardhat configuration files you need to deploy and interact with the contracts.

```bash
git clone https://github.com/smartcontractkit/smart-contract-examples.git
cd smart-contract-examples/data-streams/getting-started/hardhat
```
2. Install the dependencies:

```bash
npm install
```
3. Set an encryption password for your environment variables. This password needs to be set each time you create or restart a terminal session.

```bash
npx env-enc set-pw
```
4. Set the required environment variables using the following command:

```bash
npx env-enc set
```
- `PRIVATE_KEY`: The private key for your testnet wallet that will deploy and interact with the contracts. If you use MetaMask, follow the instructions to [Export a Private Key](https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key)
- `ARBITRUM_SEPOLIA_RPC_URL`: The Remote Procedure Call (RPC) URL for the Arbitrum Sepolia network. You can obtain one by creating an account on [Alchemy](https://www.alchemy.com/) or [Infura](https://www.infura.io/) and setting up an Arbitrum Sepolia project.
### [Deploy the upkeep and the log emitter contracts](https://docs.chain.link/data-streams/getting-started-hardhat\#deploy-the-upkeep-and-the-log-emitter-contracts)
Deploy an upkeep contract that is enabled to retrieve data from Data Streams. For this example, you will read from the ETH/USD stream with ID `0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782` on Arbitrum Sepolia. See the [Data Streams Crypto Addresses](https://docs.chain.link/data-streams/crypto-streams) page for a complete list of available crypto assets, IDs, and verifier proxy addresses.
Execute the following command to deploy the Chainlink Automation upkeep contract and the Log Emitter contract to the Arbitrum Sepolia network.

```bash
npx hardhat deployAll --network arbitrumSepolia
```
Expect output similar to the following in your terminal:

```bash
ℹ Deploying StreamsUpkeepRegistrar contract...
✔ StreamsUpkeepRegistrar deployed at: 0x48403478Aa021A9BC30Da0BDE47cbc155CcA8916
ℹ Deploying LogEmitter contract...
✔ LogEmitter deployed at: 0xD721337a827F9D814daEcCc3c7e72300af914BFE
✔ All contracts deployed successfully.
```
Save the deployed contract addresses for both contracts. You will use these addresses later.
### [Fund the upkeep contract](https://docs.chain.link/data-streams/getting-started-hardhat\#fund-the-upkeep-contract)
In this example, the upkeep contract pays for onchain verification of reports from Data Streams. The Automation subscription does not cover the cost. Transfer `1.5` testnet LINK to the upkeep contract address you saved earlier. You can retrieve unused LINK later.

```bash
npx hardhat transfer-link --recipient --amount 1500000000000000000 --network arbitrumSepolia
```
Replace `` with the address of the `StreamsUpkeepRegistrar` contract you saved earlier.
Expect output similar to the following in your terminal:

```bash
ℹ Starting LINK transfer from to the streams upkeep contract at 0xD721337a827F9D814daEcCc3c7e72300af914BFE
ℹ LINK token address: 0xb1D4538B4571d411F07960EF2838Ce337FE1E80E
ℹ LINK balance of sender 0x45C90FBb5acC1a5c156a401B56Fea55e69E7669d is 6.5 LINK
✔ 1.5 LINK were sent from 0x45C90FBb5acC1a5c156a401B56Fea55e69E7669d to 0xD721337a827F9D814daEcCc3c7e72300af914BFE. Transaction Hash: 0xf241bf4415ec081325ccd8ec3d54432e424afd16f1c81fa78b291ae9a0c03ce2
```
### [Register and fund the upkeep](https://docs.chain.link/data-streams/getting-started-hardhat\#register-and-fund-the-upkeep)
Programmatically register and fund a new `Log Trigger` upkeep with 1 LINK:

```bash
npx hardhat registerAndFundUpkeep --streams-upkeep --log-emitter --network arbitrumSepolia
```
Replace `` and `` with the addresses of your `StreamsUpkeepRegistrar` and `LogEmitter` contracts.
Expect output similar to the following in your terminal:

```bash
✔ Upkeep registered and funded with 1 LINK successfully.
```
### [Emit a log](https://docs.chain.link/data-streams/getting-started-hardhat\#emit-a-log)
Now, you can use your emitter contract to emit a log and initiate the upkeep, which retrieves data for the specified stream ID.

```bash
npx hardhat emitLog --log-emitter --network arbitrumSepolia
```
Replace `` with the address of your `LogEmitter` contract.
Expect output similar to the following in your terminal:

```bash
✔ Log emitted successfully in transaction: 0x236ee95faade12d1b6d497ee2e51ddf957f7d4986ffe51d784b923081ed440ff
```
After the transaction is complete, the log is emitted, and the upkeep is triggered.
### [View the retrieved price](https://docs.chain.link/data-streams/getting-started-hardhat\#view-the-retrieved-price)
The retrieved price is stored in the `lastDecodedPrice` contract variable and emitted in the logs. To see the price retrieved by the `StreamsUpkeepRegistrar` contract:

```bash
npx hardhat getLastRetrievedPrice --streams-upkeep --network arbitrumSepolia
```
Replace `` with the address of your `StreamsUpkeepRegistrar` contract.
Expect output similar to the following in your terminal:

```bash
✔ Last Retrieved Price: 2945878120219995000000
```
The answer on the ETH/USD stream uses 18 decimal places, so an answer of `2945878120219995000000` indicates an ETH/USD price of 2,945.878120219995. Some streams may use a different number of decimal places for answers. See the [Data Streams Crypto Addresses](https://docs.chain.link/data-streams/crypto-streams) page for more information.
Alternatively, you can view the price emitted in the logs for your upkeep transaction.
You can find the upkeep transaction hash at [Chainlink Automation UI](https://automation.chain.link/arbitrum-sepolia) and view the transaction logs in the [Arbitrum Sepolia explorer](https://sepolia.arbiscan.io/).
## [Examine the code](https://docs.chain.link/data-streams/getting-started-hardhat\#examine-the-code)
The example code you deployed has all the interfaces and functions required to work with Chainlink Automation as an upkeep contract. It follows a similar flow to the trading flow in the [Architecture](https://docs.chain.link/data-streams/architecture#example-trading-flow-using-streams-trade) documentation but uses a basic log emitter to simulate the client contract that would initiate a `StreamsLookup`. After the contract receives and verifies the report, `performUpkeep` stores the price from the report in the `lastDecodedPrice` and emits a `PriceUpdate` log message with the price. You could modify this to use the data in a way that works for your specific use case and application.
The code example uses `revert` with `StreamsLookup` to convey call information about what streams to retrieve. See the [EIP-3668 rationale](https://eips.ethereum.org/EIPS/eip-3668#rationale) for more information about how to use `revert` in this way.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Common} from "@chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol";
import {StreamsLookupCompatibleInterface} from "@chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol";
import {ILogAutomation, Log} from "@chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol";
import {IRewardManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol";
import {IVerifierFeeManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol";
import {IERC20} from "@chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol";
import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol";
/**
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE FOR DEMONSTRATION PURPOSES.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
/**
* @dev Defines the parameters required to register a new upkeep.
* @param name The name of the upkeep to be registered.
* @param encryptedEmail An encrypted email address associated with the upkeep (optional).
* @param upkeepContract The address of the contract that requires upkeep.
* @param gasLimit The maximum amount of gas to be used for the upkeep execution.
* @param adminAddress The address that will have administrative privileges over the upkeep.
* @param triggerType An identifier for the type of trigger that initiates the upkeep (`1` for event-based).
* @param checkData Data passed to the checkUpkeep function to simulate conditions for triggering upkeep.
* @param triggerConfig Configuration parameters specific to the trigger type.
* @param offchainConfig Off-chain configuration data, if applicable.
* @param amount The amount of LINK tokens to fund the upkeep registration.
*/
struct RegistrationParams {
string name;
bytes encryptedEmail;
address upkeepContract;
uint32 gasLimit;
address adminAddress;
uint8 triggerType;
bytes checkData;
bytes triggerConfig;
bytes offchainConfig;
uint96 amount;
}
/**
* @dev Interface for the Automation Registrar contract.
*/
interface AutomationRegistrarInterface {
/**
* @dev Registers a new upkeep contract with Chainlink Automation.
* @param requestParams The parameters required for the upkeep registration, encapsulated in `RegistrationParams`.
* @return upkeepID The unique identifier for the registered upkeep, used for future interactions.
*/
function registerUpkeep(
RegistrationParams calldata requestParams
) external returns (uint256);
}
// Custom interfaces for Data Streams: IVerifierProxy and IFeeManager
interface IVerifierProxy {
function verify(
bytes calldata payload,
bytes calldata parameterPayload
) external payable returns (bytes memory verifierResponse);
function s_feeManager() external view returns (IVerifierFeeManager);
}
interface IFeeManager {
function getFeeAndReward(
address subscriber,
bytes memory unverifiedReport,
address quoteAddress
) external returns (Common.Asset memory, Common.Asset memory, uint256);
function i_linkAddress() external view returns (address);
function i_nativeAddress() external view returns (address);
function i_rewardManager() external view returns (address);
}
contract StreamsUpkeepRegistrar is
ILogAutomation,
StreamsLookupCompatibleInterface
{
error InvalidReportVersion(uint16 version); // Thrown when an unsupported report version is provided to verifyReport.
LinkTokenInterface public immutable i_link;
AutomationRegistrarInterface public immutable i_registrar;
/**
* @dev Represents a data report from a Data Streams feed for v3 schema (crypto feeds).
* The `price`, `bid`, and `ask` values are carried to either 8 or 18 decimal places, depending on the feed.
* For more information, see https://docs.chain.link/data-streams/crypto-streams and https://docs.chain.link/data-streams/reference/report-schema
*/
struct ReportV3 {
bytes32 feedId; // The feed ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median price (8 or 18 decimals).
int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation (8 or 18 decimals).
int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation (8 or 18 decimals).
}
/**
* @dev Represents a data report from a Data Streams feed for v4 schema (RWA feeds).
* The `price` value is carried to either 8 or 18 decimal places, depending on the feed.
* The `marketStatus` indicates whether the market is currently open. Possible values: `0` (`Unknown`), `1` (`Closed`), `2` (`Open`).
* For more information, see https://docs.chain.link/data-streams/rwa-streams and https://docs.chain.link/data-streams/reference/report-schema-v4
*/
struct ReportV4 {
bytes32 feedId; // The feed ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median benchmark price (8 or 18 decimals).
uint32 marketStatus; // The DON's consensus on whether the market is currently open.
}
struct Quote {
address quoteAddress;
}
event PriceUpdate(int192 indexed price);
IVerifierProxy public verifier;
address public FEE_ADDRESS;
string public constant DATASTREAMS_FEEDLABEL = "feedIDs";
string public constant DATASTREAMS_QUERYLABEL = "timestamp";
int192 public lastDecodedPrice;
uint256 s_upkeepID;
bytes public s_LogTriggerConfig;
// Find a complete list of IDs at https://docs.chain.link/data-streams/crypto-streams
string[] public feedIds;
constructor(
address _verifier,
LinkTokenInterface link,
AutomationRegistrarInterface registrar,
string[] memory _feedIds
) {
verifier = IVerifierProxy(_verifier);
i_link = link;
i_registrar = registrar;
feedIds = _feedIds;
}
/**
* @notice Registers a new upkeep using the specified parameters and predicts its ID.
* @dev This function first approves the transfer of LINK tokens specified in `params.amount` to the Automation Registrar contract.
* It then registers the upkeep and stores its ID if registration is successful.
* Reverts if auto-approve is disabled or registration fails.
* @param params The registration parameters, including name, upkeep contract address, gas limit, admin address, trigger type, and funding amount.
*/
function registerAndPredictID(RegistrationParams memory params) public {
i_link.approve(address(i_registrar), params.amount);
uint256 upkeepID = i_registrar.registerUpkeep(params);
if (upkeepID != 0) {
s_upkeepID = upkeepID; // DEV - Use the upkeepID however you see fit
} else {
revert("auto-approve disabled");
}
}
/**
* @notice this is a new, optional function in streams lookup. It is meant to surface streams lookup errors.
* @return upkeepNeeded boolean to indicate whether the keeper should call performUpkeep or not.
* @return performData bytes that the keeper should call performUpkeep with, if
* upkeep is needed. If you would like to encode data to decode later, try `abi.encode`.
*/
function checkErrorHandler(
uint256 /*errCode*/,
bytes memory /*extraData*/
) external pure returns (bool upkeepNeeded, bytes memory performData) {
return (true, "0");
// Hardcoded to always perform upkeep.
// Read the StreamsLookup error handler guide for more information.
// https://docs.chain.link/chainlink-automation/guides/streams-lookup-error-handler
}
// This function uses revert to convey call information.
// See https://eips.ethereum.org/EIPS/eip-3668#rationale for details.
function checkLog(
Log calldata log,
bytes memory
) external returns (bool upkeepNeeded, bytes memory performData) {
revert StreamsLookup(
DATASTREAMS_FEEDLABEL,
feedIds,
DATASTREAMS_QUERYLABEL,
log.timestamp,
""
);
}
// The Data Streams report bytes is passed here.
// extraData is context data from feed lookup process.
// Your contract may include logic to further process this data.
// This method is intended only to be simulated offchain by Automation.
// The data returned will then be passed by Automation into performUpkeep
function checkCallback(
bytes[] calldata values,
bytes calldata extraData
) external pure returns (bool, bytes memory) {
return (true, abi.encode(values, extraData));
}
// function will be performed onchain
function performUpkeep(bytes calldata performData) external {
// Decode the performData bytes passed in by CL Automation.
// This contains the data returned by your implementation in checkCallback().
(bytes[] memory signedReports, bytes memory extraData) = abi.decode(
performData,
(bytes[], bytes)
);
bytes memory unverifiedReport = signedReports[0];
(, /* bytes32[3] reportContextData */ bytes memory reportData) = abi
.decode(unverifiedReport, (bytes32[3], bytes));
// Extract report version from reportData
uint16 reportVersion = (uint16(uint8(reportData[0])) << 8) |
uint16(uint8(reportData[1]));
// Validate report version
if (reportVersion != 3 && reportVersion != 4) {
revert InvalidReportVersion(uint8(reportVersion));
}
// Report verification fees
IFeeManager feeManager = IFeeManager(address(verifier.s_feeManager()));
IRewardManager rewardManager = IRewardManager(
address(feeManager.i_rewardManager())
);
address feeTokenAddress = feeManager.i_linkAddress();
(Common.Asset memory fee, , ) = feeManager.getFeeAndReward(
address(this),
reportData,
feeTokenAddress
);
// Approve rewardManager to spend this contract's balance in fees
IERC20(feeTokenAddress).approve(address(rewardManager), fee.amount);
// Verify the report
bytes memory verifiedReportData = verifier.verify(
unverifiedReport,
abi.encode(feeTokenAddress)
);
// Decode verified report data into the appropriate Report struct based on reportVersion
if (reportVersion == 3) {
// v3 report schema
ReportV3 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV3)
);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
} else if (reportVersion == 4) {
// v4 report schema
ReportV4 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV4)
);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
}
}
}
```
[Open in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/StreamsUpkeepRegistrar.sol&autoCompile=true) [What is Remix?](https://docs.chain.link/getting-started/conceptual-overview#what-is-remix)
### [Initializing the contract](https://docs.chain.link/data-streams/getting-started-hardhat\#initializing-the-contract)
When you deploy the contract, you define:
1. The verifier proxy address that you can find on the [Data Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page. The `IVerifierProxy` interface provides the following functions:
- The `s_feeManager` function to estimate the verification fees.
- The `verify` function to verify the report onchain.
2. The LINK token address. This address is used to register and fund your upkeep. You can find the LINK token address on the [Chainlink Token Addresses](https://docs.chain.link/resources/link-token-contracts) page.
3. The registrar's contract address. This address is used to register your upkeep. You can find the registrar contract addresses on the [Chainlink Automation Supported Networks](https://docs.chain.link/chainlink-automation/overview/supported-networks) page.
### [Funding the upkeep contract](https://docs.chain.link/data-streams/getting-started-hardhat\#funding-the-upkeep-contract)
In this example, you must fund the `StreamsUpkeepRegistrar` contract with testnet LINK tokens to pay the onchain report verification fees. You can use the [`transfer-link`](https://github.com/smartcontractkit/smart-contract-examples/blob/main/data-streams/getting-started/hardhat/tasks/transfer-link.js) task to transfer LINK tokens to the `StreamsUpkeepRegistrar` contract you deployed.
The `transfer-link` Hardhat task sets up the necessary parameters for the LINK token transfer and submits the transfer request to the LINK token contract using the `transfer` function.
**Note:** Funding the `StreamsUpkeepRegistrar` contract is distinct from funding your Chainlink Automation upkeep to pay the fees to perform the upkeep.
### [Registering the upkeep](https://docs.chain.link/data-streams/getting-started-hardhat\#registering-the-upkeep)
You need to register your log-triggered upkeep with the Chainlink Automation registrar. You can use the [`registerAndFundLogUpkeep`](https://github.com/smartcontractkit/smart-contract-examples/blob/main/data-streams/getting-started/hardhat/tasks/registerAndFundLogUpkeep.js) task to programmatically register the `StreamsUpkeepRegistrar` and `LogEmitter` contracts with the Chainlink Automation registrar. The task also funds the upkeep with 1 testnet LINK token.
The `registerAndFundLogUpkeep` Hardhat task sets up the necessary parameters for upkeep registration, including trigger configuration for a Log Emitter contract, and submits the registration request to the registrar contract via the `registerAndPredictID` function.
You can use the [Chainlink Automation UI](https://automation.chain.link/) to view the registered upkeep and the upkeep's configuration.
### [Emitting a log, retrieving, and verifying the report](https://docs.chain.link/data-streams/getting-started-hardhat\#emitting-a-log-retrieving-and-verifying-the-report)
You can use the [`emitLog` task](https://github.com/smartcontractkit/smart-contract-examples/blob/main/data-streams/getting-started/hardhat/tasks/emitLog.js) to emit a log from the `LogEmitter` contract.
1. The emitted log triggers the Chainlink Automation upkeep.
2. Chainlink Automation then uses `StreamsLookup` to retrieve a signed report from the Data Streams Aggregation Network, returns the data in a callback ( `checkCallback`), and runs the `performUpkeep` function on your registered upkeep contract.
3. The `performUpkeep` function calls the `verify` function on the verifier contract to verify the report onchain.
4. In this example, the `performUpkeep` function also stores the price from the report in the `lastDecodedPrice` state variable and emits a `PriceUpdate` log message with the price.
### [Viewing the retrieved price](https://docs.chain.link/data-streams/getting-started-hardhat\#viewing-the-retrieved-price)
The [`getLastRetrievedPrice`](https://github.com/smartcontractkit/smart-contract-examples/blob/main/data-streams/getting-started/hardhat/tasks/getLastRetrievedPrice.js) Hardhat task retrieves the last price updated by the `performUpkeep` function in the `lastDecodedPrice` state variable of the `StreamsUpkeepRegistrar` contract.
### [Feed ID types and conversion](https://docs.chain.link/data-streams/getting-started-hardhat\#feed-id-types-and-conversion)
Chainlink Data Streams uses different data types for feed IDs at different stages of the process:
- The [`StreamsLookup` error](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol#L6) requires feed IDs to be provided as an array of `string`,
- The decoded reports within the contract use `bytes32` types for feed IDs (see the [Report Schemas](https://docs.chain.link/data-streams/reference/report-schema) reference).
If your application needs to compare the feed ID(s) sent in the `StreamsLookup` with those received in the report(s), you must convert between `string` and `bytes32` types.
### [Optional: Handle Data Streams fetching errors offchain with `checkErrorHandler`](https://docs.chain.link/data-streams/getting-started-hardhat\#optional-handle-data-streams-fetching-errors-offchain-with-checkerrorhandler)
When Automation detects the triggering event, it runs the `checkLog` function of your upkeep contract, which includes a `StreamsLookup` revert custom error. The `StreamsLookup` revert enables your upkeep to fetch a report from the Data Streams Aggregation Network. If the report is fetched successfully, the `checkCallback` function is evaluated offchain. Otherwise, the `checkErrorHandler` function is evaluated offchain to determine what Automation should do next.
In this example, the `checkErrorHandler` is set to always return `true` for `upkeepNeeded`. This implies that the upkeep is always triggered, even if the report fetching fails. You can modify the `checkErrorHandler` function to handle errors offchain in a way that works for your specific use case. Read more about [using the StreamsLookup error handler](https://docs.chain.link/chainlink-automation/guides/streams-lookup-error-handler).
## What's next
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
- [\> Find the schema of data to expect from Data Streams reports.](https://docs.chain.link/data-streams/reference/report-schema)
- [\> Learn more about Log Trigger upkeeps](https://docs.chain.link/chainlink-automation/guides/log-trigger/)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Chainlink Streams Trade Guides
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Streams Trade guides](https://docs.chain.link/data-streams/tutorials/streams-trade\#overview)
Explore several guides to learn how to use the [Streams Trade](https://docs.chain.link/data-streams/streams-trade) implementation of Data Streams.
- [Getting Started](https://docs.chain.link/data-streams/getting-started): Learn how to read data from a Data Streams stream, verify the answer onchain, and store it.
- [Handle StreamsLookup errors](https://docs.chain.link/data-streams/tutorials/streams-trade/streams-trade-lookup-error-handler): Learn how to handle potential errors or edge cases in StreamsLookup upkeeps.
**Note**: Before implementing Streams Trade, ensure that Chainlink Automation is available on your desired network by checking the [Automation Supported Networks page](https://docs.chain.link/chainlink-automation/overview/supported-networks).
## Get the latest Chainlink content straight to your inbox.
Email Address
## Chainlink Streams Direct
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Streams Direct Reference](https://docs.chain.link/data-streams/reference/streams-direct\#overview)
### [API Interfaces](https://docs.chain.link/data-streams/reference/streams-direct\#api-interfaces)
- [REST API](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api) \- HTTP-based interface for simple integrations
- [WebSocket](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws) \- Real-time data streaming via WebSocket connection
### [SDK Integration](https://docs.chain.link/data-streams/reference/streams-direct\#sdk-integration)
- [Go SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk) \- Native Go language integration
- [Rust SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk) \- Native Rust language integration
### [Verification](https://docs.chain.link/data-streams/reference/streams-direct\#verification)
- [Onchain report data verification](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification) \- Verify the authenticity of received data on EVM chains
**Note:** You can also verify Data Streams reports on Solana using the [onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification) or [offchain](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification) integration methods.
## Get the latest Chainlink content straight to your inbox.
Email Address
## Streams Direct Guides
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
On this page
# [Streams Direct guides](https://docs.chain.link/data-streams/tutorials/streams-direct\#overview)
Explore several guides to learn how to use the [Streams Direct](https://docs.chain.link/data-streams/streams-direct) implementation with the [Data Streams SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk) for Go.
- [Fetch and decode reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api): Learn how to fetch and decode reports from the Data Streams Aggregation Network.
- [Stream and decode reports (WebSocket)](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws): Learn how to listen for real-time reports from the Data Streams Aggregation Network, decode the report data, and log their attributes.
- [Verify report data onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-onchain-verification): Learn how to verify onchain the integrity of reports by confirming their authenticity as signed by the Decentralized Oracle Network (DON).
## Get the latest Chainlink content straight to your inbox.
Email Address
## Streams Trade Interface
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Streams Trade Interface](https://docs.chain.link/data-streams/reference/streams-trade-interface\#overview)
To retrieve and verify reports, Streams Trade requires several interfaces.
**Note**: Before implementing Streams Trade, ensure that Chainlink Automation is available on your desired network by checking the [Automation Supported Networks page](https://docs.chain.link/chainlink-automation/overview/supported-networks).
## [Automation interfaces](https://docs.chain.link/data-streams/reference/streams-trade-interface\#automation-interfaces)
- [StreamsLookupCompatibleInterface](https://docs.chain.link/chainlink-automation/reference/automation-interfaces#streamslookupcompatibleinterface)
- [ILogAutomation](https://docs.chain.link/chainlink-automation/reference/automation-interfaces#ilogautomation)
## [Data Streams interfaces](https://docs.chain.link/data-streams/reference/streams-trade-interface\#data-streams-interfaces)
- IVerifierProxy
- IFeeManager
In the code example for using Data Streams with Automation (Streams Trade), the interfaces are specified in the example itself.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Common} from "@chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol";
import {StreamsLookupCompatibleInterface} from "@chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol";
import {ILogAutomation, Log} from "@chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol";
import {IRewardManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol";
import {IVerifierFeeManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol";
import {IERC20} from "@chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol";
/**
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE FOR DEMONSTRATION PURPOSES.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
// Custom interfaces for IVerifierProxy and IFeeManager
interface IVerifierProxy {
/**
* @notice Verifies that the data encoded has been signed.
* correctly by routing to the correct verifier, and bills the user if applicable.
* @param payload The encoded data to be verified, including the signed
* report.
* @param parameterPayload Fee metadata for billing. For the current implementation this is just the abi-encoded fee token ERC-20 address.
* @return verifierResponse The encoded report from the verifier.
*/
function verify(
bytes calldata payload,
bytes calldata parameterPayload
) external payable returns (bytes memory verifierResponse);
function s_feeManager() external view returns (IVerifierFeeManager);
}
interface IFeeManager {
/**
* @notice Calculates the fee and reward associated with verifying a report, including discounts for subscribers.
* This function assesses the fee and reward for report verification, applying a discount for recognized subscriber addresses.
* @param subscriber The address attempting to verify the report. A discount is applied if this address
* is recognized as a subscriber.
* @param unverifiedReport The report data awaiting verification. The content of this report is used to
* determine the base fee and reward, before considering subscriber discounts.
* @param quoteAddress The payment token address used for quoting fees and rewards.
* @return fee The fee assessed for verifying the report, with subscriber discounts applied where applicable.
* @return reward The reward allocated to the caller for successfully verifying the report.
* @return totalDiscount The total discount amount deducted from the fee for subscribers
*/
function getFeeAndReward(
address subscriber,
bytes memory unverifiedReport,
address quoteAddress
) external returns (Common.Asset memory, Common.Asset memory, uint256);
function i_linkAddress() external view returns (address);
function i_nativeAddress() external view returns (address);
function i_rewardManager() external view returns (address);
}
contract StreamsUpkeep is ILogAutomation, StreamsLookupCompatibleInterface {
error InvalidReportVersion(uint16 version); // Thrown when an unsupported report version is provided to verifyReport.
/**
* @dev Represents a data report from a Data Streams stream for v3 schema (crypto streams).
* The `price`, `bid`, and `ask` values are carried to either 8 or 18 decimal places, depending on the stream.
* For more information, see https://docs.chain.link/data-streams/crypto-streams and https://docs.chain.link/data-streams/reference/report-schema
*/
struct ReportV3 {
bytes32 feedId; // The stream ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median price (8 or 18 decimals).
int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation (8 or 18 decimals).
int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation (8 or 18 decimals).
}
/**
* @dev Represents a data report from a Data Streams stream for v4 schema (RWA streams).
* The `price` value is carried to either 8 or 18 decimal places, depending on the stream.
* The `marketStatus` indicates whether the market is currently open. Possible values: `0` (`Unknown`), `1` (`Closed`), `2` (`Open`).
* For more information, see https://docs.chain.link/data-streams/rwa-streams and https://docs.chain.link/data-streams/reference/report-schema-v4
*/
struct ReportV4 {
bytes32 feedId; // The stream ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median benchmark price (8 or 18 decimals).
uint32 marketStatus; // The DON's consensus on whether the market is currently open.
}
struct Quote {
address quoteAddress;
}
IVerifierProxy public verifier;
address public FEE_ADDRESS;
string public constant DATASTREAMS_FEEDLABEL = "feedIDs";
string public constant DATASTREAMS_QUERYLABEL = "timestamp";
int192 public lastDecodedPrice;
// This example reads the ID for the ETH/USD report.
// Find a complete list of IDs at https://docs.chain.link/data-streams/crypto-streams.
string[] public feedIds = [\
"0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782"\
];
constructor(address _verifier) {
verifier = IVerifierProxy(_verifier);
}
// This function uses revert to convey call information.
// See https://eips.ethereum.org/EIPS/eip-3668#rationale for details.
function checkLog(
Log calldata log,
bytes memory
) external returns (bool upkeepNeeded, bytes memory performData) {
revert StreamsLookup(
DATASTREAMS_FEEDLABEL,
feedIds,
DATASTREAMS_QUERYLABEL,
log.timestamp,
""
);
}
/**
* @notice this is a new, optional function in streams lookup. It is meant to surface streams lookup errors.
* @return upkeepNeeded boolean to indicate whether the keeper should call performUpkeep or not.
* @return performData bytes that the keeper should call performUpkeep with, if
* upkeep is needed. If you would like to encode data to decode later, try `abi.encode`.
*/
function checkErrorHandler(
uint256 /*errCode*/,
bytes memory /*extraData*/
) external pure returns (bool upkeepNeeded, bytes memory performData) {
return (true, "0");
// Hardcoded to always perform upkeep.
// Read the StreamsLookup error handler guide for more information.
// https://docs.chain.link/chainlink-automation/guides/streams-lookup-error-handler
}
// The Data Streams report bytes is passed here.
// extraData is context data from stream lookup process.
// Your contract may include logic to further process this data.
// This method is intended only to be simulated offchain by Automation.
// The data returned will then be passed by Automation into performUpkeep
function checkCallback(
bytes[] calldata values,
bytes calldata extraData
) external pure returns (bool, bytes memory) {
return (true, abi.encode(values, extraData));
}
// function will be performed onchain
function performUpkeep(bytes calldata performData) external {
// Decode the performData bytes passed in by CL Automation.
// This contains the data returned by your implementation in checkCallback().
(bytes[] memory signedReports, bytes memory extraData) = abi.decode(
performData,
(bytes[], bytes)
);
bytes memory unverifiedReport = signedReports[0];
(, /* bytes32[3] reportContextData */ bytes memory reportData) = abi
.decode(unverifiedReport, (bytes32[3], bytes));
// Extract report version from reportData
uint16 reportVersion = (uint16(uint8(reportData[0])) << 8) |
uint16(uint8(reportData[1]));
// Validate report version
if (reportVersion != 3 && reportVersion != 4) {
revert InvalidReportVersion(uint8(reportVersion));
}
// Report verification fees
IFeeManager feeManager = IFeeManager(address(verifier.s_feeManager()));
IRewardManager rewardManager = IRewardManager(
address(feeManager.i_rewardManager())
);
address feeTokenAddress = feeManager.i_linkAddress();
(Common.Asset memory fee, , ) = feeManager.getFeeAndReward(
address(this),
reportData,
feeTokenAddress
);
// Approve rewardManager to spend this contract's balance in fees
IERC20(feeTokenAddress).approve(address(rewardManager), fee.amount);
// Verify the report
bytes memory verifiedReportData = verifier.verify(
unverifiedReport,
abi.encode(feeTokenAddress)
);
// Decode verified report data into the appropriate Report struct based on reportVersion
if (reportVersion == 3) {
// v3 report schema
ReportV3 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV3)
);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
} else if (reportVersion == 4) {
// v4 report schema
ReportV4 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV4)
);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
}
}
}
```
[Open in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/StreamsUpkeep.sol&autoCompile=true) [What is Remix?](https://docs.chain.link/getting-started/conceptual-overview#what-is-remix)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Liquidity-Weighted Prices
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Data Streams Liquidity-Weighted Bid-Ask Prices (LWBA)](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#overview)
Chainlink Data Streams provides [reports](https://docs.chain.link/data-streams/reference/report-schema) with a _Mid_ and _Liquidity-Weighted Bid and Ask (LWBA)_ prices. These three prices form a pricing spread that offers protocols insight into market activity based on the current state of the order books.
**Note**: At the moment, only [Crypto streams](https://docs.chain.link/data-streams/crypto-streams) provide LWBA prices.
## [Bid and Ask prices](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#bid-and-ask-prices)
### [What are Bid and Ask prices?](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#what-are-bid-and-ask-prices)
Bid and Ask prices appear in the order book of an exchange and represent the trading orders buyers and sellers actively submit. These prices drive potential market transactions.
On an exchange, the Mid price in the order book is derived from the midpoint between the best Bid and the best Ask price. While the Mid price serves as a useful reference, for instance, in calculating funding rates, it is important to note that it is not a price at which trades should be executed. Actual trades must match an open bid or ask.
- **Bid price**: The Bid price refers to the maximum price that a buyer is willing to pay for an asset. It represents the highest price at which a buyer would agree to buy.
- **Ask price**: The Ask price is the minimum price at which a seller is willing to sell their asset. It represents the lowest price at which a seller would agree to sell.
### [Key characteristics](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#key-characteristics)
- **Price spread**: The difference between the Ask and the Bid prices is the _spread_. A narrower spread typically indicates a more liquid market, whereas a wider spread can signify less liquidity or higher volatility.
- **Market orders**: When traders place market orders to buy or sell immediately, they accept the best available Ask or Bid prices from the market. This interaction drives immediate transactions but can also impact the market price if the order size is substantial compared to the available volume.
- **Liquidity and volume**: Bid and Ask prices are not static and can fluctuate based on the asset's trading volume and market liquidity. High liquidity generally results in a narrower spread, which enables more trading activity near this spread and facilitates smoother transactions without substantial impacts on the market price.
### [Role in Chainlink Data Streams](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#role-in-chainlink-data-streams)
In Chainlink Data Streams, Bid and Ask prices play a pivotal role in the construction of Liquidity-Weighted Bid and Ask (LWBA) prices.
## [What is a Liquidity-Weighted price?](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#what-is-a-liquidity-weighted-price)
A Liquidity-Weighted price considers the Bid and Ask prices based on the available liquidity at each price level in the order books. This method weights price data by the volume of assets available at each price point, and provides a more accurate reflection of market conditions where larger orders would significantly impact the price.
## [What are the benefits of LWBA prices?](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#what-are-the-benefits-of-lwba-prices)
Liquidity-weighted Bid and Ask prices help in several key areas:
- **Accuracy**: They offer a more precise measure of the market price that considers the volume available at different price levels and allows for true market sentiment to be reflected.
- **Risk Management**: They consider the market's depth and help protocols assess and manage their risk more effectively and dynamically during periods of high volatility.
- **Efficiency**: Liquidity-weighted prices facilitate smarter order execution, which accurately reflects realistic slippage and enhances the trading experience for traders and protocols by closely mirroring actual market conditions.
## [Use case examples](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#use-case-examples)
- **Derivatives trading**: Platforms can use LWBA prices to set more accurate strike prices in options markets or fair settlement prices in futures contracts.
- **Liquidity provision**: Automated market makers (AMMs) and other liquidity providers can use these prices to quote more accurate and realistic prices that reflect current market conditions.
- **Loan collateralization**: Lending platforms might use liquidity-weighted prices to determine more realistic valuations for collateral during loan issuance and liquidation processes, thereby reducing the risk of unfair liquidations.
## [Practical examples of LWBA prices](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#practical-examples-of-lwba-prices)
To better understand how LWBA prices are calculated and used, consider the following examples that illustrate their application in different market scenarios. Each example explains the calculation, highlights trading and risk management benefits, and discusses the spread between Bid and Ask prices.
### [Example 1: Market volatility](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#example-1-market-volatility)
**Scenario**: Assume the market experiences a sudden drop, leading to a scenario where most buy orders accumulate at a lower price point. Similarly, sellers might be inclined to lower their ask prices to exit positions quickly. The order book shows 10 units at $0.99 but a more substantial 100 units at $0.90.
**Order book**:
| Type | Price | Quantity |
| --- | --- | --- |
| Bid | $0.99 | 10 |
| Bid | $0.90 | 100 |
| Ask | $1.01 | 15 |
| Ask | $1.05 | 85 |
**LWBA Price Calculation**:
- Bid = ((10 x 0.99) + (100 x 0.90)) / 110 = $0.909
- Ask = ((15 x 1.01) + (85 x 1.05)) / 100 = $1.044
**Spread Calculation**: Ask - Bid = $1.044 - $0.909 = $0.135
The LWBA Bid price of $0.909 and Ask price of $1.044 provide a realistic snapshot of the market under volatile conditions. The spread of $0.135 illustrates a wider gap due to high volatility, impacts liquidity and indicates a less efficient market. This dual perspective helps traders and protocols manage risk by pricing assets closer to the most liquid market levels and offers a more cautious approach to valuation during market drops.
### [Example 2: Market stability](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#example-2-market-stability)
**Scenario**: In a stable market, traders place the bulk of buy and sell orders close to the current market prices, leading to high liquidity near these levels.
**Order book**:
| Type | Price | Quantity |
| --- | --- | --- |
| Bid | $0.98 | 90 |
| Bid | $0.99 | 10 |
| Ask | $1.00 | 50 |
| Ask | $1.01 | 50 |
**LWBA Price Calculation**:
- Bid = ((10 x 0.99) + (90 x 0.98)) / 100 = $0.981
- Ask = ((50 x 1.00) + (50 x 1.01)) / 100 = $1.005
**Spread Calculation**: Ask - Bid = $1.005 - $0.981 = $0.024
The LWBA Bid price of $0.981 and Ask price of $1.005 reflect the concentration of liquidity near the top price points, with a narrow spread of $0.024 that indicates a highly liquid and efficient market. This pricing accuracy allows traders to execute orders close to their desired price points with minimal slippage and enhances transaction cost efficiency and market predictiveness in stable conditions.
### [Conclusion](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices\#conclusion)
| Example | Weighted Bid Price | Weighted Ask Price | Spread | Market condition | Key benefit |
| --- | --- | --- | --- | --- | --- |
| 1 | $0.909 | $1.044 | $0.135 | High volatility | Aligns price with majority liquidity |
| 2 | $0.981 | $1.005 | $0.024 | Market stability | Minimizes slippage and improves price accuracy |
In these examples, Liquidity-Weighted Bid and Ask prices, along with the spread between them, adjust dynamically based on the actual distribution of orders within the market. By reflecting real-time liquidity and volume, these prices and spreads provide protocols and traders with critical information that enhances pricing accuracy, reduces trading risks, and increases efficiency across various market conditions.
## What's next
- [\> Find the list of available Stream IDs.](https://docs.chain.link/data-streams/crypto-streams)
- [\> Find the schema of data to expect from Data Streams reports.](https://docs.chain.link/data-streams/reference/report-schema)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Report Schemas Overview
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Report Schemas](https://docs.chain.link/data-streams/reference/report-schema-v4\#overview)
## Available Report Schemas
Choose the schema version you want to explore.
Real World Asset (RWA) Report Schema (v4)
[Cryptocurrency Report Schema (v3)](https://docs.chain.link/data-streams/reference/report-schema) [Real World Asset (RWA) Report Schema (v4)](https://docs.chain.link/data-streams/reference/report-schema-v4)
Real World Asset (RWA) streams adhere to the report schema outlined below.
## [Schema Fields](https://docs.chain.link/data-streams/reference/report-schema-v4\#schema-fields)
| Field | Type | Description |
| --- | --- | --- |
| `feedID` | `bytes32` | The unique identifier for the stream |
| `validFromTimestamp` | `uint32` | The earliest timestamp during which the price is valid |
| `observationsTimestamp` | `uint32` | The latest timestamp during which the price is valid |
| `nativeFee` | `uint192` | The cost to verify this report onchain when paying with the blockchain's native token |
| `linkFee` | `uint192` | The cost to verify this report onchain when paying with LINK |
| `expiresAt` | `uint32` | The expiration date of this report |
| `price` | `int192` | The DON's consensus median price for this report carried to 18 decimal places |
| `marketStatus` | `uint32` | The DON's consensus on whether the market is currently open. Possible values: `0` ( `Unknown`), `1` ( `Closed`), `2` ( `Open`). |
**Notes**:
- Future RWA streams may use different report schemas.
- [Bid and Ask](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices) values are not available for the first iteration of the RWA report schema (v4).
## Get the latest Chainlink content straight to your inbox.
Email Address
## Crypto Data Streams
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Data Streams Crypto streams](https://docs.chain.link/data-streams/crypto-streams?network=soneium&page=1\#overview)
To learn how to use Data Streams, see the [Data Streams Getting Started](https://docs.chain.link/data-streams/getting-started) page.
For LINK token and Faucet details, see the [LINK Token Contracts](https://docs.chain.link/resources/link-token-contracts?parent=dataFeeds) page.
## [Streams Verifier Network Addresses](https://docs.chain.link/data-streams/crypto-streams?network=soneium&page=1\#streams-verifier-network-addresses)
Apechain
+
Arbitrum
+
Avalanche
+
Base
+
Berachain
+
Blast
+
BNB Chain
+
Bob
+
Botanix
+
Ethereum
+
Gnosis
+
HashKey Chain
+
Hyperliquid
+
Ink
+
Lens
+
Linea
+
Mantle
+
MegaETH
+
Monad
+
opBNB
+
OP
+
Ronin
+
Scroll
+
Shibarium
+
Soneium
+
Sonic
+
Solana
+
Taiko
+
Unichain
+
World Chain
+
ZKSync
+
## [Mainnet Crypto Streams](https://docs.chain.link/data-streams/crypto-streams?network=soneium&page=1\#mainnet-crypto-streams)
## [Testnet Crypto Streams](https://docs.chain.link/data-streams/crypto-streams?network=soneium&page=1\#testnet-crypto-streams)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Chainlink Rust SDK
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Streams Direct SDK (Rust)](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#overview)
## Streams Direct SDKs
Choose the SDK version that matches your needs.
Rust SDK
[Go SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk) [Rust SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk)
The [Data Streams SDK for Rust](https://github.com/smartcontractkit/data-streams-sdk/tree/main/rust) provides a client library for interacting with Chainlink Data Streams. It offers both point-in-time data retrieval and real-time data streaming capabilities with built-in fault tolerance.
## [Requirements](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#requirements)
- Rust 1.70 or later
- Valid Data Streams API credentials
## [Features](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#features)
- **REST API Client**: Fetch point-in-time data from Data Streams
- **WebSocket Client**: Stream real-time data with automatic reconnection
- **Report Decoding**: Built-in support for decoding and validating multiple report formats (V3, V4)
- **High Availability**: WebSocket connection management with failover support
- **Tracing Support**: Optional logging via the [`tracing`](https://crates.io/crates/tracing) crate
- **Async/Await**: Built on Tokio for efficient async operations
## [Installation](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#installation)
Add the SDK to your project by including it in your `Cargo.toml`:

```toml
[dependencies]
data-streams-sdk = { git = "https://github.com/smartcontractkit/data-streams-sdk.git", subdir = "rust/crates/sdk" }
data-streams-report = { git = "https://github.com/smartcontractkit/data-streams-sdk.git", subdir = "rust/crates/report" }
```
### [Feature Flags](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#feature-flags)
The SDK provides several feature flags to customize its functionality:
- `"rest"`: Enables the REST API client (enabled by default)
- `"websocket"`: Enables the WebSocket client for real-time streaming (enabled by default)
- `"tracing"`: Enables logging with the `tracing` crate (optional)
- `"full"`: Enables all features (default)
## [Report Types](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#report-types)
The Rust SDK supports multiple report formats, including **V3 (Crypto)** and **V4 (RWA)**. For the complete list of fields and their detailed descriptions, refer to the dedicated schema pages:
- [V3 (Cryptocurrency) Report Schema](https://docs.chain.link/data-streams/reference/report-schema)
- [V4 (RWA) Report Schema](https://docs.chain.link/data-streams/reference/report-schema-v4)
Below are basic code snippets for decoding these reports with the SDK:
### [V3 Reports (Crypto Streams)](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#v3-reports-crypto-streams)

```rust
use data_streams_report::report::v3::ReportDataV3;
// After you get 'report_blob' (for example, from 'decode_full_report' or a contract call):
let report_data = ReportDataV3::decode(&report_blob)?;
// Access whichever fields you need:
println!("Benchmark Price: {}", report_data.benchmark_price);
println!("Bid: {}", report_data.bid);
println!("Ask: {}", report_data.ask);
// ... etc.
```
For more details on every field in V3 (Crypto) reports, see the [V3 report schema page](https://docs.chain.link/data-streams/reference/report-schema).
### [V4 Reports (RWA Streams)](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#v4-reports-rwa-streams)

```rust
use data_streams_report::report::v4::ReportDataV4;
let report_data = ReportDataV4::decode(&report_blob)?;
// Example usage:
println!("Price: {}", report_data.price);
println!("Market Status: {}", report_data.market_status);
// ... etc.
```
For more details on every field in V4 (RWA) reports, see the [V4 report schema page](https://docs.chain.link/data-streams/reference/report-schema-v4).
## [Authentication](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#authentication)
The SDK uses HMAC authentication for all API requests. Configure your credentials:

```rust
use data_streams_sdk::config::Config;
use std::env;
let api_key = env::var("API_KEY").expect("API_KEY must be set");
let user_secret = env::var("USER_SECRET").expect("USER_SECRET must be set");
let config = Config::new(
api_key,
user_secret,
"https://api.testnet-dataengine.chain.link".to_owned(),
"wss://ws.testnet-dataengine.chain.link".to_owned(),
)
.build()?;
```
Security best practices:
- Store credentials in environment variables
- Avoid hardcoding credentials in source code
- Use separate credentials for development and production
- Rotate credentials periodically
## [WebSocket Features](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#websocket-features)
### [High Availability Mode](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#high-availability-mode)

```rust
use data_streams_sdk::config::{Config, WebSocketHighAvailability};
let ws_urls = "wss://ws1.dataengine.chain.link,wss://ws2.dataengine.chain.link";
let config = Config::new(api_key, api_secret, rest_url, ws_urls)
// Enable WebSocket HA mode
.with_ws_ha(WebSocketHighAvailability::Enabled)
// Increase the max reconnection attempts (optional, default is 5)
.with_ws_max_reconnect(10)
.build()?;
```
- Multiple WebSocket endpoints
- Automatic failover on connection loss
- Parallel connections to reduce gaps in data
### [Connection Management](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#connection-management)
The SDK allows you to:
- Set `ws_max_reconnect`: The maximum number of reconnection attempts (default: 5)
- Enable HA for multiple WebSocket endpoints
- Optional `insecure_skip_verify` for TLS
Example:

```rust
use data_streams_sdk::config::{Config, InsecureSkipVerify, WebSocketHighAvailability};
let ws_urls = "wss://ws.testnet-dataengine.chain.link";
let config = Config::new(api_key, api_secret, rest_url, ws_urls)
.with_ws_ha(WebSocketHighAvailability::Enabled)
.with_ws_max_reconnect(5)
.with_insecure_skip_verify(InsecureSkipVerify::Enabled)
.build()?;
// Create and initialize the stream
let mut stream = Stream::new(&config, feed_ids).await?;
stream.listen().await?;
```
## [Error Handling](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#error-handling)
The SDK defines distinct error types:
- `ClientError` for REST-based issues (e.g., HTTP request failures)
- `StreamError` for WebSocket streaming issues
- `HmacError` for authentication/HMAC generation problems
Example:

```rust
use data_streams_sdk::client::Client;
use data_streams_sdk::client::ClientError;
match client.get_latest_report(feed_id).await {
Ok(report_response) => {
println!("Report: {:?}", report_response.report);
}
Err(ClientError::ApiError(e)) => {
eprintln!("Server returned an error: {}", e);
}
Err(e) => {
eprintln!("Some other request error: {}", e);
}
}
```
## [Examples](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#examples)
### [Step-by-Step Guides](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#step-by-step-guides)
- [Fetch and decode reports using the REST API](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust)
- [Stream and decode reports via WebSocket](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rust)
### [More Examples](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#more-examples)
The [SDK repository](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/docs/examples/) includes additional examples for common use cases:
- Fetching a single report, bulk reports, or paginated reports
- Compressing report data
- Simple WebSocket streaming
- Multiple WebSocket endpoints (HA)
## [Performance Considerations](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#performance-considerations)
- Reuse the same `Client` instance whenever possible
- Gracefully close WebSocket `Stream` objects when not in use ( `stream.close().await?`)
- Monitor memory usage if you expect large volumes of data
- Use timeouts or retry logic in your own application where needed
## [Configuration Reference](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#configuration-reference)
Below is a detailed guide to the available builder methods for the `ConfigBuilder`. Each method is **optional** but can help you tailor the SDK’s behavior for your specific needs.

```rust
pub struct ConfigBuilder {
// Enables High Availability (HA) for WebSocket connections
pub fn with_ws_ha(mut self, WebSocketHighAvailability) -> Self;
// Sets the max number of WebSocket reconnection attempts before giving up
pub fn with_ws_max_reconnect(mut self, usize) -> Self;
// Allows skipping TLS certificate verification (use with caution in production)
pub fn with_insecure_skip_verify(mut self, InsecureSkipVerify) -> Self;
// Provides a way to inspect HTTP responses for logging or debugging (REST calls only)
pub fn with_inspect_http_response(mut self, fn(&Response)) -> Self;
// Finalizes and validates the config
pub fn build(self) -> Result;
}
```
### [`with_ws_ha(WebSocketHighAvailability)`](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#with_ws_hawebsockethighavailability)
- Purpose: Enables or disables HA mode for WebSocket streaming.
- Values:
- `WebSocketHighAvailability::Enabled`: Maintains multiple WebSocket connections to different endpoints simultaneously.
- `WebSocketHighAvailability::Disabled`: Maintains a single connection.
- Default: `Disabled`.
- Example Use Case:

```rust
// When you want uninterrupted streaming even if one server goes down:
let config = Config::new(api_key, api_secret, rest_url, "wss://ws1,...,wss://wsN")
.with_ws_ha(WebSocketHighAvailability::Enabled)
.build()?;
```
### [`with_ws_max_reconnect(usize)`](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#with_ws_max_reconnectusize)
- Purpose: Sets the maximum number of reconnection attempts before the SDK stops trying.
- Default: `5`.
- Parameter: `usize` indicates how many times you want the SDK to attempt reconnecting after a connection failure.
- Example Use Case:

```rust
// If you want to be very persistent:
.with_ws_max_reconnect(20)
```
### [`with_insecure_skip_verify(InsecureSkipVerify)`](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#with_insecure_skip_verifyinsecureskipverify)
- Purpose: When set, it allows skipping TLS certificate verification.
- Values:
- `InsecureSkipVerify::Enabled`: Skips verification of certificates — useful for local dev or self-signed certs.
- `InsecureSkipVerify::Disabled`: Normal, secure certificate handling (recommended for production).
- Default: `Disabled`.
- Example Use Case:

```rust
// Useful in development when using self-signed certs or containers
.with_insecure_skip_verify(InsecureSkipVerify::Enabled)
```
### [`with_inspect_http_response(fn(&Response))`](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk\#with_inspect_http_responsefnresponse)
- Purpose: Allows you to provide a callback function that inspects any HTTP `Response` received by the REST client.
- Default: `None`. (No inspection)
- Example:

```rust
// Log every HTTP response's status code
.with_inspect_http_response(|response| {
println!("Received HTTP status: {}", response.status());
})
```
## What's next
- [\> Learn how to fetch and decode Data Streams reports using the Data Streams SDK](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust)
- [\> Learn how to stream and decode reports via a WebSocket connection using the Data Streams SDK](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rust)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Streams Direct WebSocket
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Streams Direct WebSocket](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws\#overview)
## [Domains](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws\#domains)
| Description | Testnet URL | Mainnet URL |
| --- | --- | --- |
| WebSocket endpoint to subscribe to price updates | wss://ws.testnet-dataengine.chain.link | wss://ws.dataengine.chain.link |
## [Authentication](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws\#authentication)
### [Headers](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws\#headers)
All routes require the following three headers for user authentication:
| Header | Description |
| --- | --- |
| `Authorization` | The user’s unique identifier, provided as a UUID (Universally Unique IDentifier). |
| `X-Authorization-Timestamp` | The current timestamp, with precision up to milliseconds. The timestamp must closely synchronize with the server time, allowing a maximum discrepancy of 5 seconds (by default). |
| `X-Authorization-Signature-SHA256` | The HMAC (Hash-based Message Authentication Code) signature, generated by hashing parts of the request and its metadata using SHA-256 with a shared secret key. |
## [WebSocket Connection](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws\#websocket-connection)
Establish a streaming WebSocket connection that sends reports for the given stream ID(s) after they are verified.
##### [Endpoint](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws\#endpoint)
**`/api/v1/ws`**
| Type | Parameter(s) |
| --- | --- |
| WebSocket | `feedIDs`: A comma-separated list of Data Streams stream IDs. |
##### [Sample request](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws\#sample-request)

```http
GET /api/v1/ws?feedIDs=,,...
```
##### [Sample response](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws\#sample-response)

```json
{
"report": {
"feedID": "hex encoded feedId",
"fullReport": "a blob containing the report context + body, can be passed unmodified to the contract for verification"
}
}
```
## [Error response codes](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws\#error-response-codes)
| Status Code | Description |
| --- | --- |
| 400 Bad Request | This error is triggered when:
- There is any missing/malformed query argument.
- Required headers are missing or provided with incorrect values. |
| 401 Unauthorized User | This error is triggered when:
- Authentication fails, typically because the HMAC signature provided by the client doesn't match the one expected by the server.
- A user requests access to a stream without the appropriate permission or that does not exist. |
| 500 Internal Server | Indicates an unexpected condition encountered by the server, preventing it from fulfilling the request. This error typically points to issues on the server side. |
## Get the latest Chainlink content straight to your inbox.
Email Address
## Fetch V3 Reports in Rust
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
On this page
# [Fetch and decode V3 reports using the Rust SDK](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#overview)
## Guide Versions
This guide is available in multiple versions. Choose the one that matches your needs.
Rust SDK - V3 reports for Crypto streams
[Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-go) [Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go) [Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust) [Rust SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust)
In this guide, you'll learn how to use Chainlink Data Streams with the _[Streams Direct](https://docs.chain.link/data-streams/streams-direct) implementation_ and the [Data Streams SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk) for Rust to fetch and decode [V3 reports](https://docs.chain.link/data-streams/reference/report-schema) for [Crypto streams](https://docs.chain.link/data-streams/crypto-streams) from the Data Streams Aggregation Network. You'll set up your Rust project, retrieve reports, decode them, and log their attributes.
## [Requirements](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#requirements)
- **Git**: Make sure you have Git installed. You can check your current version by running `git --version` in your terminal and download the latest version from the official [Git website](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) if necessary.
- **Rust**: Make sure you have Rust installed. You can install Rust by following the instructions on the official [Rust website](https://www.rust-lang.org/tools/install).
- **API Credentials**: Access to the Streams Direct implementation requires API credentials. If you haven't already, [contact us](https://chainlinkcommunity.typeform.com/datastreams?typeform-source=docs.chain.link#ref_id=docs) to request mainnet or testnet access.
## [Guide](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#guide)
You'll start with the set up of your Rust project. Next, you'll fetch and decode reports for crypto streams and log their attributes to your terminal.
### [Set up your Rust project](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#set-up-your-rust-project)
1. Create a new directory for your project and navigate to it:

```bash
mkdir my-data-streams-project && cd my-data-streams-project
```
2. Initialize a new Rust project:

```bash
cargo init
```
3. Add the Data Streams SDK to your `Cargo.toml`:

```toml
[dependencies]
data-streams-sdk = { git = "https://github.com/smartcontractkit/data-streams-sdk.git", subdir = "rust/crates/sdk" }
data-streams-report = { git = "https://github.com/smartcontractkit/data-streams-sdk.git", subdir = "rust/crates/report" }
tokio = { version = "1.4", features = ["full"] }
hex = "0.4"
```
### [Fetch and decode a report with a single stream](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#fetch-and-decode-a-report-with-a-single-stream)
1. Replace the contents of `src/main.rs` with the following code:

```rust
use data_streams_report::feed_id::ID;
use data_streams_report::report::{decode_full_report, v3::ReportDataV3};
use data_streams_sdk::client::Client;
use data_streams_sdk::config::Config;
use std::env;
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box> {
// Get feed ID from command line arguments
let args: Vec = env::args().collect();
if args.len() < 2 {
eprintln!("Usage: cargo run [FeedID]");
std::process::exit(1);
}
let feed_id_input = &args[1];
// Get API credentials from environment variables
let api_key = env::var("API_KEY").expect("API_KEY must be set");
let api_secret = env::var("API_SECRET").expect("API_SECRET must be set");
// Initialize the configuration
let config = Config::new(
api_key,
api_secret,
"https://api.testnet-dataengine.chain.link".to_string(),
"wss://api.testnet-dataengine.chain.link/ws".to_string(),
)
.build()?;
// Initialize the client
let client = Client::new(config)?;
// Parse the feed ID
let feed_id = ID::from_hex_str(feed_id_input)?;
// Fetch the latest report
let response = client.get_latest_report(feed_id).await?;
println!("\nRaw report data: {:?}\n", response.report);
// Decode the report
let full_report = hex::decode(&response.report.full_report[2..])?;
let (_report_context, report_blob) = decode_full_report(&full_report)?;
let report_data = ReportDataV3::decode(&report_blob)?;
// Print decoded report details
println!("\nDecoded Report for Stream ID {}:", feed_id_input);
println!("------------------------------------------");
println!("Observations Timestamp: {}", response.report.observations_timestamp);
println!("Benchmark Price : {}", report_data.benchmark_price);
println!("Bid : {}", report_data.bid);
println!("Ask : {}", report_data.ask);
println!("Valid From Timestamp : {}", response.report.valid_from_timestamp);
println!("Expires At : {}", report_data.expires_at);
println!("Link Fee : {}", report_data.link_fee);
println!("Native Fee : {}", report_data.native_fee);
println!("------------------------------------------");
Ok(())
}
```
2. Set up your API credentials as environment variables:

```bash
export API_KEY=""
export API_SECRET=""
```
Replace `` and `` with your API credentials.
3. For this example, you will read from the ETH/USD crypto stream. This stream ID is `0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782`. See the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page for a complete list of available crypto assets.
Build and run your application:

```bash
cargo run -- 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
```
Expect output similar to the following in your terminal:

```bash
Raw report data: Report { feed_id: 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782, valid_from_timestamp: 1734124400, observations_timestamp: 1734124400, full_report: "0x0006f9b553e393ced311551efd30d1decedb63d76ad41737462e2cdbbdff1578000000000000000000000000000000000000000000000000000000004f56930f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba78200000000000000000000000000000000000000000000000000000000675ca37000000000000000000000000000000000000000000000000000000000675ca3700000000000000000000000000000000000000000000000000000174be1bd8758000000000000000000000000000000000000000000000000000cb326ce8c3ea800000000000000000000000000000000000000000000000000000000675df4f00000000000000000000000000000000000000000000000d3a30bcc15e207c0000000000000000000000000000000000000000000000000d3a1557b5e634060200000000000000000000000000000000000000000000000d3ab99a974ff10f400000000000000000000000000000000000000000000000000000000000000000292bdd75612560e46ed9b0c2437898f81eb0e18b6b902a161b9708e9177175cf3b8ef2b279f230f766fb29306250ee90856516ee349ca42b2d7fb141deb006745000000000000000000000000000000000000000000000000000000000000000221c156e80276827e1bfeb6542ab064dfa958f5be955f516fb62b1c93437472c31cc65fcaba68c9d661701190bc32025a0690af0eefe027ac218fd15c588dd4d5" }
Decoded Report for Stream ID 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782:
------------------------------------------
Observations Timestamp: 1734124400
Benchmark Price : 3904011708000000000000
Bid : 3903888333211164500000
Ask : 3904628100124598400000
Valid From Timestamp : 1734124400
Expires At : 1734210800
Link Fee : 3574678975954600
Native Fee : 25614677280600
------------------------------------------
```
#### [Decoded report details](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#decoded-report-details)
The decoded report details include:
| Attribute | Value | Description |
| --- | --- | --- |
| `Stream ID` | `0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782` | The unique identifier for the stream. In this example, the stream is for ETH/USD. |
| `Observations Timestamp` | `1734124400` | The timestamp indicating when the data was captured. |
| `Benchmark Price` | `3904011708000000000000` | The observed price in the report, with 18 decimals. For readability: `3,904.0117080000000` USD per ETH. |
| `Bid` | `3903888333211164500000` | The highest price a buyer is willing to pay for an asset, with 18 decimals. For readability: `3,903.8883332111645` USD per ETH. Learn more about the [Bid price](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices). |
| `Ask` | `3904628100124598400000` | The lowest price a seller is willing to accept for an asset, with 18 decimals. For readability: `3,904.6281001245984` USD per ETH. Learn more about the [Ask price](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices). |
| `Valid From Timestamp` | `1734124400` | The start validity timestamp for the report, indicating when the data becomes relevant. |
| `Expires At` | `1734210800` | The expiration timestamp of the report, indicating the point at which the data becomes outdated. |
| `Link Fee` | `3574678975954600` | The fee to pay in LINK tokens for the onchain verification of the report data. With 18 decimals. For readability: `0.003574678975954600` LINK. **Note:** This example fee is not indicative of actual fees. |
| `Native Fee` | `25614677280600` | The fee to pay in the native blockchain token (e.g., ETH on Ethereum) for the onchain verification of the report data. With 18 decimals. For readability: `0.0000256146772806000` ETH. **Note:** This example fee is not indicative of actual fees. |
#### [Payload for onchain verification](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#payload-for-onchain-verification)
In this guide, you log and decode the `full_report` payload to extract the report data. In a
production environment, you should verify the data to ensure its integrity and authenticity. Refer to the
[Verify report data onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-onchain-verification) guide.
## [Explanation](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#explanation)
### [Initializing the API client and configuration](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#initializing-the-api-client-and-configuration)
The API client is initialized in two steps:
1. [`Config::new`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/config.rs#L131) creates a configuration with your API credentials and endpoints. This function:
- Validates your API key and secret
- Sets up the REST API endpoint for data retrieval
- Configures optional settings like TLS verification
2. [`Client::new`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/client.rs#L131) creates the HTTP client with your configuration. This client:
- Handles authentication automatically
- Manages HTTP connections
- Implements retry logic for failed requests
### [Fetching reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#fetching-reports)
The SDK provides several methods to fetch reports through the REST API:
1. Latest report: [`get_latest_report`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/client.rs#L165) retrieves the most recent report for a feed:
- Takes a feed ID as input
- Returns a single report with the latest timestamp
- Useful for applications that need the most current data
2. Historical report: [`get_report`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/client.rs#L242) fetches a report at a specific timestamp:
- Takes both feed ID and timestamp
- Returns the report closest to the requested timestamp
- Helpful for historical analysis or verification
Each API request automatically:
- Generates HMAC authentication headers
- Includes proper timestamps
- Handles HTTP response status codes
- Deserializes the JSON response into Rust structures
### [Decoding reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#decoding-reports)
Reports are decoded in three stages:
1. Hex decoding: The `full_report` field comes as a hex string prefixed with "0x":

```rust
let full_report = hex::decode(&response.report.full_report[2..])?;
```
2. Report separation: [`decode_full_report`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/report/src/report.rs#L77) splits the binary data:
- Extracts the report context (metadata)
- Isolates the report blob (actual data)
- Validates the report format
3. Data extraction: [`ReportDataV3::decode`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/report/src/report/v3.rs#L80) parses the report blob into structured data:
- Benchmark price (18 decimal places)
- Bid and ask prices for [liquidity-weighted pricing](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices)
- Fee information for onchain verification
- Timestamp information
### [Error handling](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust\#error-handling)
The example demonstrates Rust's robust error handling:
1. Type-safe errors:
- Uses custom error types for different failure scenarios
- Implements the `Error` trait for proper error propagation
- Provides detailed error messages for debugging
2. Error propagation:
- Uses the `?` operator for clean error handling
- Converts errors between types when needed
- Bubbles up errors to the main function
3. Input validation:
- Checks command-line arguments
- Validates environment variables
- Verifies feed ID format
The decoded data can be used for further processing, analysis, or display in your application. For production environments, you must verify the data onchain using the provided `full_report` payload.
## What's next
- [\> Learn how to stream and decode reports via a WebSocket connection](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rust)
- [\> Learn how to verify your data onchain](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification)
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Onchain Report Verification
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Onchain report verification (EVM chains)](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification\#overview)
## [Verify reports onchain](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification\#verify-reports-onchain)
To verify data onchain on EVM chains, Streams Direct requires several Solidity interfaces.
The primary onchain interaction occurs between the `IVerifierProxy` interface and your protocol's client contract. Find the Verifier proxy address for each stream on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
### [Interfaces](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification\#interfaces)
- IVerifierProxy
- IFeeManager
In the current code example for verifying reports onchain using Streams Direct, these interfaces are specified in the example itself. Imports for these interfaces will be available in the future.
### [Contract example to verify report data onchain](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification\#contract-example-to-verify-report-data-onchain)
This contract example allows you to verify reports and pay the verification fee in LINK tokens. Your contract must have sufficient LINK tokens to pay for the verification fee. Learn how to [fund your contract with LINK tokens](https://docs.chain.link/resources/fund-your-contract).

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Common} from "@chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol";
import {IRewardManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol";
import {IVerifierFeeManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol";
import {IERC20} from "@chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol";
using SafeERC20 for IERC20;
/**
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE FOR DEMONSTRATION PURPOSES.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
// Custom interfaces for IVerifierProxy and IFeeManager
interface IVerifierProxy {
/**
* @notice Verifies that the data encoded has been signed correctly by routing to the correct verifier, and bills the user if applicable.
* @param payload The encoded data to be verified, including the signed report.
* @param parameterPayload Fee metadata for billing. In the current implementation, this consists of the abi-encoded address of the ERC-20 token used for fees.
* @return verifierResponse The encoded report from the verifier.
*/
function verify(
bytes calldata payload,
bytes calldata parameterPayload
) external payable returns (bytes memory verifierResponse);
/**
* @notice Verifies multiple reports in bulk, ensuring that each is signed correctly, routes them to the appropriate verifier, and handles billing for the verification process.
* @param payloads An array of encoded data to be verified, where each entry includes the signed report.
* @param parameterPayload Fee metadata for billing. In the current implementation, this consists of the abi-encoded address of the ERC-20 token used for fees.
* @return verifiedReports An array of encoded reports returned from the verifier.
*/
function verifyBulk(
bytes[] calldata payloads,
bytes calldata parameterPayload
) external payable returns (bytes[] memory verifiedReports);
function s_feeManager() external view returns (IVerifierFeeManager);
}
interface IFeeManager {
/**
* @notice Calculates the fee and reward associated with verifying a report, including discounts for subscribers.
* This function assesses the fee and reward for report verification, applying a discount for recognized subscriber addresses.
* @param subscriber The address attempting to verify the report. A discount is applied if this address is recognized as a subscriber.
* @param unverifiedReport The report data awaiting verification. The content of this report is used to determine the base fee and reward, before considering subscriber discounts.
* @param quoteAddress The payment token address used for quoting fees and rewards.
* @return fee The fee assessed for verifying the report, with subscriber discounts applied where applicable.
* @return reward The reward allocated to the caller for successfully verifying the report.
* @return totalDiscount The total discount amount deducted from the fee for subscribers.
*/
function getFeeAndReward(
address subscriber,
bytes memory unverifiedReport,
address quoteAddress
) external returns (Common.Asset memory, Common.Asset memory, uint256);
function i_linkAddress() external view returns (address);
function i_nativeAddress() external view returns (address);
function i_rewardManager() external view returns (address);
}
/**
* @dev This contract implements functionality to verify Data Streams reports from
* the Streams Direct API or WebSocket connection, with payment in LINK tokens.
*/
contract ClientReportsVerifier {
error NothingToWithdraw(); // Thrown when a withdrawal attempt is made but the contract holds no tokens of the specified type.
error NotOwner(address caller); // Thrown when a caller tries to execute a function that is restricted to the contract's owner.
error InvalidReportVersion(uint16 version); // Thrown when an unsupported report version is provided to verifyReport.
/**
* @dev Represents a data report from a Data Streams stream for v3 schema (crypto streams).
* The `price`, `bid`, and `ask` values are carried to either 8 or 18 decimal places, depending on the stream.
* For more information, see https://docs.chain.link/data-streams/crypto-streams and https://docs.chain.link/data-streams/reference/report-schema
*/
struct ReportV3 {
bytes32 feedId; // The stream ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median price (8 or 18 decimals).
int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation (8 or 18 decimals).
int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation (8 or 18 decimals).
}
/**
* @dev Represents a data report from a Data Streams stream for v4 schema (RWA stream).
* The `price` value is carried to either 8 or 18 decimal places, depending on the stream.
* The `marketStatus` indicates whether the market is currently open. Possible values: `0` (`Unknown`), `1` (`Closed`), `2` (`Open`).
* For more information, see https://docs.chain.link/data-streams/rwa-streams and https://docs.chain.link/data-streams/reference/report-schema-v4
*/
struct ReportV4 {
bytes32 feedId; // The stream ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median benchmark price (8 or 18 decimals).
uint32 marketStatus; // The DON's consensus on whether the market is currently open.
}
IVerifierProxy public s_verifierProxy; // The VerifierProxy contract used for report verification.
address private s_owner; // The owner of the contract.
int192 public lastDecodedPrice; // Stores the last decoded price from a verified report.
event DecodedPrice(int192 price); // Event emitted when a report is successfully verified and decoded.
/**
* @param _verifierProxy The address of the VerifierProxy contract.
* You can find these addresses on https://docs.chain.link/data-streams/crypto-streams.
*/
constructor(address _verifierProxy) {
s_owner = msg.sender;
s_verifierProxy = IVerifierProxy(_verifierProxy);
}
/// @notice Checks if the caller is the owner of the contract.
modifier onlyOwner() {
if (msg.sender != s_owner) revert NotOwner(msg.sender);
_;
}
/**
* @notice Verifies an unverified data report and processes its contents, supporting both v3 and v4 report schemas.
* @dev Performs the following steps:
* - Decodes the unverified report to extract the report data.
* - Extracts the report version by reading the first two bytes of the report data.
* - The first two bytes correspond to the schema version encoded in the stream ID.
* - Schema version `0x0003` corresponds to report version 3 (for Crypto assets).
* - Schema version `0x0004` corresponds to report version 4 (for Real World Assets).
* - Validates that the report version is either 3 or 4; reverts with `InvalidReportVersion` otherwise.
* - Retrieves the fee manager and reward manager contracts.
* - Calculates the fee required for report verification using the fee manager.
* - Approves the reward manager to spend the calculated fee amount.
* - Verifies the report via the VerifierProxy contract.
* - Decodes the verified report data into the appropriate report struct (`ReportV3` or `ReportV4`) based on the report version.
* - Emits a `DecodedPrice` event with the price extracted from the verified report.
* - Updates the `lastDecodedPrice` state variable with the price from the verified report.
* @param unverifiedReport The encoded report data to be verified, including the signed report and metadata.
* @custom:reverts InvalidReportVersion(uint8 version) Thrown when an unsupported report version is provided.
*/
function verifyReport(bytes memory unverifiedReport) external {
// Retrieve fee manager and reward manager
IFeeManager feeManager = IFeeManager(
address(s_verifierProxy.s_feeManager())
);
IRewardManager rewardManager = IRewardManager(
address(feeManager.i_rewardManager())
);
// Decode unverified report to extract report data
(, bytes memory reportData) = abi.decode(
unverifiedReport,
(bytes32[3], bytes)
);
// Extract report version from reportData
uint16 reportVersion = (uint16(uint8(reportData[0])) << 8) |
uint16(uint8(reportData[1]));
// Validate report version
if (reportVersion != 3 && reportVersion != 4) {
revert InvalidReportVersion(uint8(reportVersion));
}
// Set the fee token address (LINK in this case)
address feeTokenAddress = feeManager.i_linkAddress();
// Calculate the fee required for report verification
(Common.Asset memory fee, , ) = feeManager.getFeeAndReward(
address(this),
reportData,
feeTokenAddress
);
// Approve rewardManager to spend this contract's balance in fees
IERC20(feeTokenAddress).approve(address(rewardManager), fee.amount);
// Verify the report through the VerifierProxy
bytes memory verifiedReportData = s_verifierProxy.verify(
unverifiedReport,
abi.encode(feeTokenAddress)
);
// Decode verified report data into the appropriate Report struct based on reportVersion
if (reportVersion == 3) {
// v3 report schema
ReportV3 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV3)
);
// Log price from the verified report
emit DecodedPrice(verifiedReport.price);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
} else if (reportVersion == 4) {
// v4 report schema
ReportV4 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV4)
);
// Log price from the verified report
emit DecodedPrice(verifiedReport.price);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
}
}
/**
* @notice Withdraws all tokens of a specific ERC20 token type to a beneficiary address.
* @dev Utilizes SafeERC20's safeTransfer for secure token transfer. Reverts if the contract's balance of the specified token is zero.
* @param _beneficiary Address to which the tokens will be sent. Must not be the zero address.
* @param _token Address of the ERC20 token to be withdrawn. Must be a valid ERC20 token contract.
*/
function withdrawToken(
address _beneficiary,
address _token
) public onlyOwner {
// Retrieve the balance of this contract for the specified token
uint256 amount = IERC20(_token).balanceOf(address(this));
// Revert if there is nothing to withdraw
if (amount == 0) revert NothingToWithdraw();
// Transfer the tokens to the beneficiary
IERC20(_token).safeTransfer(_beneficiary, amount);
}
}
```
[Open in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/ClientReportsVerifier.sol&autoCompile=true) [What is Remix?](https://docs.chain.link/getting-started/conceptual-overview#what-is-remix)
## What's next
- [\> Learn how to verify report data onchain (EVM chains)](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Stream V3 Reports with Go
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Stream and decode V3 reports via WebSocket using the Go SDK](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go\#overview)
## Guide Versions
This guide is available in multiple versions. Choose the one that matches your needs.
Go SDK - V3 reports for Crypto streams
[Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go) [Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go) [Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rust) [Rust SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust)
In this guide, you'll learn how to use Chainlink Data Streams with the _[Streams Direct](https://docs.chain.link/data-streams/streams-direct)_ implementation and the [Data Streams SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk) for Go to subscribe to real-time [V3 reports](https://docs.chain.link/data-streams/reference/report-schema) for [Crypto streams](https://docs.chain.link/data-streams/crypto-streams) via a [WebSocket connection](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws). You'll set up your Go project, listen for real-time reports from the Data Streams Aggregation Network, decode the report data, and log their attributes to your terminal.
## [Requirements](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go\#requirements)
- **Git**: Make sure you have Git installed. You can check your current version by running `git --version` in your terminal and download the latest version from the official [Git website](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) if necessary.
- **Go Version**: Make sure you have Go version 1.21 or higher. You can check your current version by running `go version` in your terminal and download the latest version from the official [Go website](https://go.dev/) if necessary.
- **API Credentials**: Access to the Streams Direct implementation requires API credentials. If you haven't already, [contact us](https://chainlinkcommunity.typeform.com/datastreams?typeform-source=docs.chain.link#ref_id=docs) to request mainnet or testnet access.
## [Guide](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go\#guide)
### [Set up your Go project](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go\#set-up-your-go-project)
1. Create a new directory for your project and navigate to it:

```bash
mkdir my-data-streams-project
cd my-data-streams-project
```
2. Initialize a new Go module:

```bash
go mod init my-data-streams-project
```
3. Install the Data Streams SDK:

```bash
go get github.com/smartcontractkit/data-streams-sdk/go
```
### [Establish a WebSocket connection and listen for real-time reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go\#establish-a-websocket-connection-and-listen-for-real-time-reports)
1. Create a new Go file, `stream.go`, in your project directory:

```bash
touch stream.go
```
2. Insert the following code example and save your `stream.go` file:

```go
package main
import (
"context"
"fmt"
"os"
"time"
streams "github.com/smartcontractkit/data-streams-sdk/go"
feed "github.com/smartcontractkit/data-streams-sdk/go/feed"
report "github.com/smartcontractkit/data-streams-sdk/go/report"
v3 "github.com/smartcontractkit/data-streams-sdk/go/report/v3" // Import the v3 report schema for Crypto streams. For RWA streams, use the v4 schema.
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run stream.go [StreamID1] [StreamID2] ...")
os.Exit(1)
}
// Set up the SDK client configuration
cfg := streams.Config{
ApiKey: os.Getenv("API_KEY"),
ApiSecret: os.Getenv("API_SECRET"),
WsURL: "wss://ws.testnet-dataengine.chain.link",
Logger: streams.LogPrintf,
}
// Create a new client
client, err := streams.New(cfg)
if err != nil {
cfg.Logger("Failed to create client: %v\n", err)
os.Exit(1)
}
// Parse the feed IDs from the command line arguments
var ids []feed.ID
for _, arg := range os.Args[1:] {
var fid feed.ID
if err := fid.FromString(arg); err != nil {
cfg.Logger("Invalid stream ID %s: %v\n", arg, err)
os.Exit(1)
}
ids = append(ids, fid)
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Subscribe to the feeds
stream, err := client.Stream(ctx, ids)
if err != nil {
cfg.Logger("Failed to subscribe: %v\n", err)
os.Exit(1)
}
defer stream.Close()
for {
reportResponse, err := stream.Read(context.Background())
if err != nil {
cfg.Logger("Error reading from stream: %v\n", err)
continue
}
// Log the contents of the report before decoding
cfg.Logger("Raw report data: %+v\n", reportResponse)
// Decode each report as it comes in
decodedReport, decodeErr := report.Decode[v3.Data](reportResponse.FullReport)
if decodeErr != nil {
cfg.Logger("Failed to decode report: %v\n", decodeErr)
continue
}
// Log the decoded report
cfg.Logger("\n--- Report Stream ID: %s ---\n" +
"------------------------------------------\n" +
"Observations Timestamp : %d\n" +
"Benchmark Price : %s\n" +
"Bid : %s\n" +
"Ask : %s\n" +
"Valid From Timestamp : %d\n" +
"Expires At : %d\n" +
"Link Fee : %s\n" +
"Native Fee : %s\n" +
"------------------------------------------\n",
reportResponse.FeedID.String(),
decodedReport.Data.ObservationsTimestamp,
decodedReport.Data.BenchmarkPrice.String(),
decodedReport.Data.Bid.String(),
decodedReport.Data.Ask.String(),
decodedReport.Data.ValidFromTimestamp,
decodedReport.Data.ExpiresAt,
decodedReport.Data.LinkFee.String(),
decodedReport.Data.NativeFee.String(),
)
// Also, log the stream stats
cfg.Logger("\n--- Stream Stats ---\n" +
stream.Stats().String() + "\n" +
"--------------------------------------------------------------------------------------------------------------------------------------------\n",
)
}
}
```
3. Download the required dependencies and update the `go.mod` and `go.sum` files:

```bash
go mod tidy
```
4. Set up the SDK client configuration within `stream.go` with your API credentials and the WebSocket URL:

```go
cfg := streams.Config{
ApiKey: os.Getenv("API_KEY"),
ApiSecret: os.Getenv("API_SECRET"),
WsURL: "wss://ws.testnet-dataengine.chain.link",
Logger: streams.LogPrintf,
}
```
- Set your API credentials as environment variables:

```bash
export API_KEY=""
export API_SECRET=""
```
Replace `` and `` with your API credentials.
- `WsURL` is the [WebSocket URL](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws#domains) for the Data Streams Aggregation Network. Use `wss://ws.testnet-dataengine.chain.link` for the testnet environment.
See the [SDK Reference](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk#config-struct) page for more configuration options.
5. For this example, you'll subscribe to the ETH/USD Data Streams crypto stream. This stream ID is `0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782`. See the [Crypto Streams](https://docs.chain.link/data-streams/crypto-streams) page for a complete list of available crypto assets.
Execute your application:

```bash
go run stream.go 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
```
Expect output similar to the following in your terminal:

```bash
2024-07-31T15:34:27-05:00 Raw report data: {"fullReport":"0x0006f9b553e393ced311551efd30d1decedb63d76ad41737462e2cdbbdff15780000000000000000000000000000000000000000000000000000000035252f11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba7820000000000000000000000000000000000000000000000000000000066aa9fd30000000000000000000000000000000000000000000000000000000066aa9fd300000000000000000000000000000000000000000000000000001c23cdce76d0000000000000000000000000000000000000000000000000001ba0a27c8b79d40000000000000000000000000000000000000000000000000000000066abf1530000000000000000000000000000000000000000000000af35b91cbc421fe2800000000000000000000000000000000000000000000000af354910dbd1830c200000000000000000000000000000000000000000000000af3629289cb2be3f800000000000000000000000000000000000000000000000000000000000000002e03c8b14707a80c59922eeb6b89c79dd8ac6b4b925203b3fe2f0903ba6765934aaf6c4170522c0e54abecb90e7ba7b26e27a83b12740e6a6fd5835c5ece9034c000000000000000000000000000000000000000000000000000000000000000252088e89df570d7022fd2bfc71eb53bfe72423ccba1834a785d80c278b334fab65d4acced307504358554844c2007ab0322b7ab2b7bfa2bc39563bf823654a36","feedID":"0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782","validFromTimestamp":1722458067,"observationsTimestamp":1722458067}
2024-07-31T15:34:27-05:00
--- Report Stream ID: 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 ---
------------------------------------------
Observations Timestamp : 1722458067
Benchmark Price : 3232051369848762000000
Bid : 3232019831592780500000
Ask : 3232082908104743600000
Valid From Timestamp : 1722458067
Expires At : 1722544467
Link Fee : 7776444105849300
Native Fee : 30940102293200
------------------------------------------
2024-07-31T15:34:27-05:00
--- Stream Stats ---
accepted: 1, deduplicated: 0, total_received 1, partial_reconnects: 0, full_reconnects: 0, configured_connections: 1, active_connections 1
--------------------------------------------------------------------------------------------------------------------------------------------
2024-07-31T15:34:28-05:00 Raw report data: {"fullReport":"0x0006f9b553e393ced311551efd30d1decedb63d76ad41737462e2cdbbdff15780000000000000000000000000000000000000000000000000000000035252f14000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba7820000000000000000000000000000000000000000000000000000000066aa9fd40000000000000000000000000000000000000000000000000000000066aa9fd400000000000000000000000000000000000000000000000000001c23c416de34000000000000000000000000000000000000000000000000001ba0909c32d3c00000000000000000000000000000000000000000000000000000000066abf1540000000000000000000000000000000000000000000000af35f59d91552300000000000000000000000000000000000000000000000000af34696c66686640800000000000000000000000000000000000000000000000af3c6a5680c2a6000000000000000000000000000000000000000000000000000000000000000000020d3c5953a51793330c4bb5082d0e82eca98281d340d56088b5707dbc77e5c106311585b943ced71c62a3e6b100dc9316c3580354aee92626280228dd9b6a2c3900000000000000000000000000000000000000000000000000000000000000026398ed0026b877ba17280888f1c7f93f42ca4c3148cf33761412af03b19c08880e4ee75f222eb928db5429fc4339aa1e275bf5a5ffeb6345aa0acef594024abc","feedID":"0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782","validFromTimestamp":1722458068,"observationsTimestamp":1722458068}
2024-07-31T15:34:28-05:00
--- Report Stream ID: 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 ---
------------------------------------------
Observations Timestamp : 1722458068
Benchmark Price : 3232068400000000000000
Bid : 3231956881848792400000
Ask : 3232533600000000000000
Valid From Timestamp : 1722458068
Expires At : 1722544468
Link Fee : 7776367327499200
Native Fee : 30939939266100
------------------------------------------
2024-07-31T15:34:28-05:00
--- Stream Stats ---
accepted: 2, deduplicated: 0, total_received 2, partial_reconnects: 0, full_reconnects: 0, configured_connections: 1, active_connections 1
--------------------------------------------------------------------------------------------------------------------------------------------
2024-07-31T15:34:29-05:00 Raw report data: {"fullReport":"0x0006f9b553e393ced311551efd30d1decedb63d76ad41737462e2cdbbdff15780000000000000000000000000000000000000000000000000000000035252f19000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba7820000000000000000000000000000000000000000000000000000000066aa9fd50000000000000000000000000000000000000000000000000000000066aa9fd500000000000000000000000000000000000000000000000000001c2232164340000000000000000000000000000000000000000000000000001ba02d9e17e83c0000000000000000000000000000000000000000000000000000000066abf1550000000000000000000000000000000000000000000000af3fbd367bea5ac0000000000000000000000000000000000000000000000000af3f1f78eb5653c0000000000000000000000000000000000000000000000000af405a99196de7800000000000000000000000000000000000000000000000000000000000000000020a7b2c4de654a6fb2e0b9c3706521a94bb852c705fe03e682da43301986c229f99b40a47c34b2d23c51e6323274d68b5c6d0d36dbc02586233d50dfc3ef193700000000000000000000000000000000000000000000000000000000000000002364b1b5d922cfe20faa94011a22324ed452fe17a0c1d1475a468974a39419aae33a027865c4a2738fbd59f2ce3a1c72435054a72084b4802f205fe7a690d1ecc","feedID":"0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782","validFromTimestamp":1722458069,"observationsTimestamp":1722458069}
2024-07-31T15:34:29-05:00
--- Report Stream ID: 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 ---
------------------------------------------
Observations Timestamp : 1722458069
Benchmark Price : 3232773100000000000000
Bid : 3232728700000000000000
Ask : 3232817400000000000000
Valid From Timestamp : 1722458069
Expires At : 1722544469
Link Fee : 7775942157527100
Native Fee : 30933194785600
------------------------------------------
2024-07-31T15:34:29-05:00
--- Stream Stats ---
accepted: 3, deduplicated: 0, total_received 3, partial_reconnects: 0, full_reconnects: 0, configured_connections: 1, active_connections 1
--------------------------------------------------------------------------------------------------------------------------------------------
[...]
```
#### [Decoded report details](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go\#decoded-report-details)
The decoded report details include:
| Attribute | Value | Description |
| --- | --- | --- |
| `Stream ID` | `0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782` | The unique identifier for the stream. In this example, the stream is for ETH/USD. |
| `Observations Timestamp` | `1722458069` | The timestamp indicating when the data was captured. |
| `Benchmark Price` | `3232773100000000000000` | The observed price in the report, with 18 decimals. For readability: `3,232.7731000000000` USD per ETH. |
| `Bid` | `3232728700000000000000` | The highest price a buyer is willing to pay for an asset, with 18 decimals. For readability: `3,232.7287000000000` USD per ETH. Learn more about the [Bid price](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices). |
| `Ask` | `3232817400000000000000` | The lowest price a seller is willing to accept for an asset, with 18 decimals. For readability: `3,232.8174000000000` USD per ETH. Learn more about the [Ask price](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices). |
| `Valid From Timestamp` | `1722458069` | The start validity timestamp for the report, indicating when the data becomes relevant. |
| `Expires At` | `1722544469` | The expiration timestamp of the report, indicating the point at which the data becomes outdated. |
| `Link Fee` | `7775942157527100` | The fee to pay in LINK tokens for the onchain verification of the report data. With 18 decimals. For readability: `0.0077759421575271` LINK. |
| `Native Fee` | `30933194785600` | The fee to pay in the native blockchain token (e.g., ETH on Ethereum) for the onchain verification of the report data. With 18 decimals. **Note:** This example fee is not indicative of actual fees. |
#### [Payload for onchain verification](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go\#payload-for-onchain-verification)
In this guide, you log and decode the `fullReport` payload to extract the report data. In a
production environment, you should verify the data to ensure its integrity and authenticity. Refer to the
[Verify report data onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-onchain-verification) guide.
## [Explanation](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go\#explanation)
### [Establishing a WebSocket connection and listening for reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go\#establishing-a-websocket-connection-and-listening-for-reports)
Your application uses the [Stream](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/client.go#L98) function in the [Data Streams SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk)'s client package to establish a real-time WebSocket connection with the Data Streams Aggregation Network.
Once the WebSocket connection is established, your application subscribes to one or more streams by passing an array of `feed.IDs` to the `Stream` function. This subscription lets the client receive real-time updates whenever new report data is available for the specified streams.
### [Decoding a report](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go\#decoding-a-report)
As data reports arrive via the established WebSocket connection, they are processed in real-time:
- Reading streams: The [`Read`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/stream.go#L266) method on the returned Stream object is continuously called within a loop. This method blocks until new data is available, ensuring that all incoming reports are captured as soon as they are broadcasted.
- Decoding reports: For each received report, the SDK's [`Decode`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/report/report.go#L30) function parses and transforms the raw data into a structured format ( `v3.Data` for [crypto streams](https://docs.chain.link/data-streams/crypto-streams)). This decoded data includes data such as the benchmark price and [bid and ask](https://docs.chain.link/data-streams/concepts/liquidity-weighted-prices) prices.
### [Handling the decoded data](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go\#handling-the-decoded-data)
In this example, the application logs the structured report data to the terminal. However, this data can be used for further processing, analysis, or display in your own application.
## What's next
- [\> Learn how to verify your data onchain](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification)
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Data Streams Go SDK
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Streams Direct SDK (Go)](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#overview)
## Streams Direct SDKs
Choose the SDK version that matches your needs.
Go SDK
[Go SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk) [Rust SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk)
This documentation provides a detailed reference for the Data Streams SDK for Go. It implements a client library that offers a domain-oriented abstraction for interacting with the Data Streams API and enables both point-in-time data retrieval and real-time data streaming with built-in fault tolerance capabilities.
## [streams](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#streams)
### [Installation](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#installation)

```go
import streams "github.com/smartcontractkit/data-streams-sdk/go"
```
### [Types](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#types)
#### [`Client` interface](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#client-interface)
[Interface](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/client.go#L21) for interacting with the Data Streams API. Use the [`New`](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk#new) function to create a new instance of the client.
###### [Interface Methods](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#interface-methods)
- `GetFeeds`: Lists all streams available to you.

```go
GetFeeds(ctx context.Context) (r []*Feed, err error)
```
- `GetLatestReport`: Fetches the latest report available for the specified `FeedID`.

```go
GetLatestReport(ctx context.Context, id FeedID) (r *Report, err error)
```
- `GetReports`: Fetches reports for the specified stream IDs and a given timestamp.

```go
GetReports(ctx context.Context, ids []FeedID, timestamp uint64) ([]*Report, error)
```
- `GetReportPage`: Paginates the reports for a specified `FeedID` starting from a given timestamp.

```go
GetReportPage(ctx context.Context, id FeedID, startTS uint64) (*ReportPage, error)
```
- `Stream`: Creates a real-time report stream for specified stream IDs.

```go
Stream(ctx context.Context, feedIDs []FeedID) (Stream, error)
```
#### [`Config` struct](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#config-struct)
Configuration struct for the client. `Config` specifies the client configuration and dependencies. If you specify the `Logger` function, informational client activity is logged.

```go
type Config struct {
ApiKey string // Client API key
ApiSecret string // Client API secret
RestURL string // Rest API URL
WsURL string // Websocket API URL
WsHA bool // Use concurrent connections to multiple Streams servers
WsMaxReconnect int // Maximum number of reconnection attempts for Stream underlying connections
LogDebug bool // Log debug information
InsecureSkipVerify bool // Skip server certificate chain and host name verification
Logger func(format string, a ...any) // Logger function
// InspectHttp intercepts http responses for rest requests.
// The response object must not be modified.
InspectHttpResponse func(*http.Response)
}
```
#### [`CtxKey` string](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#ctxkey-string)
Custom context key type used for passing additional headers.

```go
type CtxKey string
```
- Constants:
- `CustomHeadersCtxKey`: Key for passing custom HTTP headers.

```go
const (
// CustomHeadersCtxKey is used as key in the context.Context object
// to pass in a custom http headers in a http.Header to be used by the client.
// Custom header values will overwrite client headers if they have the same key.
CustomHeadersCtxKey CtxKey = "CustomHeaders"
)
```
#### [`ReportPage` struct](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#reportpage-struct)
Represents a paginated response of reports.

```go
type ReportPage struct {
Reports []*Report // Slice of Report, representing individual report entries.
NextPageTS uint64 // Timestamp for the next page, used for fetching subsequent pages.
}
```
#### [`ReportResponse` struct](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#reportresponse-struct)
Implements the report envelope that contains the full report payload, its stream ID and timestamps. Use the [`Decode`](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk#decode) function to decode the report payload.

```go
type ReportResponse struct {
FeedID feed.ID `json:"feedID"`
FullReport []byte `json:"fullReport"`
ValidFromTimestamp uint64 `json:"validFromTimestamp"`
ObservationsTimestamp uint64 `json:"observationsTimestamp"`
}
```
##### [Methods](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#methods)
- `MarshalJSON`: Serializes the `ReportResponse` into JSON.

```go
func (r *ReportResponse) MarshalJSON() ([]byte, error)
```
- `String`: Returns the string representation of the `ReportResponse`.

```go
func (r *ReportResponse) String() (s string)
```
- `UnmarshalJSON`: Deserializes the `ReportResponse` from JSON.

```go
func (r *ReportResponse) UnmarshalJSON(b []byte) (err error)
```
#### [`Stats` struct](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#stats-struct)
Statistics related to the Stream's operational metrics.

```go
type Stats struct {
Accepted uint64 // Total number of accepted reports
Deduplicated uint64 // Total number of deduplicated reports when in HA
TotalReceived uint64 // Total number of received reports
PartialReconnects uint64 // Total number of partial reconnects when in HA
FullReconnects uint64 // Total number of full reconnects
ConfiguredConnections uint64 // Number of configured connections if in HA
ActiveConnections uint64 // Current number of active connections
}
```
##### [Methods](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#methods-1)
- `String`: Returns a string representation of the `Stats`.

```go
func (s Stats) String() (st string)
```
#### [`Stream` interface](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#stream-interface)
[Interface](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/stream.go#L39) for managing a real-time data stream.
##### [Interface Methods](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#interface-methods-1)
- `Read`: Reads the next available report from the stream. This method will pause (block) the execution until one of the following occurs:
- A report is successfully received.
- The provided context is canceled, typically due to a timeout or a cancel signal.
- An error state is encountered in any of the underlying connections, such as a network failure.

```go
Read(context.Context) (*Report, error)
```
- `Stats`: Returns statistics about the stream operations as `Stats`.

```go
Stats() Stats
```
- `Close`: Closes the stream.

```go
Close() error
```
### [Functions](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#functions)
#### [`New`](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#new)
Creates a new client instance with the specified configuration.

```go
func New(cfg Config) (c Client, err error)
```
**Note**: `New` does not initialize any connections to the Data Streams service.
#### [`LogPrintf`](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#logprintf)
Utility function for logging.

```go
func LogPrintf(format string, a ...any)
```
## [feed](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#feed)
### [Installation](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#installation-1)

```go
import feed "github.com/smartcontractkit/data-streams-sdk/go/feed"
```
### [Types](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#types-1)
#### [`Feed` struct](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#feed-struct)
Identifies the report stream ID.

```go
type Feed struct {
FeedID ID `json:"feedID"`
}
```
Where `ID` is the unique identifier for the stream.
#### [`FeedVersion` uint16](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#feedversion-uint16)
Represents the stream [report schema](https://docs.chain.link/data-streams/reference/report-schema) version.

```go
type FeedVersion uint16
```
#### [`ID` \[32\]byte](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#id-32byte)
Represents a unique identifier for a stream.

```go
type ID [32]byte
```
##### [Methods](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#methods-2)
- `FromString`: Converts a string into an `ID`.

```go
func (f *ID) FromString(s string) (err error)
```
- `MarshalJSON`: Serializes the `ID` into JSON.

```go
func (f *ID) MarshalJSON() (b []byte, err error)
```
- `String`: Returns the string representation of the `ID`.

```go
func (f *ID) String() (id string)
```
- `UnmarshalJSON`: Deserializes the `ID` from JSON.

```go
func (f *ID) UnmarshalJSON(b []byte) (err error)
```
- `Version`: Returns the version of the stream.

```go
func (f *ID) Version() FeedVersion
```
## [report](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#report)
### [Installation](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#installation-2)

```go
import report "github.com/smartcontractkit/data-streams-sdk/go/report"
```
### [Types](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#types-2)
#### [`Data` interface](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#data-interface)
[Interface](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/report/report.go#L13) that represents the actual report data and attributes.

```go
type Data interface {
v1.Data | v2.Data | v3.Data | v4.Data
Schema() abi.Arguments
}
```
#### [`Report` struct](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#report-struct)
Represents the report envelope that contains the full report payload, its Feed ID, and timestamps.

```go
type Report[T Data] struct {
Data T
ReportContext [3][32]byte
ReportBlob []byte
RawRs [][32]byte
RawSs [][32]byte
RawVs [32]byte
}
```
### [Functions](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#functions-1)
#### [`Decode`](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk\#decode)
Decodes the report serialized bytes and its data.

```go
func Decode[T Data](fullReport []byte) (r *Report[T], err error)
```
Example:

```go
payload, _ := hex.DecodeString(
`0006bd87830d5f336e205cf5c63329a1dab8f5d56812eaeb7c69300e66ab8e22000000000000000000000000000000000000000000000000000000000cf7ed13000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000003000101000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000030ab7d02fbba9c6304f98824524407b1f494741174320cfd17a2c22eec1de0000000000000000000000000000000000000000000000000000000066a8f5c60000000000000000000000000000000000000000000000000000000066a8f5c6000000000000000000000000000000000000000000000000000057810653dd9000000000000000000000000000000000000000000000000000541315da76d6100000000000000000000000000000000000000000000000000000000066aa474600000000000000000000000000000000000000000000000009a697ee4230350400000000000000000000000000000000000000000000000009a6506d1426d00000000000000000000000000000000000000000000000000009a77d03ae355fe0000000000000000000000000000000000000000000000000000000000000000672bac991f5233df89f581dc02a89dd8d48419e3558b247d3e65f4069fa45c36658a5a4820dc94fc47a88a21d83474c29ee38382c46b6f9a575b9ce8be4e689c03c76fac19fbec4a29dba704c72cc003a6be1f96af115e322321f0688e24720a5d9bd7136a1d96842ec89133058b888b2e6572b5d4114de2426195e038f1c9a5ce50016b6f5a5de07e08529b845e1c622dcbefa0cfa2ffd128e9932ecee8efd869bc56d09a50ceb360a8d366cfa8eefe3f64279c88bdbc887560efa9944238eb000000000000000000000000000000000000000000000000000000000000000060e2a800f169f26164533c7faff6c9073cd6db240d89444d3487113232f9c31422a0993bb47d56807d0dc26728e4c8424bb9db77511001904353f1022168723010c46627c890be6e701e766679600696866c888ec80e7dbd428f5162a24f2d8262f846bdb06d9e46d295dd8e896fb232be80534b0041660fe4450a7ede9bc3b230722381773a4ae81241568867a759f53c2bdd05d32b209e78845fc58203949e50a608942b270c456001e578227ad00861cf5f47b27b09137a0c4b7f8b4746cef`)
report, err := report.Decode[v3.Data](payload)
if err != nil {
streams.LogPrintf("error decoding report: %s", err)
os.Exit(1)
}
streams.LogPrintf(
"FeedID: %s, FeedVersion: %d, Bid: %s, Ask: %s, BenchMark: %s, LinkFee: %s, NativeFee: %s, ValidFromTS: %d, ExpiresAt: %d",
report.Data.FeedID.String(),
report.Data.FeedID.Version(),
report.Data.Bid.String(),
report.Data.Ask.String(),
report.Data.BenchmarkPrice.String(),
report.Data.LinkFee.String(),
report.Data.NativeFee.String(),
report.Data.ValidFromTimestamp,
report.Data.ExpiresAt,
)
```
## What's next
- [\> Learn how to fetch and decode Data Streams reports using the Data Streams SDK](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api)
- [\> Learn how to stream and decode reports via a WebSocket connection using the Data Streams SDK](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Solana Offchain Verification
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
On this page
# [Verify report data - Offchain integration (Solana)](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification\#overview)
## Guide Versions
This guide is available in multiple versions. Choose the one that matches your needs.
Solana (Rust) - Offchain integration
[EVM Chains (Solidity)](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification) [Solana (Rust) - Onchain integration](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification) [Solana (Rust) - Offchain integration](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification)
To verify a Data Streams report, you must confirm the report integrity signed by the Decentralized Oracle Network (DON).
You have two options to verify Data Streams reports on Solana:
1. **Onchain integration**: Verify reports directly within your Solana program using [Cross-Program Invocation (CPI)](https://solana.com/docs/core/cpi) to the verifier program. Learn more about this method in the [onchain verification guide](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification).
2. **Offchain integration**: Verify reports client-side using an SDK. You'll learn how to implement this method in this guide.
Both methods use the same underlying verification logic and security guarantees, differing only in where the verification occurs.
## [Offchain integration](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification\#offchain-integration)
The offchain integration allows you to verify the authenticity of Data Streams reports from your client-side application. While this method requires sending a transaction to the verifier program, the verification logic and processing of results happens in your client application rather than in a Solana program.
In this guide, you'll learn how to:
- Set up an Anchor project
- Configure the necessary dependencies
- Create a command-line tool to verify reports
- Process and display the verified report data
### [Prerequisites](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification\#prerequisites)
Before you begin, you should have:
- Familiarity with [Rust](https://www.rust-lang.org/learn) programming
- Understanding of [Solana](https://solana.com/docs) concepts:
- [RPC Clients](https://solana.com/docs/rpc) and network interaction
- [Transactions](https://solana.com/docs/core/transactions) and signing
- [Keypairs](https://solana.com/docs/intro/wallets#keypair) and account management
- An allowlisted account in the Data Streams Access Controller ( [contact us](https://chainlinkcommunity.typeform.com/datastreams?typeform-source=docs.chain.link#ref_id=docs) to get started)
### [Requirements](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification\#requirements)
To complete this guide, you'll need:
- **Rust and Cargo**: Install the latest version using [rustup](https://rustup.rs/). Run `rustc --version` to verify your installation.
- **Solana CLI tools**: Install the latest version following the [official guide](https://docs.solana.com/cli/install-solana-cli-tools). Run `solana --version` to verify your installation.
- **Anchor Framework**: Follow the [official installation guide](https://www.anchor-lang.com/docs/installation). Run `anchor --version` to verify your installation.
- **Devnet SOL**: You'll need devnet SOL for transaction fees. Use the [Solana CLI](https://docs.solana.com/cli/transfer-tokens#airdrop-some-tokens-to-get-started) or the [Solana Faucet](https://faucet.solana.com/) to get devnet SOL. Check your balance with `solana balance`.
- **Allowlisted Account**: Your account must be allowlisted in the Data Streams Access Controller.
> **Note**: While this guide uses the Anchor framework for project structure, you can integrate the verification using any Rust-based Solana project setup. The verifier SDK and client libraries are written in Rust, but you can integrate them into your preferred Rust project structure.
### [Implementation guide](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification\#implementation-guide)
#### [1\. Create a new Anchor project](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification\#1-create-a-new-anchor-project)
1. Create a new Anchor project:

```bash
anchor init example_verify
cd example_verify
```
2. Create a binary target for the verification tool:

```bash
mkdir -p programs/example_verify/src/bin
touch programs/example_verify/src/bin/main.rs
```
#### [2\. Configure your project's dependencies](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification\#2-configure-your-projects-dependencies)
Update your program's manifest file ( `programs/example_verify/Cargo.toml`):

```toml
[package]
name = "example_verify"
version = "0.1.0"
description = "Created with Anchor"
edition = "2021"
[lib]
crate-type = ["cdylib", "lib"]
[[bin]]
name = "example_verify"
path = "src/bin/main.rs"
[features]
no-entrypoint = []
no-idl = []
no-log-ix-name = []
cpi = ["no-entrypoint"]
default = []
[dependencies]
data-streams-report = { git = "https://github.com/smartcontractkit/data-streams-sdk.git" }
sdk-off-chain = { git = "https://github.com/smartcontractkit/smart-contract-examples.git", branch = "data-streams-solana-integration", package = "sdk-off-chain"}
solana-program = "1.18.26"
solana-sdk = "1.18.26"
solana-client = "1.18.26"
hex = "0.4.3"
borsh = "0.10.3"
```
#### [3\. Implement the verification library](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification\#3-implement-the-verification-library)
Create `programs/example_verify/src/lib.rs` with the verification function:

```rust
use data_streams_report::report::v3::ReportDataV3;
use sdk_off_chain::VerificationClient;
use solana_client::rpc_client::RpcClient;
use solana_sdk::{
commitment_config::CommitmentConfig,
pubkey::Pubkey,
signature::read_keypair_file,
signer::Signer,
};
use std::{ path::PathBuf, str::FromStr };
pub fn default_keypair_path() -> String {
let mut path = PathBuf::from(std::env::var("HOME").unwrap_or_else(|_| ".".to_string()));
path.push(".config/solana/id.json");
path.to_str().unwrap().to_string()
}
pub fn verify_report(
signed_report: &[u8],
program_id: &str,
access_controller: &str
) -> Result> {
// Initialize RPC client with confirmed commitment level
let rpc_client = RpcClient::new_with_commitment(
"https://api.devnet.solana.com",
CommitmentConfig::confirmed()
);
// Load the keypair that will pay for and sign verification transactions
let payer = read_keypair_file(default_keypair_path())?;
println!("Using keypair: {}", payer.pubkey());
// Convert to Pubkey
let program_pubkey = Pubkey::from_str(program_id)?;
let access_controller_pubkey = Pubkey::from_str(access_controller)?;
println!("Program ID: {}", program_pubkey);
println!("Access Controller: {}", access_controller_pubkey);
// Create a verification client instance
let client = VerificationClient::new(
program_pubkey,
access_controller_pubkey,
rpc_client,
payer
);
// Verify the report
println!("Verifying report of {} bytes...", signed_report.len());
let result = client.verify(signed_report.to_vec()).map_err(|e| {
println!("Verification error: {:?}", e);
e
})?;
// Decode the returned data into a ReportDataV3 struct
let return_data = result.return_data.ok_or("No return data")?;
let report = ReportDataV3::decode(&return_data)?;
Ok(report)
}
```
> This example uses the [V3 schema](https://docs.chain.link/data-streams/reference/report-schema) for [crypto streams](https://docs.chain.link/data-streams/crypto-streams) to decode the report. If you verify reports for [RWA streams](https://docs.chain.link/data-streams/rwa-streams), import and use the [V4 schema](https://docs.chain.link/data-streams/reference/report-schema-v4) from the [report crate](https://github.com/smartcontractkit/data-streams-sdk/tree/main/rust/crates/report) instead.
#### [4\. Create the command-line interface](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification\#4-create-the-command-line-interface)
Create `programs/example_verify/src/bin/main.rs`:

```rust
use example_verify::verify_report;
use std::env;
use std::str::FromStr;
use hex;
use solana_sdk::pubkey::Pubkey;
fn main() {
let args: Vec = env::args().collect();
if args.len() != 4 {
eprintln!(
"Usage: {} ",
args[0]
);
std::process::exit(1);
}
let program_id_str = &args[1];
let access_controller_str = &args[2];
let hex_report = &args[3];
// Validate program_id and access_controller
if Pubkey::from_str(program_id_str).is_err() {
eprintln!("Invalid program ID provided");
std::process::exit(1);
}
if Pubkey::from_str(access_controller_str).is_err() {
eprintln!("Invalid access controller address provided");
std::process::exit(1);
}
// Decode the hex string for the signed report
let signed_report = match hex::decode(hex_report) {
Ok(bytes) => bytes,
Err(e) => {
eprintln!("Failed to decode hex string: {}", e);
std::process::exit(1);
}
};
// Perform verification off-chain
match verify_report(&signed_report, program_id_str, access_controller_str) {
Ok(report) => {
println!("\nVerified Report Data:");
println!("Feed ID: {}", report.feed_id);
println!("Valid from timestamp: {}", report.valid_from_timestamp);
println!("Observations timestamp: {}", report.observations_timestamp);
println!("Native fee: {}", report.native_fee);
println!("Link fee: {}", report.link_fee);
println!("Expires at: {}", report.expires_at);
println!("Benchmark price: {}", report.benchmark_price);
println!("Bid: {}", report.bid);
println!("Ask: {}", report.ask);
}
Err(e) => {
eprintln!("Verification failed: {}", e);
std::process::exit(1);
}
}
}
```
#### [5\. Build and run the verifier](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification\#5-build-and-run-the-verifier)
1. Build the project:

```bash
cargo build
```
2. Make sure you are connected to Devnet with `solana config set --url https://api.devnet.solana.com`.
3. Run the verifier with your report:

```bash
cargo run --
```
Replace the placeholders with:
- ``: The Verifier Program ID (find it on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page)
- ``: The Access Controller Account (find it on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page)
- ``: Your hex-encoded signed report (without the '0x' prefix)
Example:

```bash
cargo run -- Gt9S41PtjR58CbG9JhJ3J6vxesqrNAswbWYbLNTMZA3c 2k3DsgwBoqrnvXKVvd7jX7aptNxdcRBdcd5HkYsGgbrb 0006f9b553e393ced311551efd30d1decedb63d76ad41737462e2cdbbdff1578000000000000000000000000000000000000000000000000000000004f56930f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba78200000000000000000000000000000000000000000000000000000000675ca37000000000000000000000000000000000000000000000000000000000675ca3700000000000000000000000000000000000000000000000000000174be1bd8758000000000000000000000000000000000000000000000000000cb326ce8c3ea800000000000000000000000000000000000000000000000000000000675df4f00000000000000000000000000000000000000000000000d3a30bcc15e207c0000000000000000000000000000000000000000000000000d3a1557b5e634060200000000000000000000000000000000000000000000000d3ab99a974ff10f400000000000000000000000000000000000000000000000000000000000000000292bdd75612560e46ed9b0c2437898f81eb0e18b6b902a161b9708e9177175cf3b8ef2b279f230f766fb29306250ee90856516ee349ca42b2d7fb141deb006745000000000000000000000000000000000000000000000000000000000000000221c156e80276827e1bfeb6542ab064dfa958f5be955f516fb62b1c93437472c31cc65fcaba68c9d661701190bc32025a0690af0eefe027ac218fd15c588dd4d5
```
Expect the output to be similar to the following:

```bash
Using keypair:
Program ID: Gt9S41PtjR58CbG9JhJ3J6vxesqrNAswbWYbLNTMZA3c
Access Controller: 2k3DsgwBoqrnvXKVvd7jX7aptNxdcRBdcd5HkYsGgbrb
Verifying report of 736 bytes...
FeedId: 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
Valid from timestamp: 1734124400
Observations timestamp: 1734124400
Native fee: 25614677280600
Link fee: 3574678975954600
Expires at: 1734210800
Price: 3904011708000000000000
Bid: 3903888333211164500000
Ask: 3904628100124598400000
```
### [Best practices](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification\#best-practices)
When implementing verification in production:
1. **Error Handling**:
- Implement robust error handling for network issues
- Add proper logging and monitoring
- Handle report expiration gracefully
2. **Security**:
- Securely manage keypairs and never expose them
- Validate all input parameters
- Implement rate limiting for verification requests
3. **Performance**:
- Cache verified reports when appropriate
- Implement retry mechanisms with backoff
- Use connection pooling for RPC clients
## What's next
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
- [\> Learn how to verify reports on Solana onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Streams Direct API
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Streams Direct REST API](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#overview)
## [Domains](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#domains)
| Description | Testnet URL | Mainnet URL |
| --- | --- | --- |
| REST endpoint to query specific reports | [https://api.testnet-dataengine.chain.link](https://api.testnet-dataengine.chain.link/) | [https://api.dataengine.chain.link](https://api.dataengine.chain.link/) |
## [Authentication](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#authentication)
### [Headers](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#headers)
All routes require the following three headers for user authentication:
| Header | Description |
| --- | --- |
| `Authorization` | The user’s unique identifier, provided as a UUID (Universally Unique IDentifier). |
| `X-Authorization-Timestamp` | The current timestamp, with precision up to milliseconds. The timestamp must closely synchronize with the server time, allowing a maximum discrepancy of 5 seconds (by default). |
| `X-Authorization-Signature-SHA256` | The HMAC (Hash-based Message Authentication Code) signature, generated by hashing parts of the request and its metadata using SHA-256 with a shared secret key. |
## [API endpoints](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#api-endpoints)
### [Return a single report at a given timestamp](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#return-a-single-report-at-a-given-timestamp)
##### [Endpoint](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#endpoint)
**`/api/v1/reports`**
| Type | Description | Parameter(s) |
| --- | --- | --- |
| HTTP GET | Returns a single report for a given timestamp. | - `feedID`: A Data Streams stream ID.
- `timestamp`: The Unix timestamp for the report. |
##### [Sample request](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#sample-request)

```http
GET /api/v1/reports?feedID=×tamp=
```
##### [Sample response](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#sample-response)

```json
{
"report": {
"feedID": "Hex encoded feedId.",
"validFromTimestamp": "Report's earliest applicable timestamp (in seconds).",
"observationsTimestamp": "Report's latest applicable timestamp (in seconds).",
"fullReport": "A blob containing the report context and body. Encode the fee token into the payload before passing it to the contract for verification."
}
}
```
### [Return a single report with the latest timestamp](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#return-a-single-report-with-the-latest-timestamp)
##### [Endpoint](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#endpoint-1)
**`/api/v1/reports/latest`**
| Type | Parameter(s) |
| --- | --- |
| HTTP GET | `feedID`: A Data Streams stream ID. |
##### [Sample request](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#sample-request-1)

```http
GET /api/v1/reports/latest?feedID=
```
##### [Sample response](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#sample-response-1)

```json
{
"report": {
"feedID": "Hex encoded feedId.",
"validFromTimestamp": "Report's earliest applicable timestamp (in seconds).",
"observationsTimestamp": "Report's latest applicable timestamp (in seconds).",
"fullReport": "A blob containing the report context and body. Encode the fee token into the payload before passing it to the contract for verification."
}
}
```
### [Return a report for multiple FeedIDs at a given timestamp](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#return-a-report-for-multiple-feedids-at-a-given-timestamp)
##### [Endpoint](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#endpoint-2)
**`/api/v1/reports/bulk`**
| Type | Description | Parameter(s) |
| --- | --- | --- |
| HTTP GET | Return a report for multiple FeedIDs at a given timestamp. | - `feedIDs`: A comma-separated list of Data Streams stream IDs.
- `timestamp`: The Unix timestamp for the reports. |
##### [Sample request](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#sample-request-2)

```http
GET /api/v1/reports/bulk?feedIDs=,,...×tamp=
```
##### [Sample response](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#sample-response-2)

```json
{
"reports": [\
{\
"feedID": "Hex encoded feedId.",\
"validFromTimestamp": "Report's earliest applicable timestamp (in seconds).",\
"observationsTimestamp": "Report's latest applicable timestamp (in seconds).",\
"fullReport": "A blob containing the report context and body. Encode the fee token into the payload before passing it to the contract for verification."\
}\
//...\
]
}
```
### [Return multiple sequential reports for a single stream ID, starting at a given timestamp](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#return-multiple-sequential-reports-for-a-single-stream-id-starting-at-a-given-timestamp)
##### [Endpoint](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#endpoint-3)
**`/api/v1/reports/page`**
| Type | Description | Parameter(s) |
| --- | --- | --- |
| HTTP GET | Return multiple sequential reports for a single stream ID, starting at a given timestamp. | - `feedID`: A Data Streams stream ID.
- `startTimestamp`: The Unix timestamp for the first report.
- `limit` (optional): The number of reports to return. |
##### [Sample request](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#sample-request-3)

```http
GET /api/v1/reports/page?feedID=&startTimestamp=&limit=
```
##### [Sample response](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#sample-response-3)

```json
{
"reports": [\
{\
"feedID": "Hex encoded feedId.",\
"validFromTimestamp": "Report's earliest applicable timestamp (in seconds).",\
"observationsTimestamp": "Report's latest applicable timestamp (in seconds).",\
"fullReport": "A blob containing the report context and body. Encode the fee token into the payload before passing it to the contract for verification."\
}\
//...\
]
}
```
## [Error response codes](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#error-response-codes)
| Status Code | Description |
| --- | --- |
| 400 Bad Request | This error is triggered when:
- There is any missing/malformed query argument.
- Required headers are missing or provided with incorrect values. |
| 401 Unauthorized User | This error is triggered when:
- Authentication fails, typically because the HMAC signature provided by the client doesn't match the one expected by the server.
- A user requests access to a stream without the appropriate permission or that does not exist. |
| 500 Internal Server | Indicates an unexpected condition encountered by the server, preventing it from fulfilling the request. This error typically points to issues on the server side. |
| 206 Missing data ( `/bulk` endpoint only) | Indicates that at least one stream ID data is missing from the report. E.g., you requested a report for stream IDs ``, ``, and `` at a given timestamp. If data for `` is missing from the report (not available yet at the specified timestamp), you get `[, ]` and a 206 response. |
## Get the latest Chainlink content straight to your inbox.
Email Address
## Onchain Report Verification
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Verify report data onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification\#overview)
## Guide Versions
This guide is available in multiple versions. Choose the one that matches your needs.
EVM Chains (Solidity)
[EVM Chains (Solidity)](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification) [Solana (Rust) / onchain integration](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification) [Solana (Rust) / offchain integration](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification)
In this guide, you'll learn how to verify onchain the integrity of reports by confirming their authenticity as signed by the Decentralized Oracle Network (DON). You'll use a verifier contract to verify the data onchain and pay the verification fee in LINK tokens.
## [Before you begin](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification\#before-you-begin)
Make sure you understand how to use the [Streams Direct](https://docs.chain.link/data-streams/streams-direct) implementation of Chainlink Data Streams to fetch reports via the [REST API](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api) or [WebSocket](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws) connection. Refer to the following guides for more information:
- [Fetch and decode reports via a REST API](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api)
- [Stream and decode reports via WebSocket](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws)
## [Requirements](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification\#requirements)
- This guide requires testnet ETH and LINK on _Arbitrum Sepolia_. Both are available at [faucets.chain.link](https://faucets.chain.link/arbitrum-sepolia).
- Learn how to [Fund your contract with LINK](https://docs.chain.link/resources/fund-your-contract).
## [Tutorial](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification\#tutorial)
### [Deploy the verifier contract](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification\#deploy-the-verifier-contract)
Deploy a `ClientReportsVerifier` contract on _Arbitrum Sepolia_. This contract is enabled to verify reports and pay the verification fee in LINK tokens.
1. [Open the ClientReportsVerifier.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/ClientReportsVerifier.sol) contract in Remix.
[Open in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/ClientReportsVerifier.sol&autoCompile=true) [What is Remix?](https://docs.chain.link/getting-started/conceptual-overview#what-is-remix)
2. Select the `ClientReportsVerifier.sol` contract in the **Solidity Compiler** tab.

3. Compile the contract.
4. Open MetaMask and set the network to _Arbitrum Sepolia_. If you need to add Arbitrum Sepolia to your wallet, you can find the chain ID and the LINK token contract address on the [LINK Token Contracts](https://docs.chain.link/resources/link-token-contracts#arbitrum-sepolia-testnet) page.
- [Arbitrum Sepolia testnet and LINK token contract](https://docs.chain.link/resources/link-token-contracts#arbitrum-sepolia-testnet)
5. On the **Deploy & Run Transactions** tab in Remix, select _Injected Provider - MetaMask_ in the **Environment** list. Remix will use the MetaMask wallet to communicate with _Arbitrum Sepolia_.

6. In the **Contract** section, select the `ClientReportsVerifier` contract and fill in the Arbitrum Sepolia **verifier proxy address**: `0x2ff010DEbC1297f19579B4246cad07bd24F2488A`. You can find the verifier proxy addresses on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.

7. Click the **Deploy** button to deploy the contract. MetaMask prompts you to confirm the transaction. Check the transaction details to ensure you deploy the contract to _Arbitrum Sepolia_.
8. After you confirm the transaction, the contract address appears under the **Deployed Contracts** list in Remix. Save this contract address for the next step.

### [Fund the verifier contract](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification\#fund-the-verifier-contract)
In this example, the verifier contract pays for onchain verification of reports in LINK tokens.
Open MetaMask and send 1 testnet LINK on _Arbitrum Sepolia_ to the verifier contract address you saved earlier.
### [Verify a report onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification\#verify-a-report-onchain)
1. In Remix, on the **Deploy & Run Transactions** tab, expand your verifier contract under the **Deployed Contracts** section.
2. Fill in the `verifyReport` function input parameter with the report payload you want to verify. You can use the following full report payload obtained in the [Fetch and decode report via a REST API](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api) guide as an example:

```plaintext
0x000660403d36be006d0c15d9b306f93c8660c5cfeab7db8e28c78ba316d395970000000000000000000000000000000000000000000000000000000032c3780a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200003c8e550d2fc5304993010112de9b69798297e4cc11990ee6250e464daf760000000000000000000000000000000000000000000000000000000006706e595000000000000000000000000000000000000000000000000000000006706e595000000000000000000000000000000000000000000000000000025bd3eb74c080000000000000000000000000000000000000000000000000021c6a95c654c7400000000000000000000000000000000000000000000000000000000670837150000000000000000000000000000000000000000000000079a2ab4077fc8fc6000000000000000000000000000000000000000000000000799fcb42536dfd8300000000000000000000000000000000000000000000000079a59496c3f29a0000000000000000000000000000000000000000000000000000000000000000002bd4acd37ce3cd5799de05d156ab328a5effd94468ebbaf2ff18d13d9631259cbe66cca01af6a8bb36e79d2d731a44e16791ee31e46ce27ed6530f1590cd7734c0000000000000000000000000000000000000000000000000000000000000002391562f1f2e4986bdb978fbf5ee27f7012992a79301af42d3473761ef2ede6271a61fbf4b32ac5be68a598bcfa523e035b624dab3b3d9a46276834f824ee592a
```

3. Click the `verifyReport` button to call the function. MetaMask prompts you to accept the transaction.
4. Click the `last_decoded_price` getter function to view the decoded price from the verified report. The answer on the ETH/USD stream uses 18 decimal places, so an answer of `3257579704051546000000` indicates an ETH/USD price of 3,257.579704051546. Each stream uses a different number of decimal places for answers. See the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page for more information.

## [Examine the code](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification\#examine-the-code)
The example code you deployed has all the interfaces and functions required to verify Data Streams reports onchain.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Common} from "@chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol";
import {IRewardManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol";
import {IVerifierFeeManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol";
import {IERC20} from "@chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol";
using SafeERC20 for IERC20;
/**
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE FOR DEMONSTRATION PURPOSES.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
// Custom interfaces for IVerifierProxy and IFeeManager
interface IVerifierProxy {
/**
* @notice Verifies that the data encoded has been signed correctly by routing to the correct verifier, and bills the user if applicable.
* @param payload The encoded data to be verified, including the signed report.
* @param parameterPayload Fee metadata for billing. In the current implementation, this consists of the abi-encoded address of the ERC-20 token used for fees.
* @return verifierResponse The encoded report from the verifier.
*/
function verify(
bytes calldata payload,
bytes calldata parameterPayload
) external payable returns (bytes memory verifierResponse);
/**
* @notice Verifies multiple reports in bulk, ensuring that each is signed correctly, routes them to the appropriate verifier, and handles billing for the verification process.
* @param payloads An array of encoded data to be verified, where each entry includes the signed report.
* @param parameterPayload Fee metadata for billing. In the current implementation, this consists of the abi-encoded address of the ERC-20 token used for fees.
* @return verifiedReports An array of encoded reports returned from the verifier.
*/
function verifyBulk(
bytes[] calldata payloads,
bytes calldata parameterPayload
) external payable returns (bytes[] memory verifiedReports);
function s_feeManager() external view returns (IVerifierFeeManager);
}
interface IFeeManager {
/**
* @notice Calculates the fee and reward associated with verifying a report, including discounts for subscribers.
* This function assesses the fee and reward for report verification, applying a discount for recognized subscriber addresses.
* @param subscriber The address attempting to verify the report. A discount is applied if this address is recognized as a subscriber.
* @param unverifiedReport The report data awaiting verification. The content of this report is used to determine the base fee and reward, before considering subscriber discounts.
* @param quoteAddress The payment token address used for quoting fees and rewards.
* @return fee The fee assessed for verifying the report, with subscriber discounts applied where applicable.
* @return reward The reward allocated to the caller for successfully verifying the report.
* @return totalDiscount The total discount amount deducted from the fee for subscribers.
*/
function getFeeAndReward(
address subscriber,
bytes memory unverifiedReport,
address quoteAddress
) external returns (Common.Asset memory, Common.Asset memory, uint256);
function i_linkAddress() external view returns (address);
function i_nativeAddress() external view returns (address);
function i_rewardManager() external view returns (address);
}
/**
* @dev This contract implements functionality to verify Data Streams reports from
* the Streams Direct API or WebSocket connection, with payment in LINK tokens.
*/
contract ClientReportsVerifier {
error NothingToWithdraw(); // Thrown when a withdrawal attempt is made but the contract holds no tokens of the specified type.
error NotOwner(address caller); // Thrown when a caller tries to execute a function that is restricted to the contract's owner.
error InvalidReportVersion(uint16 version); // Thrown when an unsupported report version is provided to verifyReport.
/**
* @dev Represents a data report from a Data Streams stream for v3 schema (crypto streams).
* The `price`, `bid`, and `ask` values are carried to either 8 or 18 decimal places, depending on the stream.
* For more information, see https://docs.chain.link/data-streams/crypto-streams and https://docs.chain.link/data-streams/reference/report-schema
*/
struct ReportV3 {
bytes32 feedId; // The stream ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median price (8 or 18 decimals).
int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation (8 or 18 decimals).
int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation (8 or 18 decimals).
}
/**
* @dev Represents a data report from a Data Streams stream for v4 schema (RWA stream).
* The `price` value is carried to either 8 or 18 decimal places, depending on the stream.
* The `marketStatus` indicates whether the market is currently open. Possible values: `0` (`Unknown`), `1` (`Closed`), `2` (`Open`).
* For more information, see https://docs.chain.link/data-streams/rwa-streams and https://docs.chain.link/data-streams/reference/report-schema-v4
*/
struct ReportV4 {
bytes32 feedId; // The stream ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median benchmark price (8 or 18 decimals).
uint32 marketStatus; // The DON's consensus on whether the market is currently open.
}
IVerifierProxy public s_verifierProxy; // The VerifierProxy contract used for report verification.
address private s_owner; // The owner of the contract.
int192 public lastDecodedPrice; // Stores the last decoded price from a verified report.
event DecodedPrice(int192 price); // Event emitted when a report is successfully verified and decoded.
/**
* @param _verifierProxy The address of the VerifierProxy contract.
* You can find these addresses on https://docs.chain.link/data-streams/crypto-streams.
*/
constructor(address _verifierProxy) {
s_owner = msg.sender;
s_verifierProxy = IVerifierProxy(_verifierProxy);
}
/// @notice Checks if the caller is the owner of the contract.
modifier onlyOwner() {
if (msg.sender != s_owner) revert NotOwner(msg.sender);
_;
}
/**
* @notice Verifies an unverified data report and processes its contents, supporting both v3 and v4 report schemas.
* @dev Performs the following steps:
* - Decodes the unverified report to extract the report data.
* - Extracts the report version by reading the first two bytes of the report data.
* - The first two bytes correspond to the schema version encoded in the stream ID.
* - Schema version `0x0003` corresponds to report version 3 (for Crypto assets).
* - Schema version `0x0004` corresponds to report version 4 (for Real World Assets).
* - Validates that the report version is either 3 or 4; reverts with `InvalidReportVersion` otherwise.
* - Retrieves the fee manager and reward manager contracts.
* - Calculates the fee required for report verification using the fee manager.
* - Approves the reward manager to spend the calculated fee amount.
* - Verifies the report via the VerifierProxy contract.
* - Decodes the verified report data into the appropriate report struct (`ReportV3` or `ReportV4`) based on the report version.
* - Emits a `DecodedPrice` event with the price extracted from the verified report.
* - Updates the `lastDecodedPrice` state variable with the price from the verified report.
* @param unverifiedReport The encoded report data to be verified, including the signed report and metadata.
* @custom:reverts InvalidReportVersion(uint8 version) Thrown when an unsupported report version is provided.
*/
function verifyReport(bytes memory unverifiedReport) external {
// Retrieve fee manager and reward manager
IFeeManager feeManager = IFeeManager(
address(s_verifierProxy.s_feeManager())
);
IRewardManager rewardManager = IRewardManager(
address(feeManager.i_rewardManager())
);
// Decode unverified report to extract report data
(, bytes memory reportData) = abi.decode(
unverifiedReport,
(bytes32[3], bytes)
);
// Extract report version from reportData
uint16 reportVersion = (uint16(uint8(reportData[0])) << 8) |
uint16(uint8(reportData[1]));
// Validate report version
if (reportVersion != 3 && reportVersion != 4) {
revert InvalidReportVersion(uint8(reportVersion));
}
// Set the fee token address (LINK in this case)
address feeTokenAddress = feeManager.i_linkAddress();
// Calculate the fee required for report verification
(Common.Asset memory fee, , ) = feeManager.getFeeAndReward(
address(this),
reportData,
feeTokenAddress
);
// Approve rewardManager to spend this contract's balance in fees
IERC20(feeTokenAddress).approve(address(rewardManager), fee.amount);
// Verify the report through the VerifierProxy
bytes memory verifiedReportData = s_verifierProxy.verify(
unverifiedReport,
abi.encode(feeTokenAddress)
);
// Decode verified report data into the appropriate Report struct based on reportVersion
if (reportVersion == 3) {
// v3 report schema
ReportV3 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV3)
);
// Log price from the verified report
emit DecodedPrice(verifiedReport.price);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
} else if (reportVersion == 4) {
// v4 report schema
ReportV4 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV4)
);
// Log price from the verified report
emit DecodedPrice(verifiedReport.price);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
}
}
/**
* @notice Withdraws all tokens of a specific ERC20 token type to a beneficiary address.
* @dev Utilizes SafeERC20's safeTransfer for secure token transfer. Reverts if the contract's balance of the specified token is zero.
* @param _beneficiary Address to which the tokens will be sent. Must not be the zero address.
* @param _token Address of the ERC20 token to be withdrawn. Must be a valid ERC20 token contract.
*/
function withdrawToken(
address _beneficiary,
address _token
) public onlyOwner {
// Retrieve the balance of this contract for the specified token
uint256 amount = IERC20(_token).balanceOf(address(this));
// Revert if there is nothing to withdraw
if (amount == 0) revert NothingToWithdraw();
// Transfer the tokens to the beneficiary
IERC20(_token).safeTransfer(_beneficiary, amount);
}
}
```
[Open in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/ClientReportsVerifier.sol&autoCompile=true) [What is Remix?](https://docs.chain.link/getting-started/conceptual-overview#what-is-remix)
### [Initializing the contract](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification\#initializing-the-contract)
When deploying the contract, you define the verifier proxy address for the stream you want to read from. You can find this address on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page. The verifier proxy address provides functions that are required for this example:
- The `s_feeManager` function to estimate the verification fees.
- The `verify` function to verify the report onchain.
### [Verifying a report](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification\#verifying-a-report)
The `verifyReport` function is the core function that handles onchain report verification. Here's how it works:
- **Report data extraction**:
- The function decodes the `unverifiedReport` to extract the report data.
- It then extracts the report version by reading the first two bytes of the report data, which correspond to the schema version encoded in the stream ID:
- Schema version `0x0003` corresponds to the [report schema v3](https://docs.chain.link/data-streams/reference/report-schema) (Crypto assets).
- Schema version `0x0004` corresponds to the [report schema v4](https://docs.chain.link/data-streams/reference/report-schema-v4) (Real World Assets).
- If the report version is unsupported, the function reverts with an InvalidReportVersion error.
- **Fee calculation**:
- The function interacts with the `FeeManager` contract (accessed via the verifier proxy) to calculate the fees required for verification.
- It uses the `getFeeAndReward` function to obtain the fee amount in LINK tokens.
- **Token approval**: It approves the `RewardManager` contract to spend the calculated amount of LINK tokens from the contract's balance.
- **Report verification**:
- The `verify` function of the verifier proxy is called to perform the actual verification.
- It passes the `unverifiedReport` and the encoded fee token address as parameters.
- **Data decoding**:
- Depending on the report version, the function decodes the verified report data into the appropriate struct ( `ReportV3` or `ReportV4`).
- It emits a `DecodedPrice` event with the price extracted from the verified report.
- The `lastDecodedPrice` state variable is updated with the new price.
## What's next
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Solana Report Verification
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Verify report data - Onchain integration (Solana)](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#overview)
## Guide Versions
This guide is available in multiple versions. Choose the one that matches your needs.
Solana (Rust) - Onchain integration
[EVM Chains (Solidity)](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification) [Solana (Rust) - Onchain integration](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification) [Solana (Rust) - Offchain integration](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification)
To verify a Data Streams report, you must confirm the report integrity signed by the Decentralized Oracle Network (DON).
You have two options to verify Data Streams reports on Solana:
1. **Onchain integration**: Verify reports directly within your Solana program using [Cross-Program Invocation (CPI)](https://solana.com/docs/core/cpi) to the Verifier program. You'll learn how to implement this method in this guide.
2. **Offchain integration**: Verify reports client-side using an SDK. Learn more about this method in the [offchain verification guide](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification).
Both methods use the same underlying verification logic and security guarantees, differing only in where the verification occurs.
## [Onchain integration](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#onchain-integration)
You can verify Data Streams reports directly within your Solana program using this integration. This method ensures atomic verification and processing of report data.
In this guide, you'll learn how to:
- Integrate with the Chainlink Data Streams Verifier program
- Create and invoke the verification instruction
- Retrieve the verified report data
### [Prerequisites](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#prerequisites)
Before you begin, you should have:
- Familiarity with [Rust](https://www.rust-lang.org/learn) programming
- Understanding of [Solana](https://solana.com/docs) concepts:
- [Accounts](https://solana.com/docs/core/accounts)
- [Instructions](https://solana.com/docs/core/transactions#instruction)
- [Program Derived Addresses (PDAs)](https://solana.com/docs/core/pda)
- Knowledge of the [Anchor](https://www.anchor-lang.com/) framework
- An allowlisted account in the Data Streams Access Controller. ( [Contact us](https://chainlinkcommunity.typeform.com/datastreams?typeform-source=docs.chain.link#ref_id=docs) to get started).
### [Requirements](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#requirements)
To complete this guide, you'll need:
- **Rust and Cargo**: Install the latest version using [rustup](https://rustup.rs/). Run `rustc --version` to verify your installation.
- **Solana CLI tools**: Install the latest version following the [official guide](https://docs.solana.com/cli/install-solana-cli-tools). Run `solana --version` to verify your installation.
- **Anchor Framework**: Follow the [official installation guide](https://www.anchor-lang.com/docs/installation). Run `anchor --version` to verify your installation.
- **Node.js and npm**: [Install Node.js 20 or later](https://nodejs.org/). Verify your installation with `node --version`.
- **ts-node**: Install globally using npm: `npm install -g ts-node`. Verify your installation with `ts-node --version`.
- **Devnet SOL**: You'll need devnet SOL for deployment and testing. Use the [Solana CLI](https://docs.solana.com/cli/transfer-tokens#airdrop-some-tokens-to-get-started) or the [Solana Faucet](https://faucet.solana.com/) to get devnet SOL.
> **Note**: While this guide uses the Anchor framework for project structure, you can integrate the verification using any Rust-based Solana program framework. The verifier SDK is written in Rust, but you can integrate it into your preferred Rust program structure.
### [Implementation guide](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#implementation-guide)
#### [1\. Create a new Anchor project](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#1-create-a-new-anchor-project)
1. Open your terminal and run the following command to create a new Anchor project:

```bash
anchor init example_verify
```
This command creates a new directory named `example_verify` with the basic structure of an Anchor project.
2. Navigate to the project directory:

```bash
cd example_verify
```
#### [2\. Configure your project for devnet](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#2-configure-your-project-for-devnet)
Open your `Anchor.toml` file at the root of your project and update it to use devnet:

```toml
[features]
seeds = false
skip-lint = false
[programs.devnet]
# Replace with your program ID
example_verify = ""
[registry]
url = "https://api.apr.dev"
[provider]
cluster = "devnet"
wallet = "~/.config/solana/id.json"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
```
Replace `` with your program ID. You can run `solana-keygen pubkey target/deploy/example_verify-keypair.json` to get your program ID.
#### [3\. Set up your program's dependencies](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#3-set-up-your-programs-dependencies)
In your program's manifest file ( `programs/example_verify/Cargo.toml`), add the Chainlink Data Streams client and the report crate as dependencies:

```toml
[dependencies]
chainlink_solana_data_streams = { git = "https://github.com/smartcontractkit/chainlink-solana", branch = "develop", subdir = "contracts/crates/chainlink-solana-data-streams" }
data-streams-report = { git = "https://github.com/smartcontractkit/data-streams-sdk.git", subdir = "rust/crates/report" }
# Additional required dependencies
anchor-lang = "0.29.0"
```
#### [4\. Write the program](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#4-write-the-program)
Navigate to your program main file ( `programs/example_verify/src/lib.rs`). This is where you'll write your program logic. Replace the contents of `lib.rs` with the following example code:

```rust
// Import required dependencies for Anchor, Solana, and Data Streams
use anchor_lang::prelude::*;
use anchor_lang::solana_program::{
program::{get_return_data, invoke},
pubkey::Pubkey,
instruction::Instruction,
};
use data_streams_report::report::v3::ReportDataV3;
use chainlink_solana_data_streams::VerifierInstructions;
declare_id!("");
#[program]
pub mod example_verify {
use super::*;
/// Verifies a Data Streams report using Cross-Program Invocation to the Verifier program
/// Returns the decoded report data if verification succeeds
pub fn verify(ctx: Context, signed_report: Vec) -> Result<()> {
let program_id = ctx.accounts.verifier_program_id.key();
let verifier_account = ctx.accounts.verifier_account.key();
let access_controller = ctx.accounts.access_controller.key();
let user = ctx.accounts.user.key();
let config_account = ctx.accounts.config_account.key();
// Create verification instruction
let chainlink_ix: Instruction = VerifierInstructions::verify(
&program_id,
&verifier_account,
&access_controller,
&user,
&config_account,
signed_report,
);
// Invoke the Verifier program
invoke(
&chainlink_ix,
&[\
ctx.accounts.verifier_account.to_account_info(),\
ctx.accounts.access_controller.to_account_info(),\
ctx.accounts.user.to_account_info(),\
ctx.accounts.config_account.to_account_info(),\
],
)?;
// Decode and log the verified report data
if let Some((_program_id, return_data)) = get_return_data() {
msg!("Report data found");
let report = ReportDataV3::decode(&return_data)
.map_err(|_| error!(CustomError::InvalidReportData))?;
// Log report fields
msg!("FeedId: {}", report.feed_id);
msg!("Valid from timestamp: {}", report.valid_from_timestamp);
msg!("Observations Timestamp: {}", report.observations_timestamp);
msg!("Native Fee: {}", report.native_fee);
msg!("Link Fee: {}", report.link_fee);
msg!("Expires At: {}", report.expires_at);
msg!("Benchmark Price: {}", report.benchmark_price);
msg!("Bid: {}", report.bid);
msg!("Ask: {}", report.ask);
} else {
msg!("No report data found");
return Err(error!(CustomError::NoReportData));
}
Ok(())
}
}
#[error_code]
pub enum CustomError {
#[msg("No valid report data found")]
NoReportData,
#[msg("Invalid report data format")]
InvalidReportData,
}
#[derive(Accounts)]
pub struct ExampleProgramContext<'info> {
/// The Verifier Account stores the DON's public keys and other verification parameters.
/// This account must match the PDA derived from the verifier program.
/// CHECK: The account is validated by the verifier program.
pub verifier_account: AccountInfo<'info>,
/// The Access Controller Account
/// CHECK: The account structure is validated by the verifier program.
pub access_controller: AccountInfo<'info>,
/// The account that signs the transaction.
pub user: Signer<'info>,
/// The Config Account is a PDA derived from a signed report
/// CHECK: The account is validated by the verifier program.
pub config_account: UncheckedAccount<'info>,
/// The Verifier Program ID specifies the target Chainlink Data Streams Verifier Program.
/// CHECK: The program ID is validated by the verifier program.
pub verifier_program_id: AccountInfo<'info>,
}
```
Replace `` with your program ID in the `declare_id!` macro. You can run `solana-keygen pubkey target/deploy/example_verify-keypair.json` to get your program ID.
Note how the `VerifierInstructions::verify` helper method automatically handles the PDA computations internally. Refer to the [Program Derived Addresses (PDAs)](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification#program-derived-addresses-pdas) section for more information.
> This example uses the [V3 schema](https://docs.chain.link/data-streams/reference/report-schema) for [crypto streams](https://docs.chain.link/data-streams/crypto-streams) to decode the report. If you verify reports for [RWA streams](https://docs.chain.link/data-streams/rwa-streams), import and use the [V4 schema](https://docs.chain.link/data-streams/reference/report-schema-v4) from the [report crate](https://github.com/smartcontractkit/data-streams-sdk/tree/main/rust/crates/report) instead.
#### [5\. Deploy your program](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#5-deploy-your-program)
1. Run the following command to build your program:

```bash
anchor build
```
**Note**: If you run into this error, set the `version` field at the top of your `cargo.lock` file to `3`.

```bash
warning: virtual workspace defaulting to `resolver = "1"` despite one or more workspace members being on edition 2021 which implies `resolver = "2"`
note: to keep the current resolver, specify `workspace.resolver = "1"` in the workspace root's manifest
note: to use the edition 2021 resolver, specify `workspace.resolver = "2"` in the workspace root's manifest
note: for more details see https://doc.rust-lang.org/cargo/reference/resolver.html#resolver-versions
warning: .../example_verify/programs/example_verify/Cargo.toml: unused manifest key: dependencies.data-streams-report.subdir
error: failed to parse lock file at: .../example_verify/Cargo.lock
Caused by:
lock file version 4 requires `-Znext-lockfile-bump`
```
2. Deploy your program to a Solana cluster (devnet in this example) using:

```bash
anchor deploy
```
Expect an output similar to the following:

```bash
Deploying cluster: https://api.devnet.solana.com
Upgrade authority: ~/.config/solana/id.json
Deploying program "example_verify"...
Program path: ~/example_verify/target/deploy/example_verify.so...
Program Id: 8XcUbDgY2UaUYNHkirKsWqXJtzPXezBSyj5Yh87dXums
Signature: 3ky6VkpebDGq7x1n8JB32daybmjvbRBsD4yR2uCCussSWhokaEESTXuSa5s8NMvKTz2NZjoq9aoQ9pvuw9bYoibt
Deploy success
```
#### [6\. Interact with the Verifier Program](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#6-interact-with-the-verifier-program)
In this section, you'll write a client script to interact with your deployed program, which will use [Cross-Program Invocation (CPI)](https://solana.com/docs/core/cpi) to verify reports through the Chainlink Data Streams Verifier Program.
1. In the `tests` directory, create a new file `verify_test.ts` to interact with your deployed program.
2. Populate your `verify_tests.ts` file with the example client script below.
- Replace `` with your program ID.
- This example provides a report payload. To use your own report payload, update the `hexString` variable.

```typescript
import * as anchor from "@coral-xyz/anchor"
import { Program } from "@coral-xyz/anchor"
import { PublicKey } from "@solana/web3.js"
import { ExampleVerify } from "../target/types/example_verify"
import * as snappy from "snappy"
// Data Streams Verifier Program ID on Devnet
const VERIFIER_PROGRAM_ID = new PublicKey("Gt9S41PtjR58CbG9JhJ3J6vxesqrNAswbWYbLNTMZA3c")
async function main() {
// Setup connection and provider
const provider = anchor.AnchorProvider.env()
anchor.setProvider(provider)
// Initialize your program using the IDL and your program ID
const program = new Program(
require("../target/idl/example_verify.json"),
"",
provider
)
// Convert the hex string to a Uint8Array
// This is an example report payload for a crypto stream
const hexString =
"0x00064f2cd1be62b7496ad4897b984db99243e0921906f66ded15149d993ef42c000000000000000000000000000000000000000000000000000000000103c90c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200003684ea93c43ed7bd00ab3bb189bb62f880436589f1ca58b599cd97d6007fb0000000000000000000000000000000000000000000000000000000067570fa40000000000000000000000000000000000000000000000000000000067570fa400000000000000000000000000000000000000000000000000004c6ac85bf854000000000000000000000000000000000000000000000000002e1bf13b772a9c0000000000000000000000000000000000000000000000000000000067586124000000000000000000000000000000000000000000000000002bb4cf7662949c000000000000000000000000000000000000000000000000002bae04e2661000000000000000000000000000000000000000000000000000002bb6a26c3fbeb80000000000000000000000000000000000000000000000000000000000000002af5e1b45dd8c84b12b4b58651ff4173ad7ca3f5d7f5374f077f71cce020fca787124749ce727634833d6ca67724fd912535c5da0f42fa525f46942492458f2c2000000000000000000000000000000000000000000000000000000000000000204e0bfa6e82373ae7dff01a305b72f1debe0b1f942a3af01bad18e0dc78a599f10bc40c2474b4059d43a591b75bdfdd80aafeffddfd66d0395cca2fdeba1673d"
// Remove the '0x' prefix if present
const cleanHexString = hexString.startsWith("0x") ? hexString.slice(2) : hexString
// Validate hex string format
if (!/^[0-9a-fA-F]+$/.test(cleanHexString)) {
throw new Error("Invalid hex string format")
}
// Convert hex to Uint8Array
const signedReport = new Uint8Array(cleanHexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)))
// Compress the report using Snappy
const compressedReport = await snappy.compress(Buffer.from(signedReport))
// Derive necessary PDAs using the SDK's helper functions
const verifierAccount = await PublicKey.findProgramAddressSync([Buffer.from("verifier")], VERIFIER_PROGRAM_ID)
const configAccount = await PublicKey.findProgramAddressSync([signedReport.slice(0, 32)], VERIFIER_PROGRAM_ID)
// The Data Streams access controller on devnet
const accessController = new PublicKey("2k3DsgwBoqrnvXKVvd7jX7aptNxdcRBdcd5HkYsGgbrb")
try {
console.log("\n📝 Transaction Details")
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
console.log("🔑 Signer:", provider.wallet.publicKey.toString())
const tx = await program.methods
.verify(compressedReport)
.accounts({
verifierAccount: verifierAccount[0],
accessController: accessController,
user: provider.wallet.publicKey,
configAccount: configAccount[0],
verifierProgramId: VERIFIER_PROGRAM_ID,
})
.rpc({ commitment: "confirmed" })
console.log("✅ Transaction successful!")
console.log("🔗 Signature:", tx)
// Fetch and display logs
const txDetails = await provider.connection.getTransaction(tx, {
commitment: "confirmed",
maxSupportedTransactionVersion: 0,
})
console.log("\n📋 Program Logs")
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
let indentLevel = 0
let currentProgramId = ""
txDetails.meta.logMessages.forEach((log) => {
// Handle indentation for inner program calls
if (log.includes("Program invoke")) {
const programIdMatch = log.match(/Program (.*?) invoke/)
if (programIdMatch) {
currentProgramId = programIdMatch[1]
// Remove "Unknown Program" prefix if present
currentProgramId = currentProgramId.replace("Unknown Program ", "")
// Remove parentheses if present
currentProgramId = currentProgramId.replace(/[()]/g, "")
}
console.log(" ".repeat(indentLevel) + "🔄", log.trim())
indentLevel++
return
}
if (log.includes("Program return") || log.includes("Program consumed")) {
indentLevel = Math.max(0, indentLevel - 1)
}
// Add indentation to all logs
const indent = " ".repeat(indentLevel)
if (log.includes("Program log:")) {
const logMessage = log.replace("Program log:", "").trim()
if (log.includes("Program log:")) {
console.log(indent + "📍", logMessage)
} else if (log.includes("Program data:")) {
console.log(indent + "📊", log.replace("Program data:", "").trim())
}
}
})
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
} catch (error) {
console.log("\n❌ Transaction Failed")
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
console.error("Error:", error)
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
}
}
main()
```
**Note**: The Program IDs and Access Controller Accounts are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.
3. Add the `snappy` dependency to your project:

```bash
yarn add snappy
```
`snappy` is a compression library that is used to compress the report data.
4. Execute the test script to interact with your program:

```bash
ANCHOR_PROVIDER_URL="https://api.devnet.solana.com" ANCHOR_WALLET="~/.config/solana/id.json" ts-node tests/verify_test.ts
```
Replace `~/.config/solana/id.json` with the path to your Solana wallet (e.g., `/Users/username/.config/solana/id.json`).
5. Verify the output logs to ensure the report data is processed correctly. Expect to see the decoded report fields logged to the console:

```bash
📝 Transaction Details
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔑 Signer: 1BZZU8cJsrMSBaQQGUxTE4LQYX2SU2jjs97pkrz7rHD
✅ Transaction successful!
🔗 Signature: 2CTZ7kgAxTogvMgb7QFDJUAq9xFBUVTEvyjf7UuhoVrHDhYKtHpQmd8hEy9XvLhfgWMdVTpCRvdf18r1ixgtncUc
📋 Program Logs
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📍 Instruction: Verify
📍 Instruction: Verify
📍 Report data found
📍 FeedId: 0x0003684ea93c43ed7bd00ab3bb189bb62f880436589f1ca58b599cd97d6007fb
📍 valid from timestamp: 1733758884
📍 Observations Timestamp: 1733758884
📍 Native Fee: 84021511714900
📍 Link Fee: 12978571827423900
📍 Expires At: 1733845284
📍 Benchmark Price: 12302227135960220
📍 Bid: 12294760000000000
📍 Ask: 12304232715632312
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
### [Learn more](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#learn-more)
#### [Program Derived Addresses (PDAs)](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#program-derived-addresses-pdas)
The verification process relies on two important PDAs that are handled automatically by the [Chainlink Data Streams Solana SDK](https://github.com/smartcontractkit/chainlink-solana/tree/develop/contracts/crates/chainlink-solana-data-streams):
- **Verifier config account PDA**:
- Derived using the verifier program ID as a seed
- Stores verification-specific configuration
- Used to ensure consistent verification parameters across all reports
- **Report config account PDA**:
- Derived using the feed ID (first 32 bytes of the uncompressed signed report) as a seed
- Contains feed-specific configuration and constraints
- Ensures that each feed's verification follows its designated rules
The SDK's `VerifierInstructions::verify` helper method performs these steps:
1. Extracts the necessary seeds
2. Computes the PDAs using `Pubkey::find_program_derived_address`
3. Includes these derived addresses in the instruction data
#### [Best practices](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification\#best-practices)
This guide provides a basic example on how to verify reports. When you implement reports verification, consider the following best practices:
- Implement robust error handling:
- Handle verification failures and invalid reports comprehensively
- Implement proper error reporting and logging for debugging
- Add custom error types for different failure scenarios
- Add appropriate validations:
- Price threshold checks to prevent processing extreme values
- Timestamp validations to ensure data freshness
- Custom feed-specific validations based on your use case
## What's next
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
- [\> Learn how to verify reports on Solana offchain](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-offchain-report-verification)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Stream V4 Reports Rust
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Stream and decode V4 reports via WebSocket using the Rust SDK](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust\#overview)
## Guide Versions
This guide is available in multiple versions. Choose the one that matches your needs.
Rust SDK - V4 reports for RWA streams
[Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go) [Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go) [Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rust) [Rust SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust)
In this guide, you'll learn how to use Chainlink Data Streams with the _[Streams Direct](https://docs.chain.link/data-streams/streams-direct)_ implementation and the [Data Streams SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk) for Rust to subscribe to real-time [V4 reports](https://docs.chain.link/data-streams/reference/report-schema-v4) for [Real World Assets (RWA) streams](https://docs.chain.link/data-streams/rwa-streams) via a [WebSocket connection](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws). You'll set up your Rust project, listen for real-time reports from the Data Streams Aggregation Network, decode the report data, and log their attributes to your terminal.
## [Requirements](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust\#requirements)
- **Git**: Make sure you have Git installed. You can check your current version by running `git --version` in your terminal and download the latest version from the official [Git website](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) if necessary.
- **Rust**: Make sure you have Rust installed. You can install Rust by following the instructions on the official [Rust website](https://www.rust-lang.org/tools/install).
- **API Credentials**: Access to the Streams Direct implementation requires API credentials. If you haven't already, [contact us](https://chainlinkcommunity.typeform.com/datastreams?typeform-source=docs.chain.link#ref_id=docs) to request mainnet or testnet access.
## [Guide](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust\#guide)
### [Set up your Rust project](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust\#set-up-your-rust-project)
1. Create a new directory for your project and navigate to it:

```bash
mkdir my-data-streams-project && cd my-data-streams-project
```
2. Initialize a new Rust project:

```bash
cargo init
```
3. Add the Data Streams SDK to your `Cargo.toml`:

```toml
[dependencies]
data-streams-sdk = { git = "https://github.com/smartcontractkit/data-streams-sdk.git", subdir = "rust/crates/sdk" }
data-streams-report = { git = "https://github.com/smartcontractkit/data-streams-sdk.git", subdir = "rust/crates/report" }
tokio = { version = "1.4", features = ["full"] }
hex = "0.4"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["time"] }
```
### [Establish a WebSocket connection and listen for real-time reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust\#establish-a-websocket-connection-and-listen-for-real-time-reports)
1. Replace the contents of `src/main.rs` with the following code:

```rust
use data_streams_report::feed_id::ID;
use data_streams_report::report::{decode_full_report, v4::ReportDataV4}; // Import the v4 report schema for RWA streams
use data_streams_sdk::config::Config;
use data_streams_sdk::stream::Stream;
use std::env;
use std::error::Error;
use tracing::{info, warn};
use tracing_subscriber::fmt::time::UtcTime;
#[tokio::main]
async fn main() -> Result<(), Box> {
// Initialize logging with UTC timestamps
tracing_subscriber::fmt()
.with_timer(UtcTime::rfc_3339())
.with_max_level(tracing::Level::INFO)
.init();
// Get feed IDs from command line arguments
let args: Vec = env::args().collect();
if args.len() < 2 {
eprintln!("Usage: cargo run [StreamID1] [StreamID2] ...");
std::process::exit(1);
}
// Get API credentials from environment variables
let api_key = env::var("API_KEY").expect("API_KEY must be set");
let api_secret = env::var("API_SECRET").expect("API_SECRET must be set");
// Parse feed IDs from command line arguments
let mut feed_ids = Vec::new();
for arg in args.iter().skip(1) {
let feed_id = ID::from_hex_str(arg)?;
feed_ids.push(feed_id);
}
// Initialize the configuration
let config = Config::new(
api_key,
api_secret,
"https://api.testnet-dataengine.chain.link".to_string(),
"wss://ws.testnet-dataengine.chain.link".to_string(),
)
.build()?;
// Create and initialize the stream
let mut stream = Stream::new(&config, feed_ids).await?;
stream.listen().await?;
info!("WebSocket connection established. Listening for reports...");
// Process incoming reports
loop {
match stream.read().await {
Ok(response) => {
info!("\nRaw report data: {:?}\n", response.report);
// Decode the report
let full_report = hex::decode(&response.report.full_report[2..])?;
let (_report_context, report_blob) = decode_full_report(&full_report)?;
let report_data = ReportDataV4::decode(&report_blob)?;
// Print decoded report details
info!(
"\n--- Report Stream ID: {} ---\n\
------------------------------------------\n\
Observations Timestamp : {}\n\
Benchmark Price : {}\n\
Valid From Timestamp : {}\n\
Expires At : {}\n\
Link Fee : {}\n\
Native Fee : {}\n\
Market Status : {}\n\
------------------------------------------",
response.report.feed_id.to_hex_string(),
response.report.observations_timestamp,
report_data.price,
response.report.valid_from_timestamp,
report_data.expires_at,
report_data.link_fee,
report_data.native_fee,
report_data.market_status
);
// Print stream stats
info!(
"\n--- Stream Stats ---\n{:#?}\n\
--------------------------------------------------------------------------------------------------------------------------------------------",
stream.get_stats()
);
}
Err(e) => {
warn!("Error reading from stream: {:?}", e);
}
}
}
}
```
2. Set up your API credentials as environment variables:

```bash
export API_KEY=""
export API_SECRET=""
```
Replace `` and `` with your API credentials.
3. For this example, you'll subscribe to the AUD/USD Data Streams RWA stream. This stream ID is `0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea`. See the [RWA Streams](https://docs.chain.link/data-streams/rwa-streams) page for a complete list of available real-world assets.
Build and run your application:

```bash
cargo run -- 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea
```
Expect output similar to the following in your terminal:

```bash
2024-12-13T23:37:17.054816Z INFO my_data_streams_project: WebSocket connection established. Listening for reports...
2024-12-13T23:37:17.054876Z INFO data_streams_sdk::stream::monitor_connection: Received ping: [49]
2024-12-13T23:37:17.054896Z INFO data_streams_sdk::stream::monitor_connection: Responding with pong: [49]
2024-12-13T23:37:17.199112Z INFO data_streams_sdk::stream::monitor_connection: Received new report from Data Streams Endpoint.
2024-12-13T23:37:17.199304Z INFO my_data_streams_project:
Raw report data: Report { feed_id: 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea, valid_from_timestamp: 1734133037, observations_timestamp: 1734133037, full_report: "0x0006aee203ef23a892e75b579f8c3f26fd933d9ca45de95c2f8ac470f4ddcd76000000000000000000000000000000000000000000000000000000000b42b108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea00000000000000000000000000000000000000000000000000000000675cc52d00000000000000000000000000000000000000000000000000000000675cc52d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000675e16ad00000000000000000000000000000000000000000000000008d4182644500000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021521eae32097ed41bc3dad69f365da1979d155b574cc84e4dfb9e7970821d6bc40fac4c300b09b7cfae106f1008b4bec83edd27f20c5a3ad6b2c736e0765ecc500000000000000000000000000000000000000000000000000000000000000024941c68ad5a7d69e92fc927633634cd6cf478f7c11e3c3408341b462dac292ce66cc18bf09c30ad1df589dbfc0a19172a4719bb51efe83450ce14d959bccf541" }
2024-12-13T23:37:17.199585Z INFO my_data_streams_project:
--- Report Stream ID: 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea ---
------------------------------------------
Observations Timestamp : 1734133037
Benchmark Price : 636160000000000000
Valid From Timestamp : 1734133037
Expires At : 1734219437
Link Fee : 0
Native Fee : 0
Market Status : 1
------------------------------------------
2024-12-13T23:37:17.199633Z INFO my_data_streams_project:
--- Stream Stats ---
StatsSnapshot {
accepted: 1,
deduplicated: 0,
total_received: 1,
partial_reconnects: 0,
full_reconnects: 0,
configured_connections: 1,
active_connections: 1,
}
--------------------------------------------------------------------------------------------------------------------------------------------
2024-12-13T23:37:18.215222Z INFO data_streams_sdk::stream::monitor_connection: Received new report from Data Streams Endpoint.
2024-12-13T23:37:18.21587Z INFO my_data_streams_project:
Raw report data: Report { feed_id: 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea, valid_from_timestamp: 1734133038, observations_timestamp: 1734133038, full_report: "0x0006aee203ef23a892e75b579f8c3f26fd933d9ca45de95c2f8ac470f4ddcd76000000000000000000000000000000000000000000000000000000000b42b10c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea00000000000000000000000000000000000000000000000000000000675cc52e00000000000000000000000000000000000000000000000000000000675cc52e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000675e16ae00000000000000000000000000000000000000000000000008d4182644500000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000026a76e4abe53b8f3f7f0ca1628335a0da840d28502ea2c44e67951b17b8cc74da781aa786d5503c09043c29d0db71db2b0de3b5b5302a9050b7acdf93fdf4a36f00000000000000000000000000000000000000000000000000000000000000027d06597171eceea257fc1eaa222d4b47a0b5d227e8bf746031e9061806e55b2778fa8c6e10a574d7f9a4e192090f71769468eb3e626b3354e6cdaadff120e170" }
2024-12-13T23:37:18.216946Z INFO my_data_streams_project:
--- Report Stream ID: 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea ---
------------------------------------------
Observations Timestamp : 1734133038
Benchmark Price : 636160000000000000
Valid From Timestamp : 1734133038
Expires At : 1734219438
Link Fee : 0
Native Fee : 0
Market Status : 1
------------------------------------------
2024-12-13T23:37:18.21714Z INFO my_data_streams_project:
--- Stream Stats ---
StatsSnapshot {
accepted: 2,
deduplicated: 0,
total_received: 2,
partial_reconnects: 0,
full_reconnects: 0,
configured_connections: 1,
active_connections: 1,
}
[...]
```
The example above demonstrates streaming data from a single RWA stream. For production environments, especially when subscribing to multiple streams, it's recommended to enable [High Availability (HA) mode](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/docs/examples/wss_multiple.md). This can be achieved by:
1. Adding multiple WebSocket endpoints in the configuration:

```rust
"wss://ws.testnet-dataengine.chain.link,wss://ws.testnet-dataengine.chain.link"
```
2. Enabling HA mode in the configuration:

```rust
use data_streams_sdk::config::WebSocketHighAvailability;
// ...
.with_ws_ha(WebSocketHighAvailability::Enabled)
```
When HA mode is enabled and multiple WebSocket origins are provided, the Stream will maintain concurrent connections to different instances. This ensures high availability, fault tolerance, and minimizes the risk of report gaps.
You can subscribe to multiple streams by providing additional stream IDs as command-line arguments:

```bash
cargo run -- \
0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea \
0x0004f41f3d47d2c15f817309d905d4508e809c98b1eafc7b6cdc2a6c8ec23f3f
```
This will subscribe to both AUD/USD and EUR/USD streams.
#### [Decoded report details](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust\#decoded-report-details)
The decoded report details include:
| Attribute | Value | Description |
| --- | --- | --- |
| `Stream ID` | `0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea` | The unique identifier for the stream. In this example, the stream is for AUD/USD. |
| `Observations Timestamp` | `1734133037` | The timestamp indicating when the data was captured. |
| `Benchmark Price` | `636160000000000000` | The observed price in the report, with 18 decimals. For readability: `0.63616` USD per AUD. |
| `Valid From Timestamp` | `1734133037` | The start validity timestamp for the report, indicating when the data becomes relevant. |
| `Expires At` | `1734219437` | The expiration timestamp of the report, indicating the point at which the data becomes outdated. |
| `Link Fee` | `0` | The fee to pay in LINK tokens for the onchain verification of the report data. With 18 decimals. **Note:** This example fee is not indicative of actual fees. |
| `Native Fee` | `0` | The fee to pay in the native blockchain token (e.g., ETH on Ethereum) for the onchain verification of the report data. With 18 decimals. **Note:** This example fee is not indicative of actual fees. |
| `Market Status` | `1` | The DON's consensus on whether the market is currently open. Possible values: `0` ( `Unknown`), `1` ( `Closed`), `2` ( `Open`). In this case, the market is closed. |
#### [Payload for onchain verification](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust\#payload-for-onchain-verification)
In this guide, you log and decode the `full_report` payload to extract the report data. In a
production environment, you should verify the data onchain to ensure its integrity and authenticity. Refer to the
[Verify report data onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-onchain-verification) guide.
## [Explanation](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust\#explanation)
### [Establishing a WebSocket connection and listening for reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust\#establishing-a-websocket-connection-and-listening-for-reports)
The WebSocket connection is established in two steps:
1. [`Stream::new`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/stream.rs#L131) initializes a new stream instance with your configuration and feed IDs. This function prepares the connection parameters but doesn't establish the connection yet.
2. [`stream.listen()`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/stream.rs#L162) establishes the actual WebSocket connection and starts the background tasks that maintain the connection. These tasks handle:
- Automatic reconnection if the connection is lost
- Ping/pong messages to keep the connection alive
- Message queueing and delivery
### [Decoding a report](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust\#decoding-a-report)
As data reports arrive via the WebSocket connection, they are processed in real-time through several steps:
1. Reading streams: The [`read`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/stream.rs#L218) method on the Stream object is called within a loop. This asynchronous method:
- Awaits the next report from the WebSocket connection
- Handles backpressure automatically
- Returns a `WebSocketReport` containing the report data
2. Decoding reports: Each report is decoded in two stages:
- [`decode_full_report`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/report/src/report.rs#L77) parses the raw hexadecimal data, separating the report context (containing metadata) from the report blob
- [`ReportDataV4::decode`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/report/src/report/v4.rs#L57) transforms the report blob into a structured format containing:
- The benchmark price (with 18 decimal places)
- Market status (indicating if the market is open, closed, or unknown)
- Fee information for onchain verification
- Timestamp information
### [Handling the decoded data](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust\#handling-the-decoded-data)
The example demonstrates several best practices for handling the decoded data:
1. Logging:
- Uses the [`tracing`](https://github.com/tokio-rs/tracing) crate for structured logging
- Configures UTC timestamps for consistent time representation
- Includes both raw report data and decoded fields for debugging
2. Error handling:
- Uses Rust's `Result` type for robust error handling
- Implements the `?` operator for clean error propagation
- Logs errors with appropriate context using `warn!` macro
3. Stream monitoring:
- Tracks stream statistics through [`get_stats()`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/stream.rs#L253)
- Monitors connection status and reconnection attempts
- Reports message acceptance and deduplication counts
The decoded data can be used for further processing, analysis, or display in your application. For production environments, it's recommended to verify the data onchain using the provided `full_report` payload.
## What's next
- [\> Learn how to verify your data onchain](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification)
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/rwa-streams)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Fetch V4 Reports in Rust
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Fetch and decode V4 reports using the Rust SDK](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#overview)
## Guide Versions
This guide is available in multiple versions. Choose the one that matches your needs.
Rust SDK - V4 reports for RWA streams
[Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-go) [Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go) [Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust) [Rust SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust)
In this guide, you'll learn how to use Chainlink Data Streams with the _[Streams Direct](https://docs.chain.link/data-streams/streams-direct) implementation_ and the [Data Streams SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-rust-sdk) for Rust to fetch and decode [V4 reports](https://docs.chain.link/data-streams/reference/report-schema-v4) for [Real World Assets (RWAs) streams](https://docs.chain.link/data-streams/rwa-streams) from the Data Streams Aggregation Network. You'll set up your Rust project, retrieve reports, decode them, and log their attributes.
## [Requirements](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#requirements)
- **Git**: Make sure you have Git installed. You can check your current version by running `git --version` in your terminal and download the latest version from the official [Git website](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) if necessary.
- **Rust**: Make sure you have Rust installed. You can install Rust by following the instructions on the official [Rust website](https://www.rust-lang.org/tools/install).
- **API Credentials**: Access to the Streams Direct implementation requires API credentials. If you haven't already, [contact us](https://chainlinkcommunity.typeform.com/datastreams?typeform-source=docs.chain.link#ref_id=docs) to request mainnet or testnet access.
## [Guide](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#guide)
You'll start with the set up of your Rust project. Next, you'll fetch and decode reports for RWA streams and log their attributes to your terminal.
### [Set up your Rust project](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#set-up-your-rust-project)
1. Create a new directory for your project and navigate to it:

```bash
mkdir my-data-streams-project && cd my-data-streams-project
```
2. Initialize a new Rust project:

```bash
cargo init
```
3. Add the Data Streams SDK to your `Cargo.toml`:

```toml
[dependencies]
data-streams-sdk = { git = "https://github.com/smartcontractkit/data-streams-sdk.git", subdir = "rust/crates/sdk" }
data-streams-report = { git = "https://github.com/smartcontractkit/data-streams-sdk.git", subdir = "rust/crates/report" }
tokio = { version = "1.4", features = ["full"] }
hex = "0.4"
```
### [Fetch and decode a report with a single stream](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#fetch-and-decode-a-report-with-a-single-stream)
1. Replace the contents of `src/main.rs` with the following code:

```rust
use data_streams_report::feed_id::ID;
use data_streams_report::report::{decode_full_report, v4::ReportDataV4}; // Import the v4 report schema for RWA streams
use data_streams_sdk::client::Client;
use data_streams_sdk::config::Config;
use std::env;
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box> {
// Get feed ID from command line arguments
let args: Vec = env::args().collect();
if args.len() < 2 {
eprintln!("Usage: cargo run [FeedID]");
std::process::exit(1);
}
let feed_id_input = &args[1];
// Get API credentials from environment variables
let api_key = env::var("API_KEY").expect("API_KEY must be set");
let api_secret = env::var("API_SECRET").expect("API_SECRET must be set");
// Initialize the configuration
let config = Config::new(
api_key,
api_secret,
"https://api.testnet-dataengine.chain.link".to_string(),
"wss://api.testnet-dataengine.chain.link/ws".to_string(),
)
.build()?;
// Initialize the client
let client = Client::new(config)?;
// Parse the feed ID
let feed_id = ID::from_hex_str(feed_id_input)?;
// Fetch the latest report
let response = client.get_latest_report(feed_id).await?;
println!("\nRaw report data: {:?}\n", response.report);
// Decode the report
let full_report = hex::decode(&response.report.full_report[2..])?;
let (_report_context, report_blob) = decode_full_report(&full_report)?;
let report_data = ReportDataV4::decode(&report_blob)?;
// Print decoded report details
println!("\nDecoded Report for Stream ID {}:", feed_id_input);
println!("------------------------------------------");
println!("Observations Timestamp: {}", response.report.observations_timestamp);
println!("Benchmark Price : {}", report_data.price);
println!("Valid From Timestamp : {}", response.report.valid_from_timestamp);
println!("Expires At : {}", report_data.expires_at);
println!("Link Fee : {}", report_data.link_fee);
println!("Native Fee : {}", report_data.native_fee);
println!("Market Status : {}", report_data.market_status);
println!("------------------------------------------");
Ok(())
}
```
2. Set up your API credentials as environment variables:

```bash
export API_KEY=""
export API_SECRET=""
```
Replace `` and `` with your API credentials.
3. For this example, you will read from the AUD/USD stream. This stream ID is `0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea`. See the [Data Streams RWA streams](https://docs.chain.link/data-streams/rwa-streams) page for a complete list of available Real World Assets.
Build and run your application:

```bash
cargo run -- 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea
```
Expect output similar to the following in your terminal:

```bash
Raw report data: Report { feed_id: 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea, valid_from_timestamp: 1734125487, observations_timestamp: 1734125487, full_report: "0x0006aee203ef23a892e75b579f8c3f26fd933d9ca45de95c2f8ac470f4ddcd76000000000000000000000000000000000000000000000000000000000b3df40a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea00000000000000000000000000000000000000000000000000000000675ca7af00000000000000000000000000000000000000000000000000000000675ca7af0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000675df92f00000000000000000000000000000000000000000000000008d2f51c75fc000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002a98627fc63e8af57652d69149a23df6fe4d1bccdfcd013a4a9c0faafb4ab3830bdfb30e2d6c6d3f894b5ed7b4761f9236431548efa15f100fd5a61804cef21c0000000000000000000000000000000000000000000000000000000000000000266dc0c7d18ccc26c566df4820fd68cca5a076215d982c74abf7ae089bc24d3520716cfefdd127f522a2f98f90227926ed786479977d99ac9f91d5c99120e3cb3" }
Decoded Report for Stream ID 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea:
------------------------------------------
Observations Timestamp: 1734125487
Benchmark Price : 635840000000000000
Valid From Timestamp : 1734125487
Expires At : 1734211887
Link Fee : 0
Native Fee : 0
Market Status : 2
------------------------------------------
```
#### [Decoded report details](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#decoded-report-details)
The decoded report details include:
| Attribute | Value | Description |
| --- | --- | --- |
| `Stream ID` | `0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea` | The unique identifier for the stream. In this example, the stream is for AUD/USD. |
| `Observations Timestamp` | `1734125487` | The timestamp indicating when the data was captured. |
| `Benchmark Price` | `635840000000000000` | The observed price in the report, with 18 decimals. For readability: `0.63584` USD per AUD. |
| `Valid From Timestamp` | `1734125487` | The start validity timestamp for the report, indicating when the data becomes relevant. |
| `Expires At` | `1734211887` | The expiration timestamp of the report, indicating the point at which the data becomes outdated. |
| `Link Fee` | `0` | The fee to pay in LINK tokens for the onchain verification of the report data. With 18 decimals. **Note:** This example fee is not indicative of actual fees. |
| `Native Fee` | `0` | The fee to pay in the native blockchain token (e.g., ETH on Ethereum) for the onchain verification of the report data. With 18 decimals. **Note:** This example fee is not indicative of actual fees. |
| `Market Status` | `2` | The DON's consensus on whether the market is currently open. Possible values: `0` ( `Unknown`), `1` ( `Closed`), `2` ( `Open`). |
#### [Payload for onchain verification](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#payload-for-onchain-verification)
In this guide, you log and decode the `full_report` payload to extract the report data. In a
production environment, you should verify the data to ensure its integrity and authenticity. Refer to the
[Verify report data onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-onchain-verification) guide.
## [Explanation](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#explanation)
### [Initializing the API client and configuration](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#initializing-the-api-client-and-configuration)
The API client is initialized in two steps:
1. [`Config::new`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/config.rs#L131) creates a configuration with your API credentials and endpoints. This function:
- Validates your API key and secret
- Sets up the REST API endpoint for data retrieval
- Configures optional settings like TLS verification
2. [`Client::new`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/client.rs#L131) creates the HTTP client with your configuration. This client:
- Handles authentication automatically
- Manages HTTP connections efficiently
- Implements retry logic for failed requests
### [Fetching reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#fetching-reports)
The SDK provides several methods to fetch reports through the REST API:
1. Latest report: [`get_latest_report`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/client.rs#L165) retrieves the most recent report for a feed:
- Takes a feed ID as input
- Returns a single report with the latest timestamp
- Useful for applications that need the most current data
2. Historical report: [`get_report`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/sdk/src/client.rs#L242) fetches a report at a specific timestamp:
- Takes both feed ID and timestamp
- Returns the report closest to the requested timestamp
- Helpful for historical analysis or verification
Each API request automatically:
- Generates HMAC authentication headers
- Includes proper timestamps
- Handles HTTP response status codes
- Deserializes the JSON response into Rust structures
### [Decoding reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#decoding-reports)
Reports are decoded in three stages:
1. Hex decoding: The `full_report` field comes as a hex string prefixed with "0x":

```rust
let full_report = hex::decode(&response.report.full_report[2..])?;
```
2. Report separation: [`decode_full_report`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/report/src/report.rs#L77) splits the binary data:
- Extracts the report context (metadata)
- Isolates the report blob (actual data)
- Validates the report format
3. Data extraction: [`ReportDataV4::decode`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/crates/report/src/report/v4.rs#L57) parses the report blob into structured data:
- Price (18 decimal places)
- Market status (Open, Closed, or Unknown)
- Fee information for onchain verification
- Timestamp information
### [Error handling](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust\#error-handling)
The example demonstrates Rust's robust error handling:
1. Type-safe errors:
- Uses custom error types for different failure scenarios
- Implements the `Error` trait for proper error propagation
- Provides detailed error messages for debugging
2. Error propagation:
- Uses the `?` operator for clean error handling
- Converts errors between types when needed
- Bubbles up errors to the main function
3. Input validation:
- Checks command-line arguments
- Validates environment variables
- Verifies feed ID format
The decoded data can be used for further processing, analysis, or display in your application. For production environments, you must verify the data onchain using the provided `full_report` payload.
## What's next
- [\> Learn how to stream and decode reports via a WebSocket connection](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rust)
- [\> Learn how to verify your data onchain](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification)
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/rwa-streams)
## Get the latest Chainlink content straight to your inbox.
Email Address
## StreamsLookup Error Handling
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Using the StreamsLookup error handler](https://docs.chain.link/data-streams/tutorials/streams-trade/streams-trade-lookup-error-handler\#overview)
The Chainlink Automation StreamsLookup error handler provides insight into potential errors or edge cases in StreamsLookup upkeeps. The table below outlines a range of error codes and the behavior associated with the codes. Use the `checkErrorHandler` function to specify how you want to respond to the error codes. `checkErrorHandler` is simulated offchain and determines what action for Automation to take onchain in `performUpkeep`.
## [Error handler](https://docs.chain.link/data-streams/tutorials/streams-trade/streams-trade-lookup-error-handler\#error-handler)
When Automation detects an event, it runs the `checkLog` function, which includes a [StreamsLookup revert](https://docs.chain.link/chainlink-automation/reference/automation-interfaces#streamslookup-revert) custom error. The StreamsLookup revert enables your upkeep to fetch a report from Data Streams. If reports are fetched successfully, the [`checkCallback`](https://docs.chain.link/chainlink-automation/reference/automation-interfaces#checkcallback-function) function is evaluated offchain. Otherwise, the `checkErrorHandler` function is evaluated offchain to determine what Automation should do next. Both of these functions have the same output types ( `bool upkeepNeeded, bytes memory performData`), which Automation uses to run `performUpkeep` onchain. The [example code](https://docs.chain.link/data-streams/tutorials/streams-trade/streams-trade-lookup-error-handler#example-code) also shows each function outlined in the diagram below:

If the Automation network fails to get the requested reports, an error code is sent to the `checkErrorHandler` function in your contract. If your contract doesn't have the `checkErrorHandler` function, nothing will happen. If your contract has the `checkErrorHandler` function, it is evaluated offchain to determine what to do next. For example, you could intercept or ignore certain errors and decide not to run `performUpkeep` in those cases, in order to save time and gas. For other errors, you can execute an alternative path within `performUpkeep`, and the upkeep runs the custom logic you define in your `performUpkeep` function to handle those errors.
1. Add the `checkErrorHandler` function in your contract to specify how you want to handle [error codes](https://docs.chain.link/data-streams/tutorials/streams-trade/streams-trade-lookup-error-handler#error-codes). For example, you could decide to ignore any codes related to bad requests or incorrect input, without running `performUpkeep` onchain:

```solidity
/**
* @notice Determines the need for upkeep in response to an error from Data Streams.
* @param errorCode The error code returned by the Data Streams lookup.
* @param extraData Additional context or data related to the error condition.
* @return upkeepNeeded Boolean indicating whether upkeep is needed based on the error.
* @return performData Data to be used if upkeep is performed, encoded with success state and error context.
*/
function checkErrorHandler(
uint errorCode,
bytes calldata extraData
) external returns (bool upkeepNeeded, bytes memory performData) {
// Add custom logic to handle errors offchain here
bool _upkeepNeeded = true;
bool reportSuccess = false;
if (errorCode == 808400) {
// Handle bad request errors code offchain.
// In this example, no upkeep needed for bad request errors.
_upkeepNeeded = false;
} else {
// Handle other errors as needed.
}
return (_upkeepNeeded, abi.encode(reportSuccess, abi.encode(errorCode, extraData)));
}
```
2. Define custom logic for the alternative path within `performUpkeep`, to handle any error codes you did not intercept offchain in `checkErrorHandler`:

```solidity
// function will be performed on-chain
function performUpkeep(bytes calldata performData) external {
// Decode incoming performData
(bool reportSuccess, bytes memory payload) = abi.decode(performData, (bool, bytes));
if (reportSuccess) {
// Decode the performData bytes passed in by CL Automation.
// This contains the data returned by your implementation in checkCallback().
(bytes[] memory signedReports, bytes memory extraData) = abi.decode(payload, (bytes[], bytes));
// Logic to verify and decode report
// ...
} else {
// Handle error condition
(uint errorCode, bytes memory extraData) = abi.decode(payload, (uint, bytes));
// Custom logic to handle error codes
}
}
```
### [Testing checkErrorHandler](https://docs.chain.link/data-streams/tutorials/streams-trade/streams-trade-lookup-error-handler\#testing-checkerrorhandler)
`checkErrorHandler` is simulated offchain. When `upkeepNeeded` returns `true`, Automation runs `performUpkeep` onchain using the `performData` from `checkErrorHandler`. If the `checkErrorHandler` function itself reverts, `performUpkeep` does not run.
If you need to force errors in StreamsLookup while testing, you can try the following methods:
- Not specifying any `feedID` to force error code 808400 ( `ErrCodeStreamsBadRequest`)
- Specifying an incorrect `feedID` to force error code 808401 ( `ErrCodeStreamsBadRequest`)
- Specifying a future timestamp to force error code 808206 (where partial content is received) for both single `feedID` and bulk `feedID` requests
- Specifying old timestamps for reports not available anymore yields either error code 808504 (no response) or 808600 (bad response), depending on which service calls the timeout request
If your [StreamsLookup revert](https://docs.chain.link/chainlink-automation/reference/automation-interfaces#streamslookup-revert) function is defined incorrectly in your smart contracts, the nodes will not be able to decode it.
## [Error codes](https://docs.chain.link/data-streams/tutorials/streams-trade/streams-trade-lookup-error-handler\#error-codes)
| Error code | Retries | Possible cause of error |
| --- | --- | --- |
| No error | N/A | No error |
| ErrCodeStreamsBadRequest: 808400 | No | User requested 0 feeds |
| User error, incorrect parameter input |
| Issue with encoding http url (bad characters) |
| ErrCodeStreamsUnauthorized: 808401 | No | Key access issue or incorrect feedID |
| 808206 | Log trigger - after retries; Conditional immediately | Requested m reports but only received n (partial) |
| 8085XX (e.g 808500) | Log trigger - after retries; Conditional immediately | No response |
| ErrCodeStreamsBadResponse: 808600 | No | Error in reading body of returned response, but service is up |
| ErrCodeStreamsTimeout: 808601 | No | No valid report is received for 10 seconds |
| ErrCodeStreamsUnknownError: 808700 | No | Unknown |
## [Example code](https://docs.chain.link/data-streams/tutorials/streams-trade/streams-trade-lookup-error-handler\#example-code)
This example code includes the `revert StreamsLookup`, `checkCallback`, `checkErrorHandler` and `performUpkeep` functions. The full code example is available [here](https://github.com/smartcontractkit/documentation/blob/main/public/samples/DataStreams/StreamsUpkeepWithErrorHandler.sol).

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {StreamsLookupCompatibleInterface} from "@chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol";
import {ILogAutomation, Log} from "@chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol";
import {IRewardManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol";
import {IVerifierFeeManager} from "@chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol";
import {IERC20} from "@chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol";
import {Common} from "@chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol";
/**
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
// =====================
// INTERFACES
// =====================
interface IFeeManager {
/**
* @notice Calculates the fee and reward associated with verifying a report, including discounts for subscribers.
* This function assesses the fee and reward for report verification, applying a discount for recognized subscriber addresses.
* @param subscriber The address attempting to verify the report. A discount is applied if this address
* is recognized as a subscriber.
* @param unverifiedReport The report data awaiting verification. The content of this report is used to
* determine the base fee and reward, before considering subscriber discounts.
* @param quoteAddress The payment token address used for quoting fees and rewards.
* @return fee The fee assessed for verifying the report, with subscriber discounts applied where applicable.
* @return reward The reward allocated to the caller for successfully verifying the report.
* @return totalDiscount The total discount amount deducted from the fee for subscribers.
*/
function getFeeAndReward(
address subscriber,
bytes memory unverifiedReport,
address quoteAddress
) external returns (Common.Asset memory, Common.Asset memory, uint256);
function i_linkAddress() external view returns (address);
function i_nativeAddress() external view returns (address);
function i_rewardManager() external view returns (address);
}
interface IVerifierProxy {
/**
* @notice Verifies that the data encoded has been signed.
* correctly by routing to the correct verifier, and bills the user if applicable.
* @param payload The encoded data to be verified, including the signed
* report.
* @param parameterPayload Fee metadata for billing. In the current implementation,
* this consists of the abi-encoded address of the ERC-20 token used for fees.
* @return verifierResponse The encoded report from the verifier.
*/
function verify(
bytes calldata payload,
bytes calldata parameterPayload
) external payable returns (bytes memory verifierResponse);
function s_feeManager() external view returns (IVerifierFeeManager);
}
// ==========================
// CONTRACT IMPLEMENTATION
// ==========================
contract StreamsUpkeepWithErrorHandler is
ILogAutomation,
StreamsLookupCompatibleInterface
{
error InvalidReportVersion(uint16 version); // Thrown when an unsupported report version is provided to verifyReport.
/**
* @dev Represents a data report from a Data Streams feed for v3 schema (crypto streams).
* The `price`, `bid`, and `ask` values are carried to either 8 or 18 decimal places, depending on the feed.
* For more information, see https://docs.chain.link/data-streams/crypto-streams and https://docs.chain.link/data-streams/reference/report-schema
*/
struct ReportV3 {
bytes32 feedId; // The feed ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median price (8 or 18 decimals).
int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation (8 or 18 decimals).
int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation (8 or 18 decimals).
}
/**
* @dev Represents a data report from a Data Streams feed for v4 schema (RWA feeds).
* The `price` value is carried to either 8 or 18 decimal places, depending on the feed.
* The `marketStatus` indicates whether the market is currently open. Possible values: `0` (`Unknown`), `1` (`Closed`), `2` (`Open`).
* For more information, see https://docs.chain.link/data-streams/rwa-streams and https://docs.chain.link/data-streams/reference/report-schema-v4
*/
struct ReportV4 {
bytes32 feedId; // The feed ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median benchmark price (8 or 18 decimals).
uint32 marketStatus; // The DON's consensus on whether the market is currently open.
}
struct Quote {
address quoteAddress;
}
event PriceUpdate(int192 indexed price);
event ErrorTestLog(uint indexed errorCode);
IVerifierProxy public verifier;
address public FEE_ADDRESS;
string public constant STRING_DATASTREAMS_FEEDLABEL = "feedIDs";
string public constant STRING_DATASTREAMS_QUERYLABEL = "timestamp";
uint256 public s_error;
bool public s_isError;
string[] public feedIds = [\
"0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782" // Ex. ETH/USD Feed ID\
];
constructor(address _verifier) {
verifier = IVerifierProxy(_verifier); //Arbitrum Sepolia: 0x2ff010debc1297f19579b4246cad07bd24f2488a
}
// This function uses revert to convey call information.
// See https://eips.ethereum.org/EIPS/eip-3668#rationale for details.
function checkLog(
Log calldata log,
bytes memory
) external returns (bool upkeepNeeded, bytes memory performData) {
revert StreamsLookup(
STRING_DATASTREAMS_FEEDLABEL,
feedIds,
STRING_DATASTREAMS_QUERYLABEL,
log.timestamp,
""
);
}
/**
* @dev This function is intended for off-chain simulation by Chainlink Automation to pass in the data reports fetched from Data Streams.
* @param values The bytes array of data reports fetched from Data Streams.
* @param extraData Contextual or additional data related to the feed lookup process.
* @return upkeepNeeded Indicates that upkeep is needed to pass the data to the on-chain performUpkeep function.
* @return performData Encoded data indicating success and including the original `values` and `extraData`, to be used in `performUpkeep`.
*/
function checkCallback(
bytes[] calldata values,
bytes calldata extraData
) external pure returns (bool upkeepNeeded, bytes memory) {
bool reportSuccess = true; // Indicates successful data retrieval
return (true, abi.encode(reportSuccess, abi.encode(values, extraData)));
}
/**
* @notice Determines the need for upkeep in response to an error from Data Streams.
* @dev This function serves as an example of how errors can be handled offchain.
* @dev Developers can parameterize this logic as needed.
* @dev All error codes are documented at: https://docs.chain.link/chainlink-automation/guides/streams-lookup-error-handler#error-codes
* @param errorCode The error code returned by the Data Streams lookup.
* @param extraData Additional context or data related to the error condition.
* @return upkeepNeeded Boolean indicating whether upkeep is needed based on the error.
* @return performData Data to be used if upkeep is performed, encoded with success state and error context.
*/
function checkErrorHandler(
uint errorCode,
bytes calldata extraData
) external view returns (bool upkeepNeeded, bytes memory performData) {
bool _upkeepNeeded = false;
bool reportSuccess = false;
if (errorCode == 0) {
// If there is no error, proceed with the performUpkeep and
// the report decoding/verification
_upkeepNeeded = true;
reportSuccess = true;
} else if (errorCode == 808400 || errorCode == 808401) {
// Mark upkeep as needed for bad requests (808400) and incorrect feed ID (808401)
// to handle these specific errors onchain.
_upkeepNeeded = true;
// Note that reportSuccess remains false.
} else {
// For other error codes, decide not to perform upkeep.
// This is the default behavior, explicitly noted for clarity in this example.
_upkeepNeeded = false;
reportSuccess = false;
}
return (
_upkeepNeeded,
abi.encode(reportSuccess, abi.encode(errorCode, extraData))
);
}
function performUpkeep(bytes calldata performData) external {
// Decode incoming performData
(bool reportSuccess, bytes memory payload) = abi.decode(
performData,
(bool, bytes)
);
if (reportSuccess) {
// Decode the performData bytes passed in by CL Automation.
// This contains the data returned by your implementation in checkCallback().
(bytes[] memory signedReports, bytes memory extraData) = abi.decode(
payload,
(bytes[], bytes)
);
// Logic to verify and decode report
bytes memory unverifiedReport = signedReports[0];
(, bytes memory reportData) = abi.decode(
unverifiedReport,
(bytes32[3], bytes)
);
// Extract report version from reportData
uint16 reportVersion = (uint16(uint8(reportData[0])) << 8) |
uint16(uint8(reportData[1]));
// Validate report version
if (reportVersion != 3 && reportVersion != 4) {
revert InvalidReportVersion(uint8(reportVersion));
}
// Report verification fees
IFeeManager feeManager = IFeeManager(
address(verifier.s_feeManager())
);
IRewardManager rewardManager = IRewardManager(
address(feeManager.i_rewardManager())
);
address feeTokenAddress = feeManager.i_linkAddress();
(Common.Asset memory fee, , ) = feeManager.getFeeAndReward(
address(this),
reportData,
feeTokenAddress
);
// Approve rewardManager to spend this contract's balance in fees
IERC20(feeTokenAddress).approve(address(rewardManager), fee.amount);
// Verify the report
bytes memory verifiedReportData = verifier.verify(
unverifiedReport,
abi.encode(feeTokenAddress)
);
// Decode verified report data into the appropriate Report struct based on reportVersion
if (reportVersion == 3) {
// v3 report schema
ReportV3 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV3)
);
// Log price from report
emit PriceUpdate(verifiedReport.price);
} else if (reportVersion == 4) {
// v4 report schema
ReportV4 memory verifiedReport = abi.decode(
verifiedReportData,
(ReportV4)
);
// Log price from report
emit PriceUpdate(verifiedReport.price);
}
} else {
// Handle error condition
(uint errorCode, bytes memory extraData) = abi.decode(
payload,
(uint, bytes)
);
// Custom logic to handle error codes
s_error = errorCode;
s_isError = true;
}
}
fallback() external payable {}
receive() external payable {}
}
```
[Open in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/DataStreams/StreamsUpkeepWithErrorHandler.sol&autoCompile=true) [What is Remix?](https://docs.chain.link/getting-started/conceptual-overview#what-is-remix)
## What's next
- [\> Find the list of available feed IDs.](https://docs.chain.link/data-streams/crypto-streams)
- [\> Find the schema of data to expect from Data Streams reports.](https://docs.chain.link/data-streams/reference/report-schema)
- [\> Learn more about Log Trigger upkeeps](https://docs.chain.link/chainlink-automation/guides/log-trigger/)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Stream V4 Reports with Go
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Stream and decode V4 reports via WebSocket using the Go SDK](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go\#overview)
## Guide Versions
This guide is available in multiple versions. Choose the one that matches your needs.
Go SDK - V4 reports for RWA streams
[Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go) [Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go) [Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rust) [Rust SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-rust)
In this guide, you'll learn how to use Chainlink Data Streams with the _[Streams Direct](https://docs.chain.link/data-streams/streams-direct)_ implementation and the [Data Streams SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk) for Go to subscribe to real-time [V4 reports](https://docs.chain.link/data-streams/reference/report-schema-v4) for [Real World Assets (RWAs) streams](https://docs.chain.link/data-streams/rwa-streams) via a [WebSocket connection](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws). You'll set up your Go project, listen for real-time reports from the Data Streams Aggregation Network, decode the report data, and log their attributes to your terminal.
## [Requirements](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go\#requirements)
- **Git**: Make sure you have Git installed. You can check your current version by running `git --version` in your terminal and download the latest version from the official [Git website](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) if necessary.
- **Go Version**: Make sure you have Go version 1.21 or higher. You can check your current version by running `go version` in your terminal and download the latest version from the official [Go website](https://go.dev/) if necessary.
- **API Credentials**: Access to the Streams Direct implementation requires API credentials. If you haven't already, [contact us](https://chainlinkcommunity.typeform.com/datastreams?typeform-source=docs.chain.link#ref_id=docs) to request mainnet or testnet access.
## [Guide](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go\#guide)
### [Set up your Go project](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go\#set-up-your-go-project)
1. Create a new directory for your project and navigate to it:

```bash
mkdir my-data-streams-project
cd my-data-streams-project
```
2. Initialize a new Go module:

```bash
go mod init my-data-streams-project
```
3. Install the Data Streams SDK:

```bash
go get github.com/smartcontractkit/data-streams-sdk/go
```
### [Establish a WebSocket connection and listen for real-time reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go\#establish-a-websocket-connection-and-listen-for-real-time-reports)
1. Create a new Go file, `stream.go`, in your project directory:

```bash
touch stream.go
```
2. Insert the following code example and save your `stream.go` file:

```go
package main
import (
"context"
"fmt"
"os"
"time"
streams "github.com/smartcontractkit/data-streams-sdk/go"
feed "github.com/smartcontractkit/data-streams-sdk/go/feed"
report "github.com/smartcontractkit/data-streams-sdk/go/report"
v4 "github.com/smartcontractkit/data-streams-sdk/go/report/v4" // Import the v4 report schema for RWA streams. For Crypto streams, use the v3 schema.
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run stream.go [StreamID1] [StreamID2] ...")
os.Exit(1)
}
// Set up the SDK client configuration
cfg := streams.Config{
ApiKey: os.Getenv("API_KEY"),
ApiSecret: os.Getenv("API_SECRET"),
WsURL: "wss://ws.testnet-dataengine.chain.link",
Logger: streams.LogPrintf,
}
// Create a new client
client, err := streams.New(cfg)
if err != nil {
cfg.Logger("Failed to create client: %v\n", err)
os.Exit(1)
}
// Parse the feed IDs from the command line arguments
var ids []feed.ID
for _, arg := range os.Args[1:] {
var fid feed.ID
if err := fid.FromString(arg); err != nil {
cfg.Logger("Invalid stream ID %s: %v\n", arg, err)
os.Exit(1)
}
ids = append(ids, fid)
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Subscribe to the feeds
stream, err := client.Stream(ctx, ids)
if err != nil {
cfg.Logger("Failed to subscribe: %v\n", err)
os.Exit(1)
}
defer stream.Close()
for {
reportResponse, err := stream.Read(context.Background())
if err != nil {
cfg.Logger("Error reading from stream: %v\n", err)
continue
}
// Log the contents of the report before decoding
cfg.Logger("Raw report data: %+v\n", reportResponse)
// Decode each report as it comes in
decodedReport, decodeErr := report.Decode[v4.Data](reportResponse.FullReport)
if decodeErr != nil {
cfg.Logger("Failed to decode report: %v\n", decodeErr)
continue
}
// Log the decoded report
cfg.Logger("\n--- Report Stream ID: %s ---\n" +
"------------------------------------------\n" +
"Observations Timestamp : %d\n" +
"Benchmark Price : %s\n" +
"Valid From Timestamp : %d\n" +
"Expires At : %d\n" +
"Link Fee : %s\n" +
"Native Fee : %s\n" +
"Market Status : %d\n" +
"------------------------------------------\n",
reportResponse.FeedID.String(),
decodedReport.Data.ObservationsTimestamp,
decodedReport.Data.BenchmarkPrice.String(),
decodedReport.Data.ValidFromTimestamp,
decodedReport.Data.ExpiresAt,
decodedReport.Data.LinkFee.String(),
decodedReport.Data.NativeFee.String(),
decodedReport.Data.MarketStatus,
)
// Also, log the stream stats
cfg.Logger("\n--- Stream Stats ---\n" +
stream.Stats().String() + "\n" +
"--------------------------------------------------------------------------------------------------------------------------------------------\n",
)
}
}
```
3. Download the required dependencies and update the `go.mod` and `go.sum` files:

```bash
go mod tidy
```
4. Set up the SDK client configuration within `stream.go` with your API credentials and the WebSocket URL:

```go
cfg := streams.Config{
ApiKey: os.Getenv("API_KEY"),
ApiSecret: os.Getenv("API_SECRET"),
WsURL: "wss://ws.testnet-dataengine.chain.link",
Logger: streams.LogPrintf,
}
```
- Set your API credentials as environment variables:

```bash
export API_KEY=""
export API_SECRET=""
```
Replace `` and `` with your API credentials.
- `WsURL` is the [WebSocket URL](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws#domains) for the Data Streams Aggregation Network. Use `wss://ws.testnet-dataengine.chain.link` for the testnet environment.
See the [SDK Reference](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk#config-struct) page for more configuration options.
5. For this example, you'll subscribe to the AUD/USD RWA streams. This stream ID is `0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea`. See the [RWA Streams](https://docs.chain.link/data-streams/rwa-streams) page for a complete list of available Real World Assets.
Execute your application:

```bash
go run stream.go 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea
```
Expect output similar to the following in your terminal:

```bash
2024-10-24T12:52:50-05:00 Raw report data: {"fullReport":"0x0006aee203ef23a892e75b579f8c3f26fd933d9ca45de95c2f8ac470f4ddcd7600000000000000000000000000000000000000000000000000000000015de214000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea00000000000000000000000000000000000000000000000000000000671a897200000000000000000000000000000000000000000000000000000000671a89720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000671bdaf20000000000000000000000000000000000000000000000000936a5885261c000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000029bb0fa88b2783870c74deae7db07a588344b1ef32a58dd00589c5ebc24b1b978075d1fa41ce8670633be03f555d297ff4b005b19c58577bc70e68803160b4120000000000000000000000000000000000000000000000000000000000000000238ea2b71402354ebabb4d9be738a83d13e4f67512d13bf8ee078b6a6f2851cdf1fc20d5eb054527ec82dadcd1206dd1d36009db1e95c9ac88defc1d54cab0826","feedID":"0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea","validFromTimestamp":1729792370,"observationsTimestamp":1729792370}
2024-10-24T12:52:50-05:00
--- Report Stream ID: 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea ---
------------------------------------------
Observations Timestamp : 1729792370
Benchmark Price : 663900000000000000
Valid From Timestamp : 1729792370
Expires At : 1729878770
Link Fee : 0
Native Fee : 0
Market Status : 2
------------------------------------------
2024-10-24T12:52:50-05:00
--- Stream Stats ---
accepted: 1, deduplicated: 0, total_received 1, partial_reconnects: 0, full_reconnects: 0, configured_connections: 1, active_connections 1
--------------------------------------------------------------------------------------------------------------------------------------------
2024-10-24T12:52:51-05:00 Raw report data: {"fullReport":"0x0006aee203ef23a892e75b579f8c3f26fd933d9ca45de95c2f8ac470f4ddcd7600000000000000000000000000000000000000000000000000000000015de218000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea00000000000000000000000000000000000000000000000000000000671a897300000000000000000000000000000000000000000000000000000000671a89730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000671bdaf30000000000000000000000000000000000000000000000000936aa14799b100000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d8e3d2f04c9de178bc958eecdd747c975248fa2fd8745485ff05105d0f99abdc11caf5d40d80e6d832dce82748fb688ecc967654a09b5ba45bc6b62d7023aa9600000000000000000000000000000000000000000000000000000000000000021837177262094c1183fff139f494c2923f308851f722d80d7793a4d0ea855bec26f35f8112eae664484d16cccfacf15c8710bc44397f0bd1ca0869241a6156f9","feedID":"0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea","validFromTimestamp":1729792371,"observationsTimestamp":1729792371}
2024-10-24T12:52:51-05:00
--- Report Stream ID: 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea ---
------------------------------------------
Observations Timestamp : 1729792371
Benchmark Price : 663905000000000000
Valid From Timestamp : 1729792371
Expires At : 1729878771
Link Fee : 0
Native Fee : 0
Market Status : 2
------------------------------------------
2024-10-24T12:52:51-05:00
--- Stream Stats ---
accepted: 2, deduplicated: 0, total_received 2, partial_reconnects: 0, full_reconnects: 0, configured_connections: 1, active_connections 1
--------------------------------------------------------------------------------------------------------------------------------------------
2024-10-24T12:52:52-05:00 Raw report data: {"fullReport":"0x0006aee203ef23a892e75b579f8c3f26fd933d9ca45de95c2f8ac470f4ddcd7600000000000000000000000000000000000000000000000000000000015de303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea00000000000000000000000000000000000000000000000000000000671a897400000000000000000000000000000000000000000000000000000000671a89740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000671bdaf40000000000000000000000000000000000000000000000000936a5885261c0000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000286acd46943638d6999878133ce893f42720070ec0937b28cbd69c07b243f3f4130627d493403bbf6a3c914cd0bdf54d254490a084e23201d3bcd19797e94162e00000000000000000000000000000000000000000000000000000000000000022cac7476948bbda325c2e73ac86a7b66fd35daada10d7aa9d71f9d737376573407171b150dcc244d88ecc3f94e99668debdc046c564b2343f8e8590a9d8a92cc","feedID":"0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea","validFromTimestamp":1729792372,"observationsTimestamp":1729792372}
2024-10-24T12:52:52-05:00
--- Report Stream ID: 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea ---
------------------------------------------
Observations Timestamp : 1729792372
Benchmark Price : 663900000000000000
Valid From Timestamp : 1729792372
Expires At : 1729878772
Link Fee : 0
Native Fee : 0
Market Status : 2
------------------------------------------
2024-10-24T12:52:52-05:00
--- Stream Stats ---
accepted: 3, deduplicated: 0, total_received 3, partial_reconnects: 0, full_reconnects: 0, configured_connections: 1, active_connections 1
--------------------------------------------------------------------------------------------------------------------------------------------
[...]
```
#### [Decoded report details](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go\#decoded-report-details)
The decoded report details include:
| Attribute | Value | Description |
| --- | --- | --- |
| `Stream ID` | `0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea` | The unique identifier for the stream. In this example, the stream is for AUD/USD. |
| `Observations Timestamp` | `1729792372` | The timestamp indicating when the data was captured. |
| `Benchmark Price` | `663900000000000000` | The observed price in the report, with 18 decimals. For readability: `0.6639` USD per EUR. |
| `Valid From Timestamp` | `1729792372` | The start validity timestamp for the report, indicating when the data becomes relevant. |
| `Expires At` | `1729878772` | The expiration timestamp of the report, indicating the point at which the data becomes outdated. |
| `Link Fee` | `0` | The fee to pay in LINK tokens for the onchain verification of the report data. With 18 decimals. **Note:** This example fee is not indicative of actual fees. |
| `Native Fee` | `0` | The fee to pay in the native blockchain token (e.g., ETH on Ethereum) for the onchain verification of the report data. With 18 decimals. **Note:** This example fee is not indicative of actual fees. |
| `Market Status` | `2` | The DON's consensus on whether the market is currently open. Possible values: `0` ( `Unknown`), `1` ( `Closed`), `2` ( `Open`). |
#### [Payload for onchain verification](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go\#payload-for-onchain-verification)
In this guide, you log and decode the `fullReport` payload to extract the report data. In a
production environment, you should verify the data to ensure its integrity and authenticity. Refer to the
[Verify report data onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-onchain-verification) guide.
## [Explanation](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go\#explanation)
### [Establishing a WebSocket connection and listening for reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go\#establishing-a-websocket-connection-and-listening-for-reports)
Your application uses the [Stream](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/client.go#L98) function in the [Data Streams SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk)'s client package to establish a real-time WebSocket connection with the Data Streams Aggregation Network.
Once the WebSocket connection is established, your application subscribes to one or more streams by passing an array of `feed.IDs` to the `Stream` function. This subscription lets the client receive real-time updates whenever new report data is available for the specified streams.
### [Decoding a report](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go\#decoding-a-report)
As data reports arrive via the established WebSocket connection, they are processed in real-time:
- Reading streams: The [`Read`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/stream.go#L266) method on the returned Stream object is continuously called within a loop. This method blocks until new data is available, ensuring that all incoming reports are captured as soon as they are broadcasted.
- Decoding reports: For each received report, the SDK's [`Decode`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/report/report.go#L30) function parses and transforms the raw data into a structured format ( `v4.Data` for [RWA streams](https://docs.chain.link/data-streams/rwa-streams)). This decoded data includes data such as the observation timestamp, benchmark price, and market status from the report data.
### [Handling the decoded data](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go\#handling-the-decoded-data)
In this example, the application logs the structured report data to the terminal. However, this data can be used for further processing, analysis, or display in your own application.
## What's next
- [\> Learn how to verify your data onchain](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification)
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
## Get the latest Chainlink content straight to your inbox.
Email Address
## Fetch V4 Reports with Go
[iframe](https://www.googletagmanager.com/ns.html?id=GTM-N6DQ47T)
Finance is on at SmartCon in NYC. [Get notified when tickets go live.](https://smartcon.chain.link/?utm_source=docs)
On this page
# [Fetch and decode V4 reports using the Go SDK](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#overview)
## Guide Versions
This guide is available in multiple versions. Choose the one that matches your needs.
Go SDK - V4 reports for RWA streams
[Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-go) [Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go) [Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust) [Rust SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-rust)
In this guide, you'll learn how to use Chainlink Data Streams with the _[Streams Direct](https://docs.chain.link/data-streams/streams-direct) implementation_ and the [Data Streams SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk) for Go to fetch and decode [V4 reports](https://docs.chain.link/data-streams/reference/report-schema-v4) for [Real World Assets (RWAs) streams](https://docs.chain.link/data-streams/rwa-streams) from the Data Streams Aggregation Network. You'll set up your Go project, retrieve reports, decode them, and log their attributes.
## [Requirements](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#requirements)
- **Git**: Make sure you have Git installed. You can check your current version by running `git --version` in your terminal and download the latest version from the official [Git website](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) if necessary.
- **Go Version**: Make sure you have Go version 1.21 or higher. You can check your current version by running `go version` in your terminal and download the latest version from the official [Go website](https://go.dev/) if necessary.
- **API Credentials**: Access to the Streams Direct implementation requires API credentials. If you haven't already, [contact us](https://chainlinkcommunity.typeform.com/datastreams?typeform-source=docs.chain.link#ref_id=docs) to request mainnet or testnet access.
## [Guide](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#guide)
You'll start with the set up of your Go project. Next, you'll fetch and decode reports for both single and multiple [RWA streams](https://docs.chain.link/data-streams/rwa-streams), and log their attributes to your terminal.
### [Set up your Go project](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#set-up-your-go-project)
1. Create a new directory for your project and navigate to it:

```bash
mkdir my-data-streams-project
cd my-data-streams-project
```
2. Initialize a new Go module:

```bash
go mod init my-data-streams-project
```
3. Install the Data Streams SDK:

```bash
go get github.com/smartcontractkit/data-streams-sdk/go
```
### [Fetch and decode a report with a single stream](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#fetch-and-decode-a-report-with-a-single-stream)
1. Create a new Go file, `single-stream.go`, in your project directory:

```bash
touch single-stream.go
```
2. Insert the following code example and save your `single-stream.go` file:

```go
package main
import (
"context"
"fmt"
"os"
"time"
streams "github.com/smartcontractkit/data-streams-sdk/go"
feed "github.com/smartcontractkit/data-streams-sdk/go/feed"
report "github.com/smartcontractkit/data-streams-sdk/go/report"
v4 "github.com/smartcontractkit/data-streams-sdk/go/report/v4" // Import the v4 report schema for RWA streams. For Crypto streams, use the v3 schema.
)
func main() {
// Validate command-line arguments
if len(os.Args) < 2 {
fmt.Printf("Usage: go run main.go [FeedID]\nExample: go run main.go 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea\n")
os.Exit(1)
}
feedIDInput := os.Args[1]
// Get API credentials from environment variables
apiKey := os.Getenv("API_KEY")
apiSecret := os.Getenv("API_SECRET")
if apiKey == "" || apiSecret == "" {
fmt.Printf("API_KEY and API_SECRET environment variables must be set\n")
os.Exit(1)
}
// Define the configuration for the SDK client
cfg := streams.Config{
ApiKey: apiKey,
ApiSecret: apiSecret,
RestURL: "https://api.testnet-dataengine.chain.link",
Logger: streams.LogPrintf,
}
// Initialize the SDK client
client, err := streams.New(cfg)
if err != nil {
cfg.Logger("Failed to create client: %v\n", err)
os.Exit(1)
}
// Create context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Parse the feed ID
var feedID feed.ID
if err := feedID.FromString(feedIDInput); err != nil {
cfg.Logger("Invalid feed ID format '%s': %v\n", feedIDInput, err)
os.Exit(1)
}
// Fetch the latest report
reportResponse, err := client.GetLatestReport(ctx, feedID)
if err != nil {
cfg.Logger("Failed to get latest report: %v\n", err)
os.Exit(1)
}
// Log the raw report data
cfg.Logger("Raw report data: %+v\n", reportResponse)
// Decode the report
decodedReport, err := report.Decode[v4.Data](reportResponse.FullReport)
if err != nil {
cfg.Logger("Failed to decode report: %v\n", err)
os.Exit(1)
}
// Format and display the decoded report
fmt.Printf("\nDecoded Report for Stream ID %s:\n"+
"------------------------------------------\n"+
"Observations Timestamp: %d\n"+
"Benchmark Price : %s\n"+
"Valid From Timestamp : %d\n"+
"Expires At : %d\n"+
"Link Fee : %s\n"+
"Native Fee : %s\n"+
"Market Status : %d\n"+
"------------------------------------------\n",
feedIDInput,
decodedReport.Data.ObservationsTimestamp,
decodedReport.Data.BenchmarkPrice.String(),
decodedReport.Data.ValidFromTimestamp,
decodedReport.Data.ExpiresAt,
decodedReport.Data.LinkFee.String(),
decodedReport.Data.NativeFee.String(),
decodedReport.Data.MarketStatus,
)
}
```
3. Download the required dependencies and update the `go.mod` and `go.sum` files:

```bash
go mod tidy
```
4. Set up the SDK client configuration within `single-stream.go` with your API credentials and the REST endpoint:

```go
cfg := streams.Config{
ApiKey: os.Getenv("API_KEY"),
ApiSecret: os.Getenv("API_SECRET"),
RestURL: "https://api.testnet-dataengine.chain.link",
Logger: streams.LogPrintf,
}
```
- Set your API credentials as environment variables:

```bash
export API_KEY=""
export API_SECRET=""
```
Replace `` and `` with your API credentials.
- `RestURL` is the REST endpoint to poll for specific reports. See the [Streams Direct Interface](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api#domains) page for more information.
See the [SDK Reference](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk#config-struct) page for more configuration options.
5. For this example, you will read from the AUD/USD stream. This stream ID is `0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea`. See the [Data Streams RWA streams](https://docs.chain.link/data-streams/rwa-streams) page for a complete list of available Real World Assets.
Execute your application:

```bash
go run single-stream.go 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea
```
Expect output similar to the following in your terminal:

```bash
2024-12-14T17:50:49-05:00 Raw report data: {"fullReport":"0x0006aee203ef23a892e75b579f8c3f26fd933d9ca45de95c2f8ac470f4ddcd76000000000000000000000000000000000000000000000000000000000b75880c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea00000000000000000000000000000000000000000000000000000000675e0bc900000000000000000000000000000000000000000000000000000000675e0bc90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000675f5d4900000000000000000000000000000000000000000000000008d460e8b7e50000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000023f21e9d219ae8e279d13a36b09a439ed71c0d1118561a93987c665fbad13cb6e37bd3763d7ef840b05fda0671b01f26f3c073bef1f3b53fcd9429836ba25eae600000000000000000000000000000000000000000000000000000000000000026bd87b2293422e41ec242088d8feedbe126474b791a85e54450af84e21d017fd59158fbe4adf47dcabe54c11a8ca606659e060839474545eb9b13bf5e7c902df","feedID":"0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea","validFromTimestamp":1734216649,"observationsTimestamp":1734216649}
2024-12-14T17:50:49-05:00
Decoded Report for Stream ID 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea:
------------------------------------------
Observations Timestamp: 1734216649
Benchmark Price : 636240000000000000
Valid From Timestamp : 1734216649
Expires At : 1734303049
Link Fee : 0
Native Fee : 0
Market Status : 1
------------------------------------------
```
#### [Decoded report details](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#decoded-report-details)
The decoded report details include:
| Attribute | Value | Description |
| --- | --- | --- |
| `Stream ID` | `0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea` | The unique identifier for the stream. In this example, the stream is for AUD/USD. |
| `Observations Timestamp` | `1734216649` | The timestamp indicating when the data was captured. |
| `Benchmark Price` | `636240000000000000` | The observed price in the report, with 18 decimals. For readability: `0.63624` USD per AUD. |
| `Valid From Timestamp` | `1734216649` | The start validity timestamp for the report, indicating when the data becomes relevant. |
| `Expires At` | `1734303049` | The expiration timestamp of the report, indicating the point at which the data becomes outdated. |
| `Link Fee` | `0` | The fee to pay in LINK tokens for the onchain verification of the report data. With 18 decimals. **Note:** This example fee is not indicative of actual fees. |
| `Native Fee` | `0` | The fee to pay in the native blockchain token (e.g., ETH on Ethereum) for the onchain verification of the report data. With 18 decimals. **Note:** This example fee is not indicative of actual fees. |
| `Market Status` | `1` | The DON's consensus on whether the market is currently open. Possible values: `0` ( `Unknown`), `1` ( `Closed`), `2` ( `Open`). |
#### [Payload for onchain verification](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#payload-for-onchain-verification)
In this guide, you log and decode the `fullReport` payload to extract the report data. In a
production environment, you should verify the data to ensure its integrity and authenticity. Refer to the
[Verify report data onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-onchain-verification) guide.
### [Fetch and decode reports for multiple streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#fetch-and-decode-reports-for-multiple-streams)
1. Create a new Go file, `multiple-streams.go`, in your project directory:

```bash
touch multiple-streams.go
```
2. Insert the following code example in your `multiple-streams.go` file:

```go
package main
import (
"context"
"fmt"
"os"
"time"
streams "github.com/smartcontractkit/data-streams-sdk/go"
feed "github.com/smartcontractkit/data-streams-sdk/go/feed"
report "github.com/smartcontractkit/data-streams-sdk/go/report"
v4 "github.com/smartcontractkit/data-streams-sdk/go/report/v4" // Import the v4 report schema for RWA streams
)
func main() {
// Validate command-line arguments
if len(os.Args) < 3 {
fmt.Printf("Usage: go run multiple-streams.go [StreamID1] [StreamID2] ...\n"+
"Example: go run multiple-streams.go "+
"0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea "+
"0x0004b9905d8337c34e00f8dbe31619428bac5c3937e73e6af75c71780f1770ce\n")
os.Exit(1)
}
// Get API credentials from environment variables
apiKey := os.Getenv("API_KEY")
apiSecret := os.Getenv("API_SECRET")
if apiKey == "" || apiSecret == "" {
fmt.Printf("API_KEY and API_SECRET environment variables must be set\n")
os.Exit(1)
}
// Define the configuration for the SDK client
cfg := streams.Config{
ApiKey: apiKey,
ApiSecret: apiSecret,
RestURL: "https://api.testnet-dataengine.chain.link",
Logger: streams.LogPrintf,
}
// Initialize the SDK client
client, err := streams.New(cfg)
if err != nil {
cfg.Logger("Failed to create client: %v\n", err)
os.Exit(1)
}
// Create context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Parse Feed IDs
var ids []feed.ID
for _, arg := range os.Args[1:] {
var fid feed.ID
if err := fid.FromString(arg); err != nil {
cfg.Logger("Invalid feed ID format '%s': %v\n", arg, err)
continue
}
ids = append(ids, fid)
}
if len(ids) == 0 {
cfg.Logger("No valid feed IDs provided\n")
os.Exit(1)
}
// Fetch reports for all streams
timestamp := uint64(time.Now().Unix())
reportResponses, err := client.GetReports(ctx, ids, timestamp)
if err != nil {
cfg.Logger("Failed to get reports: %v\n", err)
os.Exit(1)
}
// Process reports
for _, reportResponse := range reportResponses {
// Log the raw report data
cfg.Logger("Raw report data for Stream ID %s: %+v\n",
reportResponse.FeedID.String(), reportResponse)
// Decode the report
decodedReport, err := report.Decode[v4.Data](reportResponse.FullReport)
if err != nil {
cfg.Logger("Failed to decode report for Stream ID %s: %v\n",
reportResponse.FeedID.String(), err)
continue // Skip to next report if decoding fails
}
// Format and display the decoded report
fmt.Printf("\nDecoded Report for Stream ID %s:\n"+
"------------------------------------------\n"+
"Observations Timestamp: %d\n"+
"Benchmark Price : %s\n"+
"Valid From Timestamp : %d\n"+
"Expires At : %d\n"+
"Link Fee : %s\n"+
"Native Fee : %s\n"+
"Market Status : %d\n"+
"------------------------------------------\n",
reportResponse.FeedID.String(),
decodedReport.Data.ObservationsTimestamp,
decodedReport.Data.BenchmarkPrice.String(),
decodedReport.Data.ValidFromTimestamp,
decodedReport.Data.ExpiresAt,
decodedReport.Data.LinkFee.String(),
decodedReport.Data.NativeFee.String(),
decodedReport.Data.MarketStatus,
)
}
}
```
3. Before running the example, verify that your API credentials are still set in your current terminal session:

```bash
echo $API_KEY
echo $API_SECRET
```
If the commands above don't show your credentials, set them again:

```bash
export API_KEY=""
export API_SECRET=""
```
4. For this example, you will read from the AUD/USD and EUR/USD RWA streams. Run your application:

```bash
go run multiple-streams.go 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea 0x0004b9905d8337c34e00f8dbe31619428bac5c3937e73e6af75c71780f1770ce
```
Expect to see output similar to the following in your terminal:

```bash
2024-12-14T17:53:30-05:00 Raw report data for Stream ID 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea: {"fullReport":"0x0006aee203ef23a892e75b579f8c3f26fd933d9ca45de95c2f8ac470f4ddcd76000000000000000000000000000000000000000000000000000000000b75a101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea00000000000000000000000000000000000000000000000000000000675e0c6900000000000000000000000000000000000000000000000000000000675e0c690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000675f5de900000000000000000000000000000000000000000000000008d460e8b7e500000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000255d50eabaa1620b13c01d671b4b8478cbbf3c00a66c96652de0a4abd033447d4077c56723b911f683224b08615cb37103422a0c72f10930f2b2cf5d69ffa7a4100000000000000000000000000000000000000000000000000000000000000022139022d94d5ba9a5d7257866ab5ac2a892de57532a6d15f4d3bb4e0616fc89f26fcf652f60f3227466f986db7a494fdb2e71e7921eaedbfa7e6248220770373","feedID":"0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea","validFromTimestamp":1734216809,"observationsTimestamp":1734216809}
Decoded Report for Stream ID 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea:
------------------------------------------
Observations Timestamp: 1734216809
Benchmark Price : 636240000000000000
Valid From Timestamp : 1734216809
Expires At : 1734303209
Link Fee : 0
Native Fee : 0
Market Status : 1
------------------------------------------
2024-12-14T17:53:30-05:00 Raw report data for Stream ID 0x0004b9905d8337c34e00f8dbe31619428bac5c3937e73e6af75c71780f1770ce: {"fullReport":"0x00062f2fdc48a5bb737dad7fac44e3d35f5d0a0c43091fea90011dbcd3ca39ff000000000000000000000000000000000000000000000000000000000d25a501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000260000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000004b9905d8337c34e00f8dbe31619428bac5c3937e73e6af75c71780f1770ce00000000000000000000000000000000000000000000000000000000675e0c6900000000000000000000000000000000000000000000000000000000675e0c690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000675f5de90000000000000000000000000000000000000000000000000e933ccf7f5aa00000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002266357ecc8bccb8199db1d62be6b26ff251e51d821abac59095ffa3bd53f2b671ba72e1f0157b7269578f24574d75f21f4e16340e924a39966385a9204c7f5c5000000000000000000000000000000000000000000000000000000000000000258e69e20a244ec3dc6bcb309d08479656b37160e2210dd7278b6be12296456184d3871968c7511af5beec82528e6f8a9caedffd12f93ca65425850a400343299","feedID":"0x0004b9905d8337c34e00f8dbe31619428bac5c3937e73e6af75c71780f1770ce","validFromTimestamp":1734216809,"observationsTimestamp":1734216809}
Decoded Report for Stream ID 0x0004b9905d8337c34e00f8dbe31619428bac5c3937e73e6af75c71780f1770ce:
------------------------------------------
Observations Timestamp: 1734216809
Benchmark Price : 1050250000000000000
Valid From Timestamp : 1734216809
Expires At : 1734303209
Link Fee : 0
Native Fee : 0
Market Status : 1
------------------------------------------
```
Your application has successfully fetched and decoded data for both streams.
#### [Payload for onchain verification](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#payload-for-onchain-verification-1)
In this guide, you log and decode the `fullReport` payloads to extract the report data. In a
production environment, you should verify the data to ensure its integrity and authenticity. Refer to the
[Verify report data onchain](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-onchain-verification) guide.
## [Explanation](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#explanation)
### [Initializing the client and configuration](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#initializing-the-client-and-configuration)
The Data Streams client is initialized in two steps:
1. Configure the client with [`streams.Config`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/config.go#L10):

```go
cfg := streams.Config{
ApiKey: os.Getenv("API_KEY"),
ApiSecret: os.Getenv("API_SECRET"),
RestURL: "https://api.testnet-dataengine.chain.link",
Logger: streams.LogPrintf,
}
```
The configuration requires:
- `ApiKey` and `ApiSecret` for authentication (required)
- `RestURL` for the API endpoint (required)
- `Logger` for debugging and error tracking (optional, defaults to `streams.LogPrintf`)
2. Create the client with [`streams.New`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/client.go#L56):

```go
client, err := streams.New(cfg)
```
The client handles:
- Authentication with HMAC signatures
- Connection management and timeouts
- Error handling and retries
### [Fetching reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#fetching-reports)
The SDK provides two main methods to fetch reports:
1. Latest report for a single stream with [`GetLatestReport`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/client.go#L130):

```go
reportResponse, err := client.GetLatestReport(ctx, feedID)
```
- Takes a context and feed ID
- Returns a single `ReportResponse` with the most recent data
- No timestamp parameter needed
- Useful for real-time price monitoring
2. Latest reports for multiple streams with [`GetReports`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/client.go#L208):

```go
reportResponses, err := client.GetReports(ctx, ids, timestamp)
```
- Takes context, feed IDs array, and Unix timestamp
- Returns array of `ReportResponse`, one per feed ID
- Timestamp determines the point in time for the reports
- Efficient for monitoring multiple assets simultaneously
Each API request automatically:
- Handles authentication with API credentials
- Manages request timeouts via context
- Processes responses into structured types
### [Decoding reports](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#decoding-reports)
Reports are decoded in two steps:
1. Report decoding with [`report.Decode`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/report/report.go#L30):

```go
decodedReport, err := report.Decode[v4.Data](reportResponse.FullReport)
```
This step:
- Takes the raw `FullReport` bytes from the response
- Uses `v4.Data` schema for RWA streams (use `v3.Data` for Crypto streams)
- Validates the format and decodes using Go generics
- Returns a structured report with typed data
2. Data access:

```go
data := decodedReport.Data
price := data.BenchmarkPrice.String() // Convert big number to string
validFrom := data.ValidFromTimestamp // Unix timestamp
expiresAt := data.ExpiresAt // Unix timestamp
marketStatus := data.MarketStatus // Market status (0: Unknown, 1: Closed, 2: Open)
```
Provides access to:
- Benchmark price (as big number)
- Fee information (LINK and native token fees)
- Timestamp data (validity period)
- Market status information
- All numeric values require `.String()` for display
### [Error handling](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go\#error-handling)
The SDK uses Go's standard error handling patterns with some enhancements:
1. Context management:

```go
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
```
- Sets request timeouts for API calls
- `defer cancel()` ensures cleanup of resources
- Same context pattern for both single and multiple reports
2. Error checking:

```go
if err != nil {
cfg.Logger("Failed to decode report: %v\n", err)
os.Exit(1) // Fatal errors: exit the program
// or
continue // Non-fatal errors: skip this report
}
```
- Fatal errors (client creation, no valid feeds) use `os.Exit(1)`
- Non-fatal errors (single report decode) use `continue`
- All errors are logged before handling
3. SDK logging:

```go
cfg.Logger("Raw report data: %+v\n", reportResponse)
```
- Uses configured logger for SDK operations
- `fmt.Printf` for user-facing output
- Debug information includes raw report data
- Structured error messages with context
The decoded data can be used for further processing or display in your application. For production environments, you must verify the data onchain using the provided `fullReport` payload.
## What's next
- [\> Learn how to stream and decode reports via a WebSocket connection](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws)
- [\> Learn how to verify your data onchain](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-onchain-verification)
- [\> Find the list of available Stream IDs](https://docs.chain.link/data-streams/crypto-streams)
## Get the latest Chainlink content straight to your inbox.
Email Address