# 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. ![Chainlink Data Streams - Push-Based vs Pull-Based Oracles](https://docs.chain.link/images/data-streams/push-based-vs-pull-based-oracles.webp) 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. ![Chainlink Data Streams - Streams Trade Architecture](https://docs.chain.link/images/data-streams/data-streams-trade-architecture-v3.webp) ### [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: ![Chainlink Data Streams - Streams Trade Example Trading Flow](https://docs.chain.link/images/data-streams/streams-trade-sequence-diagram.webp) 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. ![Chainlink Data Streams - Streams Direct Off-Chain Price Updates](https://docs.chain.link/images/data-streams/streams-direct-offchain-price-updates.webp) ## [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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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 logo](https://docs.chain.link/assets/chains/apechain.svg)Apechain + ![Arbitrum logo](https://docs.chain.link/assets/chains/arbitrum.svg)Arbitrum + ![Avalanche logo](https://docs.chain.link/assets/chains/avalanche.svg)Avalanche + ![Base logo](https://docs.chain.link/assets/chains/base.svg)Base + ![Berachain logo](https://docs.chain.link/assets/chains/berachain.svg)Berachain + ![Blast logo](https://docs.chain.link/assets/chains/blast.svg)Blast + ![BNB Chain logo](https://docs.chain.link/assets/chains/bnb-chain.svg)BNB Chain + ![Bob logo](https://docs.chain.link/assets/chains/bob.svg)Bob + ![Botanix logo](https://docs.chain.link/assets/chains/botanix.svg)Botanix + ![Ethereum logo](https://docs.chain.link/assets/chains/ethereum.svg)Ethereum + ![Gnosis logo](https://docs.chain.link/assets/chains/gnosis-chain.svg)Gnosis + ![HashKey Chain logo](https://docs.chain.link/assets/chains/hashkey.svg)HashKey Chain + ![Hyperliquid logo](https://docs.chain.link/assets/chains/hyperliquid.svg)Hyperliquid + ![Ink logo](https://docs.chain.link/assets/chains/ink.svg)Ink + ![Lens logo](https://docs.chain.link/assets/chains/lens.svg)Lens + ![Linea logo](https://docs.chain.link/assets/chains/linea.svg)Linea + ![Mantle logo](https://docs.chain.link/assets/chains/mantle.svg)Mantle + ![MegaETH logo](https://docs.chain.link/assets/chains/megaeth.svg)MegaETH + ![Monad logo](https://docs.chain.link/assets/chains/monad.svg)Monad + ![opBNB logo](https://docs.chain.link/assets/chains/opbnb.svg)opBNB + ![OP logo](https://docs.chain.link/assets/chains/optimism.svg)OP + ![Ronin logo](https://docs.chain.link/assets/chains/ronin.svg)Ronin + ![Scroll logo](https://docs.chain.link/assets/chains/scroll.svg)Scroll + ![Shibarium logo](https://docs.chain.link/assets/chains/shibarium.svg)Shibarium + ![Soneium logo](https://docs.chain.link/assets/chains/soneium.svg)Soneium + ![Sonic logo](https://docs.chain.link/assets/chains/sonic.svg)Sonic + ![Solana logo](https://docs.chain.link/assets/chains/solana.svg)Solana + ![Taiko logo](https://docs.chain.link/assets/chains/taiko.svg)Taiko + ![Unichain logo](https://docs.chain.link/assets/chains/unichain.svg)Unichain + ![World Chain logo](https://docs.chain.link/assets/chains/worldchain.svg)World Chain + ![ZKSync logo](https://docs.chain.link/assets/chains/zksync.svg)ZKSync + ## [Mainnet Crypto Streams](https://docs.chain.link/data-streams/crypto-streams?page=1\#mainnet-crypto-streams) | Stream | Details | | --- | --- | | 1INCH/USD | 0x0003fb80bf0e043e7bcc6e9808c9f62e722117afddb2b760ad6c58f6cc614444![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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. ![Chainlink Data Streams - Streams Trade Architecture](https://docs.chain.link/images/data-streams/data-streams-trade-architecture-v3.webp) 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 logo](https://docs.chain.link/assets/chains/apechain.svg)Apechain + ![Arbitrum logo](https://docs.chain.link/assets/chains/arbitrum.svg)Arbitrum + ![Avalanche logo](https://docs.chain.link/assets/chains/avalanche.svg)Avalanche + ![Base logo](https://docs.chain.link/assets/chains/base.svg)Base + ![Berachain logo](https://docs.chain.link/assets/chains/berachain.svg)Berachain + ![Blast logo](https://docs.chain.link/assets/chains/blast.svg)Blast + ![BNB Chain logo](https://docs.chain.link/assets/chains/bnb-chain.svg)BNB Chain + ![Bob logo](https://docs.chain.link/assets/chains/bob.svg)Bob + ![Botanix logo](https://docs.chain.link/assets/chains/botanix.svg)Botanix + ![Ethereum logo](https://docs.chain.link/assets/chains/ethereum.svg)Ethereum + ![Gnosis logo](https://docs.chain.link/assets/chains/gnosis-chain.svg)Gnosis + ![HashKey Chain logo](https://docs.chain.link/assets/chains/hashkey.svg)HashKey Chain + ![Hyperliquid logo](https://docs.chain.link/assets/chains/hyperliquid.svg)Hyperliquid + ![Ink logo](https://docs.chain.link/assets/chains/ink.svg)Ink + ![Lens logo](https://docs.chain.link/assets/chains/lens.svg)Lens + ![Linea logo](https://docs.chain.link/assets/chains/linea.svg)Linea + ![Mantle logo](https://docs.chain.link/assets/chains/mantle.svg)Mantle + ![MegaETH logo](https://docs.chain.link/assets/chains/megaeth.svg)MegaETH + ![Monad logo](https://docs.chain.link/assets/chains/monad.svg)Monad + ![opBNB logo](https://docs.chain.link/assets/chains/opbnb.svg)opBNB + ![OP logo](https://docs.chain.link/assets/chains/optimism.svg)OP + ![Ronin logo](https://docs.chain.link/assets/chains/ronin.svg)Ronin + ![Scroll logo](https://docs.chain.link/assets/chains/scroll.svg)Scroll + ![Shibarium logo](https://docs.chain.link/assets/chains/shibarium.svg)Shibarium + ![Soneium logo](https://docs.chain.link/assets/chains/soneium.svg)Soneium + ![Sonic logo](https://docs.chain.link/assets/chains/sonic.svg)Sonic + ![Solana logo](https://docs.chain.link/assets/chains/solana.svg)Solana + ![Taiko logo](https://docs.chain.link/assets/chains/taiko.svg)Taiko + ![Unichain logo](https://docs.chain.link/assets/chains/unichain.svg)Unichain + ![World Chain logo](https://docs.chain.link/assets/chains/worldchain.svg)World Chain + ![ZKSync logo](https://docs.chain.link/assets/chains/zksync.svg)ZKSync + ## [Mainnet RWA Streams](https://docs.chain.link/data-streams/rwa-streams?page=1\#mainnet-rwa-streams) | Stream | Details | | --- | --- | | AUD/USD | 0x000463a76b4a354b411a69c16990d01fd634e201a9f62d90bc67538469036b15![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg)
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. ![](https://docs.chain.link/images/tutorial-icons/remix-icn.png)Remix [![](https://docs.chain.link/images/tutorial-icons/remix-icn.png)Remix](https://docs.chain.link/data-streams/getting-started) [![](https://docs.chain.link/images/tutorial-icons/hardhat-icn.png)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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). 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. ![Chainlink Data Streams Solidity Compiler](https://docs.chain.link/images/data-streams/getting-started/solidity-compiler.webp) 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_. ![Chainlink Data Streams Injected Provider MetaMask](https://docs.chain.link/images/data-streams/getting-started/injected-provider.webp) 6. In the **Contract** section, select the `StreamsUpkeep` contract and fill in the Arbitrum Sepolia **verifier proxy address**: `0x2ff010DEbC1297f19579B4246cad07bd24F2488A`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). You can find the verifier proxy addresses on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page. ![Chainlink Data Streams Remix Deploy Upkeep Contract](https://docs.chain.link/images/data-streams/getting-started/deploy-upkeep.webp) 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. ![Chainlink Data Streams Remix Deployed Upkeep Contract](https://docs.chain.link/images/data-streams/getting-started/deployed-upkeep-1.webp) ### [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. ![Chainlink Data Streams Remix Compile Log Emitter Contract](https://docs.chain.link/images/data-streams/getting-started/compile-logemitter.webp) 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_. ![Chainlink Data Streams Injected Provider MetaMask](https://docs.chain.link/images/data-streams/getting-started/injected-provider.webp) 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_. ![Chainlink Data Streams Deploy Emitter Contract](https://docs.chain.link/images/data-streams/getting-started/deploy-logemitter.webp) 6. After you confirm the transaction, the contract address appears in the **Deployed Contracts** list. Save this contract address for later. ![Chainlink Data Streams Deployed Emitter Contract](https://docs.chain.link/images/data-streams/getting-started/deployed-logemitter.webp) ### [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. ![Chainlink Data Streams Remix Log Emitter ABI](https://docs.chain.link/images/data-streams/getting-started/remix-copy-abi.webp) 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. ![Chainlink Data Streams Fund Deployed Upkeep](https://docs.chain.link/images/data-streams/getting-started/fund-deployed-upkeep.webp) ### [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. ![Chainlink Data Streams Emit Log](https://docs.chain.link/images/data-streams/getting-started/emitter-emitlog.webp) 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. ![](https://docs.chain.link/images/data-streams/getting-started/request-fulfilled.webp) ### [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. ![Chainlink Data Streams Deployed Upkeep](https://docs.chain.link/images/data-streams/getting-started/deployed-upkeep-2.webp) ## [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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![Chainlink Data Streams - Streams Direct On-Demand Offchain Workflows](https://docs.chain.link/images/data-streams/data-streams-on-demand-offchain-workflows.webp) ## [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. ![](https://docs.chain.link/images/tutorial-icons/hardhat-icn.png)Hardhat [![](https://docs.chain.link/images/tutorial-icons/remix-icn.png)Remix](https://docs.chain.link/data-streams/getting-started) [![](https://docs.chain.link/images/tutorial-icons/hardhat-icn.png)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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). To ensure you are running the correct version in a terminal, type `node -v`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash git clone https://github.com/smartcontractkit/smart-contract-examples.git cd smart-contract-examples/data-streams/getting-started/hardhat ``` 2. Install the dependencies: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash npx env-enc set-pw ``` 4. Set the required environment variables using the following command: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash npx hardhat deployAll --network arbitrumSepolia ``` Expect output similar to the following in your terminal: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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 logo](https://docs.chain.link/assets/chains/apechain.svg)Apechain + ![Arbitrum logo](https://docs.chain.link/assets/chains/arbitrum.svg)Arbitrum + ![Avalanche logo](https://docs.chain.link/assets/chains/avalanche.svg)Avalanche + ![Base logo](https://docs.chain.link/assets/chains/base.svg)Base + ![Berachain logo](https://docs.chain.link/assets/chains/berachain.svg)Berachain + ![Blast logo](https://docs.chain.link/assets/chains/blast.svg)Blast + ![BNB Chain logo](https://docs.chain.link/assets/chains/bnb-chain.svg)BNB Chain + ![Bob logo](https://docs.chain.link/assets/chains/bob.svg)Bob + ![Botanix logo](https://docs.chain.link/assets/chains/botanix.svg)Botanix + ![Ethereum logo](https://docs.chain.link/assets/chains/ethereum.svg)Ethereum + ![Gnosis logo](https://docs.chain.link/assets/chains/gnosis-chain.svg)Gnosis + ![HashKey Chain logo](https://docs.chain.link/assets/chains/hashkey.svg)HashKey Chain + ![Hyperliquid logo](https://docs.chain.link/assets/chains/hyperliquid.svg)Hyperliquid + ![Ink logo](https://docs.chain.link/assets/chains/ink.svg)Ink + ![Lens logo](https://docs.chain.link/assets/chains/lens.svg)Lens + ![Linea logo](https://docs.chain.link/assets/chains/linea.svg)Linea + ![Mantle logo](https://docs.chain.link/assets/chains/mantle.svg)Mantle + ![MegaETH logo](https://docs.chain.link/assets/chains/megaeth.svg)MegaETH + ![Monad logo](https://docs.chain.link/assets/chains/monad.svg)Monad + ![opBNB logo](https://docs.chain.link/assets/chains/opbnb.svg)opBNB + ![OP logo](https://docs.chain.link/assets/chains/optimism.svg)OP + ![Ronin logo](https://docs.chain.link/assets/chains/ronin.svg)Ronin + ![Scroll logo](https://docs.chain.link/assets/chains/scroll.svg)Scroll + ![Shibarium logo](https://docs.chain.link/assets/chains/shibarium.svg)Shibarium + ![Soneium logo](https://docs.chain.link/assets/chains/soneium.svg)Soneium + ![Sonic logo](https://docs.chain.link/assets/chains/sonic.svg)Sonic + ![Solana logo](https://docs.chain.link/assets/chains/solana.svg)Solana + ![Taiko logo](https://docs.chain.link/assets/chains/taiko.svg)Taiko + ![Unichain logo](https://docs.chain.link/assets/chains/unichain.svg)Unichain + ![World Chain logo](https://docs.chain.link/assets/chains/worldchain.svg)World Chain + ![ZKSync logo](https://docs.chain.link/assets/chains/zksync.svg)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. ![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)Rust SDK [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)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`: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```http GET /api/v1/ws?feedIDs=,,... ``` ##### [Sample response](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-ws\#sample-response) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)Rust SDK - V3 reports for Crypto streams [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-go) [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash mkdir my-data-streams-project && cd my-data-streams-project ``` 2. Initialize a new Rust project: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash cargo init ``` 3. Add the Data Streams SDK to your `Cargo.toml`: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash cargo run -- 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 ``` Expect output similar to the following in your terminal: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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": ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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). ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V3 reports for Crypto streams [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go) [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rust) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash mkdir my-data-streams-project cd my-data-streams-project ``` 2. Initialize a new Go module: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash go mod init my-data-streams-project ``` 3. Install the Data Streams SDK: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash touch stream.go ``` 2. Insert the following code example and save your `stream.go` file: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash go mod tidy ``` 4. Set up the SDK client configuration within `stream.go` with your API credentials and the WebSocket URL: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). See the [Crypto Streams](https://docs.chain.link/data-streams/crypto-streams) page for a complete list of available crypto assets. Execute your application: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash go run stream.go 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 ``` Expect output similar to the following in your terminal: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-go-sdk) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go GetFeeds(ctx context.Context) (r []*Feed, err error) ``` - `GetLatestReport`: Fetches the latest report available for the specified `FeedID`. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go GetLatestReport(ctx context.Context, id FeedID) (r *Report, err error) ``` - `GetReports`: Fetches reports for the specified stream IDs and a given timestamp. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go GetReports(ctx context.Context, ids []FeedID, timestamp uint64) ([]*Report, error) ``` - `GetReportPage`: Paginates the reports for a specified `FeedID` starting from a given timestamp. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go GetReportPage(ctx context.Context, id FeedID, startTS uint64) (*ReportPage, error) ``` - `Stream`: Creates a real-time report stream for specified stream IDs. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go type CtxKey string ``` - Constants: - `CustomHeadersCtxKey`: Key for passing custom HTTP headers. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go func (r *ReportResponse) MarshalJSON() ([]byte, error) ``` - `String`: Returns the string representation of the `ReportResponse`. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go func (r *ReportResponse) String() (s string) ``` - `UnmarshalJSON`: Deserializes the `ReportResponse` from JSON. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go Read(context.Context) (*Report, error) ``` - `Stats`: Returns statistics about the stream operations as `Stats`. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go Stats() Stats ``` - `Close`: Closes the stream. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go func (f *ID) FromString(s string) (err error) ``` - `MarshalJSON`: Serializes the `ID` into JSON. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go func (f *ID) MarshalJSON() (b []byte, err error) ``` - `String`: Returns the string representation of the `ID`. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go func (f *ID) String() (id string) ``` - `UnmarshalJSON`: Deserializes the `ID` from JSON. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go func (f *ID) UnmarshalJSON(b []byte) (err error) ``` - `Version`: Returns the version of the stream. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```go func Decode[T Data](fullReport []byte) (r *Report[T], err error) ``` Example: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![](https://docs.chain.link/images/tutorial-icons/solanaLogoMark.svg)Solana (Rust) - Offchain integration [![](https://docs.chain.link/images/tutorial-icons/solidity_logo.svg)EVM Chains (Solidity)](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification) [![](https://docs.chain.link/images/tutorial-icons/solanaLogoMark.svg)Solana (Rust) - Onchain integration](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification) [![](https://docs.chain.link/images/tutorial-icons/solanaLogoMark.svg)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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) to verify your installation. - **Anchor Framework**: Follow the [official installation guide](https://www.anchor-lang.com/docs/installation). Run `anchor --version`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). - **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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash anchor init example_verify cd example_verify ``` 2. Create a binary target for the verification tool: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`): ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash cargo build ``` 2. Make sure you are connected to Devnet with `solana config set --url https://api.devnet.solana.com`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). 3. Run the verifier with your report: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash cargo run -- Gt9S41PtjR58CbG9JhJ3J6vxesqrNAswbWYbLNTMZA3c 2k3DsgwBoqrnvXKVvd7jX7aptNxdcRBdcd5HkYsGgbrb 0006f9b553e393ced311551efd30d1decedb63d76ad41737462e2cdbbdff1578000000000000000000000000000000000000000000000000000000004f56930f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba78200000000000000000000000000000000000000000000000000000000675ca37000000000000000000000000000000000000000000000000000000000675ca3700000000000000000000000000000000000000000000000000000174be1bd8758000000000000000000000000000000000000000000000000000cb326ce8c3ea800000000000000000000000000000000000000000000000000000000675df4f00000000000000000000000000000000000000000000000d3a30bcc15e207c0000000000000000000000000000000000000000000000000d3a1557b5e634060200000000000000000000000000000000000000000000000d3ab99a974ff10f400000000000000000000000000000000000000000000000000000000000000000292bdd75612560e46ed9b0c2437898f81eb0e18b6b902a161b9708e9177175cf3b8ef2b279f230f766fb29306250ee90856516ee349ca42b2d7fb141deb006745000000000000000000000000000000000000000000000000000000000000000221c156e80276827e1bfeb6542ab064dfa958f5be955f516fb62b1c93437472c31cc65fcaba68c9d661701190bc32025a0690af0eefe027ac218fd15c588dd4d5 ``` Expect the output to be similar to the following: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```http GET /api/v1/reports?feedID=×tamp= ``` ##### [Sample response](https://docs.chain.link/data-streams/reference/streams-direct/streams-direct-interface-api\#sample-response) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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) ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![](https://docs.chain.link/images/tutorial-icons/solidity_logo.svg)EVM Chains (Solidity) [![](https://docs.chain.link/images/tutorial-icons/solidity_logo.svg)EVM Chains (Solidity)](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification) [![](https://docs.chain.link/images/tutorial-icons/solanaLogoMark.svg)Solana (Rust) / onchain integration](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification) [![](https://docs.chain.link/images/tutorial-icons/solanaLogoMark.svg)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. ![Chainlink Data Streams - Verify Report Data Onchain - Solidity Compiler](https://docs.chain.link/images/data-streams/onchain-verification/solidity-compiler.webp) 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_. ![Chainlink Data Streams - Verify Report Data Onchain - Injected Provider MetaMask](https://docs.chain.link/images/data-streams/onchain-verification/injected-provider.webp) 6. In the **Contract** section, select the `ClientReportsVerifier` contract and fill in the Arbitrum Sepolia **verifier proxy address**: `0x2ff010DEbC1297f19579B4246cad07bd24F2488A`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). You can find the verifier proxy addresses on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page. ![Chainlink Data Streams Remix Deploy ClientReportsVerifier Contract](https://docs.chain.link/images/data-streams/onchain-verification/deploy-clientReportsVerifier.webp) 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. ![Chainlink Data Streams Remix Deployed ClientReportsVerifier Contract](https://docs.chain.link/images/data-streams/onchain-verification/deployed-clientReportsVerifier-1.webp) ### [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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```plaintext 0x000660403d36be006d0c15d9b306f93c8660c5cfeab7db8e28c78ba316d395970000000000000000000000000000000000000000000000000000000032c3780a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200003c8e550d2fc5304993010112de9b69798297e4cc11990ee6250e464daf760000000000000000000000000000000000000000000000000000000006706e595000000000000000000000000000000000000000000000000000000006706e595000000000000000000000000000000000000000000000000000025bd3eb74c080000000000000000000000000000000000000000000000000021c6a95c654c7400000000000000000000000000000000000000000000000000000000670837150000000000000000000000000000000000000000000000079a2ab4077fc8fc6000000000000000000000000000000000000000000000000799fcb42536dfd8300000000000000000000000000000000000000000000000079a59496c3f29a0000000000000000000000000000000000000000000000000000000000000000002bd4acd37ce3cd5799de05d156ab328a5effd94468ebbaf2ff18d13d9631259cbe66cca01af6a8bb36e79d2d731a44e16791ee31e46ce27ed6530f1590cd7734c0000000000000000000000000000000000000000000000000000000000000002391562f1f2e4986bdb978fbf5ee27f7012992a79301af42d3473761ef2ede6271a61fbf4b32ac5be68a598bcfa523e035b624dab3b3d9a46276834f824ee592a ``` ![Chainlink Data Streams Remix Deployed ClientReportsVerifier Contract](https://docs.chain.link/images/data-streams/onchain-verification/deployed-clientReportsVerifier-2.webp) 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. ![Chainlink Data Streams - Price from Verified Report](https://docs.chain.link/images/data-streams/onchain-verification/price-from-verified-report.webp) ## [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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![](https://docs.chain.link/images/tutorial-icons/solanaLogoMark.svg)Solana (Rust) - Onchain integration [![](https://docs.chain.link/images/tutorial-icons/solidity_logo.svg)EVM Chains (Solidity)](https://docs.chain.link/data-streams/tutorials/streams-direct/evm-onchain-report-verification) [![](https://docs.chain.link/images/tutorial-icons/solanaLogoMark.svg)Solana (Rust) - Onchain integration](https://docs.chain.link/data-streams/tutorials/streams-direct/solana-onchain-report-verification) [![](https://docs.chain.link/images/tutorial-icons/solanaLogoMark.svg)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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) to verify your installation. - **Anchor Framework**: Follow the [official installation guide](https://www.anchor-lang.com/docs/installation). Run `anchor --version`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) to verify your installation. - **Node.js and npm**: [Install Node.js 20 or later](https://nodejs.org/). Verify your installation with `node --version`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). - **ts-node**: Install globally using npm: `npm install -g ts-node`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). Verify your installation with `ts-node --version`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). - **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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash anchor build ``` **Note**: If you run into this error, set the `version` field at the top of your `cargo.lock` file to `3`. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash anchor deploy ``` Expect an output similar to the following: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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. ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)Rust SDK - V4 reports for RWA streams [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go) [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rust) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash mkdir my-data-streams-project && cd my-data-streams-project ``` 2. Initialize a new Rust project: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash cargo init ``` 3. Add the Data Streams SDK to your `Cargo.toml`: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash cargo run -- 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea ``` Expect output similar to the following in your terminal: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```rust "wss://ws.testnet-dataengine.chain.link,wss://ws.testnet-dataengine.chain.link" ``` 2. Enabling HA mode in the configuration: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)Rust SDK - V4 reports for RWA streams [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-go) [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash mkdir my-data-streams-project && cd my-data-streams-project ``` 2. Initialize a new Rust project: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash cargo init ``` 3. Add the Data Streams SDK to your `Cargo.toml`: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash cargo run -- 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea ``` Expect output similar to the following in your terminal: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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": ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![Error handler flow diagram](https://docs.chain.link/images/automation/streamslookup-errorhandler-horizontal.png) 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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). ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V4 reports for RWA streams [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-go) [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rwa-go) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-ws-rust) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash mkdir my-data-streams-project cd my-data-streams-project ``` 2. Initialize a new Go module: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash go mod init my-data-streams-project ``` 3. Install the Data Streams SDK: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash touch stream.go ``` 2. Insert the following code example and save your `stream.go` file: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash go mod tidy ``` 4. Set up the SDK client configuration within `stream.go` with your API credentials and the WebSocket URL: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash go run stream.go 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea ``` Expect output similar to the following in your terminal: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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. ![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V4 reports for RWA streams [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-go) [![](https://docs.chain.link/images/tutorial-icons/go_logo_black.png)Go SDK - V4 reports for RWA streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rwa-go) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)Rust SDK - V3 reports for Crypto streams](https://docs.chain.link/data-streams/tutorials/streams-direct/streams-direct-api-rust) [![](https://docs.chain.link/images/tutorial-icons/rust_logo_blk.svg)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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash mkdir my-data-streams-project cd my-data-streams-project ``` 2. Initialize a new Go module: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash go mod init my-data-streams-project ``` 3. Install the Data Streams SDK: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash touch single-stream.go ``` 2. Insert the following code example and save your `single-stream.go` file: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash go mod tidy ``` 4. Set up the SDK client configuration within `single-stream.go` with your API credentials and the REST endpoint: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg). 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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash go run single-stream.go 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea ``` Expect output similar to the following in your terminal: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash touch multiple-streams.go ``` 2. Insert the following code example in your `multiple-streams.go` file: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash echo $API_KEY echo $API_SECRET ``` If the commands above don't show your credentials, set them again: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```bash go run multiple-streams.go 0x000434a5b30cafe7e853832a458ea1591dc2f5fb5e4cf80b9979b8248065a7ea 0x0004b9905d8337c34e00f8dbe31619428bac5c3937e73e6af75c71780f1770ce ``` Expect to see output similar to the following in your terminal: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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): ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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): ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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): ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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): ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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): ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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: ![copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) ```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