diff --git a/public/images/tutorial-icons/ts_logo_black.svg b/public/images/tutorial-icons/ts_logo_black.svg
new file mode 100644
index 00000000000..5e014b5172c
--- /dev/null
+++ b/public/images/tutorial-icons/ts_logo_black.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/config/sidebar.ts b/src/config/sidebar.ts
index 1b5febf9a3d..f785765ad25 100644
--- a/src/config/sidebar.ts
+++ b/src/config/sidebar.ts
@@ -445,12 +445,12 @@ export const SIDEBAR: Partial> = {
{
title: "Fetch and decode reports",
url: "data-streams/tutorials/go-sdk-fetch",
- highlightAsCurrent: ["data-streams/tutorials/rust-sdk-fetch"],
+ highlightAsCurrent: ["data-streams/tutorials/rust-sdk-fetch", "data-streams/tutorials/ts-sdk-fetch"],
},
{
title: "Stream and decode reports (WebSocket)",
url: "data-streams/tutorials/go-sdk-stream",
- highlightAsCurrent: ["data-streams/tutorials/rust-sdk-stream"],
+ highlightAsCurrent: ["data-streams/tutorials/rust-sdk-stream", "data-streams/tutorials/ts-sdk-stream"],
},
{
title: "Verify report data (EVM)",
@@ -524,7 +524,10 @@ export const SIDEBAR: Partial> = {
{
title: "SDK References",
url: "data-streams/reference/data-streams-api/go-sdk",
- highlightAsCurrent: ["data-streams/reference/data-streams-api/rust-sdk"],
+ highlightAsCurrent: [
+ "data-streams/reference/data-streams-api/rust-sdk",
+ "data-streams/reference/data-streams-api/ts-sdk",
+ ],
},
{
title: "Onchain report verification (EVM chains)",
diff --git a/src/content/data-streams/index.mdx b/src/content/data-streams/index.mdx
index 2cf5d1d24db..bc1098f1645 100644
--- a/src/content/data-streams/index.mdx
+++ b/src/content/data-streams/index.mdx
@@ -50,6 +50,15 @@ Chainlink Data Streams offers price points such as mid prices and [Liquidity-Wei
Data Streams API services use an [active-active multi-site deployment](/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.
+For real-time streaming applications, the SDKs support **High Availability (HA) mode** that establishes multiple simultaneous connections for zero-downtime operation. When enabled, HA mode provides:
+
+- **Automatic failover** between connections
+- **Report deduplication** across connections
+- **Automatic origin discovery** to find available endpoints
+- **Per-connection monitoring** and statistics
+
+**Learn more:** [Go SDK](/data-streams/reference/data-streams-api/go-sdk#high-availability-ha-mode) | [Rust SDK](/data-streams/reference/data-streams-api/rust-sdk#high-availability-mode) | [TypeScript SDK](/data-streams/reference/data-streams-api/ts-sdk#high-availability-mode)
+
## Example use cases
Access to low-latency, high-frequency data enables a variety of onchain applications:
@@ -82,6 +91,7 @@ Access data directly through REST APIs or WebSocket connections using our SDKs:
- **[Go SDK](/data-streams/reference/data-streams-api/go-sdk)** - Full-featured SDK with comprehensive examples
- **[Rust SDK](/data-streams/reference/data-streams-api/rust-sdk)** - High-performance SDK for Rust applications
+- **[TypeScript SDK](/data-streams/reference/data-streams-api/ts-sdk)** - Type-safe SDK for TypeScript applications
- **[REST API](/data-streams/reference/data-streams-api/interface-api)** or **[WebSocket](/data-streams/reference/data-streams-api/interface-ws)** - Direct access to Data Streams endpoints
### Getting started
diff --git a/src/content/data-streams/reference/data-streams-api/authentication/go-examples.mdx b/src/content/data-streams/reference/data-streams-api/authentication/go-examples.mdx
index e51d4aec446..dcac59ca6fc 100644
--- a/src/content/data-streams/reference/data-streams-api/authentication/go-examples.mdx
+++ b/src/content/data-streams/reference/data-streams-api/authentication/go-examples.mdx
@@ -17,7 +17,7 @@ Below are complete examples for authenticating with the Data Streams API in Go.
To learn more about the Data Streams API authentication, see the [Data Streams Authentication](/data-streams/reference/data-streams-api/authentication) page.
-**Note**: The Data Streams SDKs handle authentication automatically. If you're using the [Go SDK](/data-streams/reference/data-streams-api/go-sdk) or [Rust SDK](/data-streams/reference/data-streams-api/rust-sdk), you don't need to implement the authentication logic manually.
+**Note**: The Data Streams SDKs handle authentication automatically. If you're using the [Go SDK](/data-streams/reference/data-streams-api/go-sdk), [Rust SDK](/data-streams/reference/data-streams-api/rust-sdk), or [TypeScript SDK](/data-streams/reference/data-streams-api/ts-sdk), you don't need to implement the authentication logic manually.
## API Authentication Example
diff --git a/src/content/data-streams/reference/data-streams-api/authentication/index.mdx b/src/content/data-streams/reference/data-streams-api/authentication/index.mdx
index e6d9e700cfe..fc2827b9027 100644
--- a/src/content/data-streams/reference/data-streams-api/authentication/index.mdx
+++ b/src/content/data-streams/reference/data-streams-api/authentication/index.mdx
@@ -26,9 +26,9 @@ This page explains how to authenticate with the Chainlink Data Streams API, cove
## Authentication Requirements
diff --git a/src/content/data-streams/reference/data-streams-api/authentication/javascript-examples.mdx b/src/content/data-streams/reference/data-streams-api/authentication/javascript-examples.mdx
index ed71c834d58..73577fca4b6 100644
--- a/src/content/data-streams/reference/data-streams-api/authentication/javascript-examples.mdx
+++ b/src/content/data-streams/reference/data-streams-api/authentication/javascript-examples.mdx
@@ -17,7 +17,7 @@ Below are complete examples for authenticating with the Data Streams API in Java
To learn more about the Data Streams API authentication, see the [Data Streams Authentication](/data-streams/reference/data-streams-api/authentication) page.
-**Note**: The Data Streams SDKs handle authentication automatically. If you're using the [Go SDK](/data-streams/reference/data-streams-api/go-sdk) or [Rust SDK](/data-streams/reference/data-streams-api/rust-sdk), you don't need to implement the authentication logic manually.
+**Note**: The Data Streams SDKs handle authentication automatically. If you're using the [Go SDK](/data-streams/reference/data-streams-api/go-sdk), [Rust SDK](/data-streams/reference/data-streams-api/rust-sdk), or [TypeScript SDK](/data-streams/reference/data-streams-api/ts-sdk), you don't need to implement the authentication logic manually.
## API Authentication Example
diff --git a/src/content/data-streams/reference/data-streams-api/authentication/rust-examples.mdx b/src/content/data-streams/reference/data-streams-api/authentication/rust-examples.mdx
index cb5ce048b26..0f58329e59e 100644
--- a/src/content/data-streams/reference/data-streams-api/authentication/rust-examples.mdx
+++ b/src/content/data-streams/reference/data-streams-api/authentication/rust-examples.mdx
@@ -17,7 +17,7 @@ Below are complete examples for authenticating with the Data Streams API in Rust
To learn more about the Data Streams API authentication, see the [Data Streams Authentication](/data-streams/reference/data-streams-api/authentication) page.
-**Note**: The Data Streams SDKs handle authentication automatically. If you're using the [Go SDK](/data-streams/reference/data-streams-api/go-sdk) or [Rust SDK](/data-streams/reference/data-streams-api/rust-sdk), you don't need to implement the authentication logic manually.
+**Note**: The Data Streams SDKs handle authentication automatically. If you're using the [Go SDK](/data-streams/reference/data-streams-api/go-sdk), [Rust SDK](/data-streams/reference/data-streams-api/rust-sdk), or [TypeScript SDK](/data-streams/reference/data-streams-api/ts-sdk), you don't need to implement the authentication logic manually.
## API Authentication Example
diff --git a/src/content/data-streams/reference/data-streams-api/authentication/typescript-examples.mdx b/src/content/data-streams/reference/data-streams-api/authentication/typescript-examples.mdx
index ca48796733e..d53db27034c 100644
--- a/src/content/data-streams/reference/data-streams-api/authentication/typescript-examples.mdx
+++ b/src/content/data-streams/reference/data-streams-api/authentication/typescript-examples.mdx
@@ -17,7 +17,7 @@ Below are complete examples for authenticating with the Data Streams API in Type
To learn more about the Data Streams API authentication, see the [Data Streams Authentication](/data-streams/reference/data-streams-api/authentication) page.
-**Note**: The Data Streams SDKs handle authentication automatically. If you're using the [Go SDK](/data-streams/reference/data-streams-api/go-sdk) or [Rust SDK](/data-streams/reference/data-streams-api/rust-sdk), you don't need to implement the authentication logic manually.
+**Note**: The Data Streams SDKs handle authentication automatically. If you're using the [Go SDK](/data-streams/reference/data-streams-api/go-sdk), [Rust SDK](/data-streams/reference/data-streams-api/rust-sdk), or [TypeScript SDK](/data-streams/reference/data-streams-api/ts-sdk), you don't need to implement the authentication logic manually.
## API Authentication Example
diff --git a/src/content/data-streams/reference/data-streams-api/go-sdk.mdx b/src/content/data-streams/reference/data-streams-api/go-sdk.mdx
index 09ceb973e4e..b55ea6dd617 100644
--- a/src/content/data-streams/reference/data-streams-api/go-sdk.mdx
+++ b/src/content/data-streams/reference/data-streams-api/go-sdk.mdx
@@ -32,14 +32,30 @@ import { PageTabs } from "@components"
url: "/data-streams/reference/data-streams-api/rust-sdk",
icon: "/images/tutorial-icons/rust_logo_blk.svg",
},
+ {
+ name: "TypeScript SDK",
+ url: "/data-streams/reference/data-streams-api/ts-sdk",
+ icon: "/images/tutorial-icons/ts_logo_black.svg",
+ },
]}
/>
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.
+## Requirements
+
+- Go 1.22.4 or later
+- Valid Chainlink Data Streams credentials
+
+## Installation
+
+```go
+go get github.com/smartcontractkit/data-streams-sdk/go
+```
+
## streams
-### Installation
+### Import
```go
import streams "github.com/smartcontractkit/data-streams-sdk/go"
@@ -56,31 +72,37 @@ import streams "github.com/smartcontractkit/data-streams-sdk/go"
- `GetFeeds`: Lists all streams available to you.
```go
- GetFeeds(ctx context.Context) (r []*Feed, err error)
+ GetFeeds(ctx context.Context) (r []*feed.Feed, err error)
```
- `GetLatestReport`: Fetches the latest report available for the specified `FeedID`.
```go
- GetLatestReport(ctx context.Context, id FeedID) (r *Report, err error)
+ GetLatestReport(ctx context.Context, id feed.ID) (r *ReportResponse, err error)
```
- `GetReports`: Fetches reports for the specified stream IDs and a given timestamp.
```go
- GetReports(ctx context.Context, ids []FeedID, timestamp uint64) ([]*Report, error)
+ GetReports(ctx context.Context, ids []feed.ID, timestamp uint64) ([]*ReportResponse, error)
```
- `GetReportPage`: Paginates the reports for a specified `FeedID` starting from a given timestamp.
```go
- GetReportPage(ctx context.Context, id FeedID, startTS uint64) (*ReportPage, error)
+ GetReportPage(ctx context.Context, id feed.ID, startTS uint64) (*ReportPage, error)
```
- `Stream`: Creates a real-time report stream for specified stream IDs.
```go
- Stream(ctx context.Context, feedIDs []FeedID) (Stream, error)
+ Stream(ctx context.Context, feedIDs []feed.ID) (Stream, error)
+ ```
+
+- `StreamWithStatusCallback`: Creates a real-time report stream for specified stream IDs with a callback function for connection status updates.
+
+ ```go
+ StreamWithStatusCallback(ctx context.Context, feedIDs []feed.ID, connStatusCallback func(isConnected bool, host string, origin string)) (Stream, error)
```
#### `Config` struct
@@ -89,24 +111,24 @@ Configuration struct for the client. `Config` specifies the client configuration
```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
+ 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.
+ // InspectHttpResponse intercepts http responses for rest requests.
// The response object must not be modified.
InspectHttpResponse func(*http.Response)
}
```
+**Note**: If `WsMaxReconnect` is not specified, it defaults to 5 attempts.
+
#### `CtxKey` string
Custom context key type used for passing additional headers.
@@ -133,8 +155,8 @@ Represents a paginated response of reports.
```go
type ReportPage struct {
- Reports []*Report // Slice of Report, representing individual report entries.
- NextPageTS uint64 // Timestamp for the next page, used for fetching subsequent pages.
+ Reports []*ReportResponse // Slice of ReportResponse, representing individual report entries.
+ NextPageTS uint64 // Timestamp for the next page, used for fetching subsequent pages.
}
```
@@ -206,7 +228,7 @@ type Stats struct {
- An error state is encountered in any of the underlying connections, such as a network failure.
```go
- Read(context.Context) (*Report, error)
+ Read(context.Context) (*ReportResponse, error)
```
- `Stats`: Returns statistics about the stream operations as `Stats`.
@@ -221,6 +243,30 @@ type Stats struct {
Close() error
```
+### High Availability (HA) Mode
+
+The Data Streams SDK supports High Availability mode for WebSocket connections. When enabled with `WsHA: true`, the SDK maintains concurrent connections to different instances to ensure high availability, fault tolerance and minimize the risk of report gaps.
+
+#### HA Mode Behavior
+
+When high availability mode is enabled:
+
+- The client queries the server for available origins using the `X-Cll-Available-Origins` header
+- Multiple WebSocket connections are established to different server instances
+- Reports are deduplicated when received across connections
+- Partial reconnects occur when some connections fail while others remain active
+- Full reconnects occur when all connections fail
+
+#### HA Configuration
+
+HA mode is controlled by the `WsHA` field in the client configuration:
+
+```go
+config := streams.Config{
+ WsHA: true, // Use concurrent connections to multiple Streams servers
+}
+```
+
### Functions
#### `New`
@@ -241,9 +287,19 @@ Utility function for logging.
func LogPrintf(format string, a ...any)
```
+### Errors
+
+#### `ErrStreamClosed`
+
+Error returned when attempting to use a closed stream.
+
+```go
+var ErrStreamClosed = fmt.Errorf("client: use of closed Stream")
+```
+
## feed
-### Installation
+### Import
```go
import feed "github.com/smartcontractkit/data-streams-sdk/go/feed"
@@ -265,12 +321,25 @@ Where `ID` is the unique identifier for the stream.
#### `FeedVersion` uint16
-Represents the stream [report schema](/data-streams/reference/report-schema-v3) version.
+Represents the stream [report schema](/data-streams/reference/report-schema-overview) version.
```go
type FeedVersion uint16
```
+##### Constants
+
+- `FeedVersion1`: Version 1 schema
+- `FeedVersion2`: Version 2 schema
+- `FeedVersion3`: Version 3 schema
+- `FeedVersion4`: Version 4 schema
+- `FeedVersion5`: Version 5 schema
+- `FeedVersion6`: Version 6 schema
+- `FeedVersion7`: Version 7 schema
+- `FeedVersion8`: Version 8 schema
+- `FeedVersion9`: Version 9 schema
+- `FeedVersion10`: Version 10 schema
+
#### `ID` [32]byte
Represents a unique identifier for a stream.
@@ -313,7 +382,7 @@ type ID [32]byte
## report
-### Installation
+### Import
```go
import report "github.com/smartcontractkit/data-streams-sdk/go/report"
@@ -323,11 +392,11 @@ import report "github.com/smartcontractkit/data-streams-sdk/go/report"
#### `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.
+[Interface](https://github.com/smartcontractkit/data-streams-sdk/blob/main/go/report/report.go#L20) that represents the actual report data and attributes.
```go
type Data interface {
- v1.Data | v2.Data | v3.Data | v4.Data | v8.Data | v9.Data
+ v1.Data | v2.Data | v3.Data | v4.Data | v5.Data | v6.Data | v7.Data | v8.Data | v9.Data | v10.Data
Schema() abi.Arguments
}
```
@@ -382,3 +451,44 @@ streams.LogPrintf(
report.Data.ExpiresAt,
)
```
+
+## Report Format and Schema Versions
+
+### Schema Versions
+
+The SDK supports multiple report schema versions (v1-v10), each optimized for different use cases:
+
+- **v2**: Feed IDs starting with `0x0002`
+- **v3**: Feed IDs starting with `0x0003` (Crypto Streams)
+- **v4**: Feed IDs starting with `0x0004` (Real-World Assets)
+- **v5**: Feed IDs starting with `0x0005`
+- **v6**: Feed IDs starting with `0x0006` (Multiple Price Values)
+- **v7**: Feed IDs starting with `0x0007` (Exchange Rate)
+- **v8**: Feed IDs starting with `0x0008` (Non-OTC RWA)
+- **v9**: Feed IDs starting with `0x0009` (NAV Fund Data)
+- **v10**: Feed IDs starting with `0x000a` (Tokenized Equity)
+
+### Common Fields
+
+All report versions include standard metadata:
+
+- `FeedID`: Unique identifier for the data stream
+- `ValidFromTimestamp`: When the report becomes valid
+- `ExpiresAt`: When the report expires
+- `LinkFee`: Fee in LINK tokens
+- `NativeFee`: Fee in native blockchain currency
+- `ObservationsTimestamp`: When the data was observed
+
+### Usage Pattern
+
+Each version follows the same decoding pattern:
+
+```go
+import v3 "github.com/smartcontractkit/data-streams-sdk/go/report/v3"
+
+report, err := report.Decode[v3.Data](fullReport)
+```
+
+Use the appropriate version import based on your feed's schema version, which can be determined by calling `feedID.Version()`.
+
+For complete field definitions and decoding examples, see the [report schema overview](/data-streams/reference/report-schema-overview) and [fetch tutorial](/data-streams/tutorials/go-sdk-fetch).
diff --git a/src/content/data-streams/reference/data-streams-api/rust-sdk.mdx b/src/content/data-streams/reference/data-streams-api/rust-sdk.mdx
index 64bfbc758f8..6b6194c5c56 100644
--- a/src/content/data-streams/reference/data-streams-api/rust-sdk.mdx
+++ b/src/content/data-streams/reference/data-streams-api/rust-sdk.mdx
@@ -32,6 +32,11 @@ import { PageTabs } from "@components"
url: "/data-streams/reference/data-streams-api/rust-sdk",
icon: "/images/tutorial-icons/rust_logo_blk.svg",
},
+ {
+ name: "TypeScript SDK",
+ url: "/data-streams/reference/data-streams-api/ts-sdk",
+ icon: "/images/tutorial-icons/ts_logo_black.svg",
+ },
]}
/>
diff --git a/src/content/data-streams/reference/data-streams-api/ts-sdk.mdx b/src/content/data-streams/reference/data-streams-api/ts-sdk.mdx
new file mode 100644
index 00000000000..8163c14c426
--- /dev/null
+++ b/src/content/data-streams/reference/data-streams-api/ts-sdk.mdx
@@ -0,0 +1,533 @@
+---
+section: dataStreams
+date: Last Modified
+title: "Data Streams SDK (TypeScript)"
+metadata:
+ title: "Data Streams TypeScript SDK Reference | Chainlink Documentation"
+ description: "Integrate with Chainlink Data Streams using the TypeScript SDK. Learn about client configuration, authentication, fetching reports, and WebSocket streaming."
+ keywords: ["TypeScript SDK", "Data Streams", "Integration", "API Client", "WebSocket Client", "Report Decoding"]
+whatsnext:
+ {
+ "Learn how to fetch and decode Data Streams reports using the Data Streams SDK": "/data-streams/tutorials/ts-sdk-fetch",
+ "Learn how to stream and decode reports via a WebSocket connection using the Data Streams SDK": "/data-streams/tutorials/ts-sdk-stream",
+ }
+---
+
+import DataStreams from "@features/data-streams/common/DataStreams.astro"
+import { Aside, PageTabs } from "@components"
+
+
+
+
+The Data Streams SDK for accessing Chainlink Data Streams with real-time streaming and historical data retrieval.
+
+## Requirements
+
+- Node.js >= 20.0.0
+- TypeScript >= 5.3.x
+- Valid Chainlink Data Streams credentials
+
+## Features
+
+- **[Real-time streaming](#streaming)** via WebSocket connections
+- **[High Availability mode](#high-availability-mode)** with multiple connections and automatic failover
+- **Historical data access** via [REST API](#rest-api)
+- **[Automatic report decoding](#schema-auto-detection)** for all supported formats (V2, V3, V4, V5, V6, V7, V8, V9, V10)
+- **[Metrics](#observability-logs--metrics)** for monitoring and observability
+- **Type-safe** with full TypeScript support
+- **Event-driven architecture** for complete developer control
+
+## Installation
+
+```bash
+npm install @chainlink/data-streams-sdk
+```
+
+## Configuration
+
+### Configuration Interface
+
+```typescript
+interface Config {
+ // Required
+ apiKey: string // API key for authentication
+ userSecret: string // User secret for authentication
+ endpoint: string // REST API URL
+ wsEndpoint: string // WebSocket URL
+
+ // Optional - Request & Retry
+ timeout?: number // Request timeout (default: 30000ms)
+ retryAttempts?: number // Retry attempts (default: 3)
+ retryDelay?: number // Retry delay (default: 1000ms)
+
+ // Optional - High Availability
+ haMode?: boolean // Enable HA mode (default: false)
+ haConnectionTimeout?: number // HA connection timeout (default: 10000ms)
+ connectionStatusCallback?: (isConnected: boolean, host: string, origin: string) => void
+
+ // Optional - Logging
+ logging?: LoggingConfig // See Logging Configuration section
+}
+```
+
+### Basic Usage
+
+```typescript
+const client = createClient({
+ apiKey: process.env.API_KEY,
+ userSecret: process.env.USER_SECRET,
+ endpoint: "https://api.dataengine.chain.link",
+ wsEndpoint: "wss://ws.dataengine.chain.link",
+})
+```
+
+### High Availability Example
+
+```typescript
+const haClient = createClient({
+ apiKey: process.env.API_KEY,
+ userSecret: process.env.USER_SECRET,
+ endpoint: "https://api.dataengine.chain.link", // Mainnet only
+ wsEndpoint: "wss://ws.dataengine.chain.link", // Single endpoint with origin discovery
+ haMode: true,
+})
+```
+
+**Note:** [High Availability mode](#high-availability-mode) is only available on mainnet, not testnet.
+
+## Examples
+
+
+**Quick Commands:**
+
+```bash
+# Real-time streaming
+npx ts-node examples/stream-reports.ts 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
+
+# High Availability streaming
+npx ts-node examples/stream-reports.ts 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 --ha
+
+# Get latest report
+npx ts-node examples/get-latest-report.ts 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
+
+# List all available feeds
+npx ts-node examples/list-feeds.ts
+```
+
+**Complete examples**
+See the [SDK repo examples](https://github.com/smartcontractkit/data-streams-sdk/tree/main/typescript/examples) for detailed usage and setup. Available examples include:
+
+- **Streaming:** Basic streaming, HA mode, metrics monitoring
+- **REST API:** Latest reports, historical data, bulk operations, feed management
+- **Configuration:** Logging setup, debugging, monitoring integration
+
+## API Reference
+
+### Streaming
+
+```typescript
+// Create stream
+const stream = client.createStream(feedIds, options?);
+
+// Events
+stream.on('report', (report) => { ... });
+stream.on('error', (error) => { ... });
+stream.on('disconnected', () => { ... });
+stream.on('reconnecting', (info) => { ... });
+
+// Control
+await stream.connect();
+await stream.close();
+
+// Metrics
+const metrics = stream.getMetrics();
+```
+
+### Stream Options
+
+```typescript
+interface StreamOptions {
+ maxReconnectAttempts?: number // Default: 5
+ // Base delay (in ms) for exponential backoff.
+ // Actual delay grows as: base * 2^(attempt-1) with jitter, capped at 10000ms.
+ // Default: 1000ms; user-provided values are clamped to the safe range [200ms, 10000ms].
+ reconnectInterval?: number
+}
+```
+
+### REST API
+
+```typescript
+// Get feeds
+const feeds = await client.listFeeds();
+
+// Get latest report
+const report = await client.getLatestReport(feedId);
+
+// Get historical report
+const report = await client.getReportByTimestamp(feedId, timestamp);
+
+// Get report page
+const reports = await client.getReportsPage(feedId, startTime, limit?);
+
+// Get bulk reports
+const reports = await client.getReportsBulk(feedIds, timestamp);
+```
+
+## Report Format
+
+### Quick Decoder Usage
+
+```typescript
+import { decodeReport } from "@chainlink/data-streams-sdk"
+const decoded = decodeReport(report.fullReport, report.feedID)
+```
+
+### Schema Auto-Detection
+
+The SDK automatically detects and decodes all report versions based on Feed ID patterns:
+
+- **V2**: Feed IDs starting with `0x0002`
+- **V3**: Feed IDs starting with `0x0003` (Crypto Streams)
+- **V4**: Feed IDs starting with `0x0004` (Real-World Assets)
+- **V5**: Feed IDs starting with `0x0005`
+- **V6**: Feed IDs starting with `0x0006` (Multiple Price Values)
+- **V7**: Feed IDs starting with `0x0007`
+- **V8**: Feed IDs starting with `0x0008` (Non-OTC RWA)
+- **V9**: Feed IDs starting with `0x0009` (NAV Fund Data)
+- **V10**: Feed IDs starting with `0x000a` (Tokenized Equity)
+
+### Common Fields
+
+All reports include standard metadata:
+
+```typescript
+interface BaseFields {
+ version: "V2" | "V3" | "V4" | "V5" | "V6" | "V7" | "V8" | "V9" | "V10"
+ nativeFee: bigint
+ linkFee: bigint
+ expiresAt: number
+ feedID: string
+ validFromTimestamp: number
+ observationsTimestamp: number
+}
+```
+
+### Schema-Specific Fields
+
+- **V2/V3/V4**: `price: bigint` - Standard price data
+- **V3**: `bid: bigint, ask: bigint` - Crypto bid/ask spreads
+- **V4**: `marketStatus: MarketStatus` - Real-world asset market status
+- **V5**: `rate: bigint, timestamp: number, duration: number` - Interest rate data with observation timestamp and duration
+- **V6**: `price: bigint, price2: bigint, price3: bigint, price4: bigint, price5: bigint` - Multiple price values in a single payload
+- **V7**: `exchangeRate: bigint` - Exchange rate data
+- **V8**: `midPrice: bigint, lastUpdateTimestamp: number, marketStatus: MarketStatus` - Non-OTC RWA data
+- **V9**: `navPerShare: bigint, navDate: number, aum: bigint, ripcord: number` - NAV fund data
+- **V10**: `price: bigint, lastUpdateTimestamp: number, marketStatus: MarketStatus, currentMultiplier: bigint, newMultiplier: bigint, activationDateTime: number, tokenizedPrice: bigint` - Tokenized equity data
+
+For complete field definitions, see the [complete list of available reports and their schemas](/data-streams/reference/report-schema-overview).
+
+## High Availability Mode
+
+HA mode establishes multiple simultaneous connections for zero-downtime operation:
+
+- **Automatic failover** between connections
+- **Report deduplication** across connections
+- **Automatic origin discovery** to find available endpoints
+- **Per-connection monitoring** and statistics
+
+```typescript
+const client = createClient({
+ // ...config
+ haMode: true,
+ wsEndpoint: "wss://ws.dataengine.chain.link", // Single endpoint (mainnet only)
+})
+```
+
+**How it works:** When `haMode` is `true`, the SDK automatically discovers multiple origin endpoints behind the single URL and establishes separate connections to each origin.
+
+**Connection monitoring:** The optional `connectionStatusCallback` can be used to integrate with external monitoring systems. The SDK already provides comprehensive connection logs, so this callback is primarily useful for custom alerting or metrics collection. See [`examples/metrics-monitoring.ts`](https://github.com/smartcontractkit/data-streams-sdk/blob/main/typescript/examples/metrics-monitoring.ts) for a complete implementation example.
+
+**Important:** HA mode is only available on mainnet endpoints.
+
+## Error Handling
+
+### Error Types Overview
+
+| **Error Type** | **When Thrown** | **Key Properties** |
+| ------------------------------- | ------------------------------------------- | --------------------------------------------- |
+| `ValidationError` | Invalid feed IDs, timestamps, parameters | `message` |
+| `AuthenticationError` | Invalid credentials, HMAC failures | `message` |
+| `APIError` | HTTP 4xx/5xx, network timeouts, rate limits | `statusCode`, `message` |
+| `ReportDecodingError` | Corrupted report data, unsupported versions | `message` |
+| `WebSocketError` | Connection failures, protocol errors | `message` |
+| `OriginDiscoveryError` | HA discovery failures | `cause`, `message` |
+| `MultiConnectionError` | All HA connections failed | `message` |
+| `PartialConnectionFailureError` | Some HA connections failed | `failedConnections`, `totalConnections` |
+| `InsufficientConnectionsError` | HA degraded performance | `availableConnections`, `requiredConnections` |
+
+### Usage Examples
+
+```typescript
+import {
+ ValidationError,
+ AuthenticationError,
+ APIError,
+ ReportDecodingError,
+ WebSocketError,
+ OriginDiscoveryError,
+ MultiConnectionError,
+} from "./src"
+
+// REST API error handling
+try {
+ const report = await client.getLatestReport(feedId)
+} catch (error) {
+ if (error instanceof ValidationError) {
+ // Invalid feed ID or parameters
+ } else if (error instanceof AuthenticationError) {
+ // Check API credentials
+ } else if (error instanceof APIError) {
+ // Server error - check error.statusCode (429, 500, etc.)
+ } else if (error instanceof ReportDecodingError) {
+ // Corrupted or unsupported report format
+ }
+}
+
+// Streaming error handling
+stream.on("error", (error) => {
+ if (error instanceof WebSocketError) {
+ // Connection issues - retry or fallback
+ } else if (error instanceof OriginDiscoveryError) {
+ // HA discovery failed - falls back to static config
+ } else if (error instanceof MultiConnectionError) {
+ // All HA connections failed - critical
+ }
+})
+```
+
+**Catch-all error handling:**
+
+```typescript
+import { DataStreamsError } from "./src"
+
+try {
+ // Any SDK operation
+} catch (error) {
+ if (error instanceof DataStreamsError) {
+ // Handles ANY SDK error (base class for all error types above)
+ console.log("SDK error:", error.message)
+ } else {
+ // Non-SDK error (network, system, etc.)
+ console.log("System error:", error)
+ }
+}
+```
+
+## Observability (Logs & Metrics)
+
+The SDK is designed to plug into your existing observability stack.
+
+### Logging (Pino/Winston/Console)
+
+Pass your logger to the SDK and choose a verbosity level. For deep WS diagnostics, enable connection debug.
+
+### Quick Start
+
+```typescript
+import { createClient, LogLevel } from "@chainlink/data-streams-sdk"
+
+// Silent mode (default) - Zero overhead
+const client = createClient({
+ /* ... config without logging */
+})
+
+// Basic console logging
+const client = createClient({
+ // ... other config
+ logging: {
+ logger: {
+ info: console.log,
+ warn: console.warn,
+ error: console.error,
+ },
+ },
+})
+```
+
+Using Pino (structured JSON):
+
+```typescript
+import pino from "pino"
+import { createClient, LogLevel } from "@chainlink/data-streams-sdk"
+
+const root = pino({ level: process.env.PINO_LEVEL || "info" })
+const sdk = root.child({ component: "sdk" })
+
+const client = createClient({
+ // ...config
+ logging: {
+ logger: {
+ info: sdk.info.bind(sdk),
+ warn: sdk.warn.bind(sdk),
+ error: sdk.error.bind(sdk),
+ debug: sdk.debug.bind(sdk),
+ },
+ logLevel: LogLevel.INFO,
+ // For very verbose WS diagnostics, set DEBUG + enableConnectionDebug
+ // logLevel: LogLevel.DEBUG,
+ // enableConnectionDebug: true,
+ },
+})
+```
+
+Command-line with pretty output:
+
+```bash
+PINO_LEVEL=info npx ts-node examples/metrics-monitoring.ts | npx pino-pretty
+```
+
+### Log Levels
+
+#### š“ ERROR
+
+**Critical failures only**
+
+- Authentication failures
+- Network connection errors
+- Report decoding failures
+- API request failures
+- Unexpected crashes
+
+**Example Use:** Production alerts & monitoring
+
+---
+
+#### š” WARN
+
+**Everything in ERROR +**
+
+- Partial reconnections
+- Fallback to static origins
+- Retry attempts
+- Connection timeouts
+- Invalid data warnings
+
+**Example Use:** Production environments
+
+---
+
+#### šµ INFO
+
+**Everything in WARN +**
+
+- Client initialization
+- Successful API calls
+- Stream connections
+- Report retrievals
+- Connection status changes
+- Connection mode determination
+
+**Example Use:** Development & staging
+
+---
+
+#### š DEBUG
+
+**Everything in INFO +**
+
+- Feed ID validation
+- Report decoding steps
+- Auth header generation
+- Request/response details
+- WebSocket ping/pong
+- Origin discovery process
+- Configuration validation
+- Origin tracking (HA mode)
+
+**Example Use:** Debugging & development only
+
+### Logging Configuration Options
+
+```typescript
+interface LoggingConfig {
+ /** External logger functions (console, winston, pino, etc.) */
+ logger?: {
+ debug?: (message: string, ...args: any[]) => void
+ info?: (message: string, ...args: any[]) => void
+ warn?: (message: string, ...args: any[]) => void
+ error?: (message: string, ...args: any[]) => void
+ }
+
+ /** Minimum logging level - filters out lower priority logs */
+ logLevel?: LogLevel // DEBUG (0) | INFO (1) | WARN (2) | ERROR (3)
+
+ /** Enable WebSocket ping/pong and connection state debugging logs */
+ enableConnectionDebug?: boolean
+}
+```
+
+**Compatible with:** console, winston, pino, and any logger with `debug/info/warn/error` methods. See `examples/logging-basic.ts` for complete integration examples.
+
+**For debugging:** Use `LogLevel.DEBUG` for full diagnostics and `enableConnectionDebug: true` to see WebSocket ping/pong messages and connection state transitions.
+
+**Origin tracking** in HA mode shows which specific endpoint received each report.
+
+### Metrics (`stream.getMetrics()`)
+
+The `stream.getMetrics()` API provides a complete snapshot for dashboards and alerts:
+
+```typescript
+const m = stream.getMetrics()
+// m.accepted, m.deduplicated, m.totalReceived
+// m.partialReconnects, m.fullReconnects
+// m.activeConnections, m.configuredConnections
+// m.originStatus: { [origin]: ConnectionStatus }
+```
+
+Simple periodic print (example):
+
+```typescript
+setInterval(() => {
+ const m = stream.getMetrics()
+ console.log(`accepted=${m.accepted} dedup=${m.deduplicated} active=${m.activeConnections}/${m.configuredConnections}`)
+}, 30000)
+```
+
+Refer to `examples/metrics-monitoring.ts` for a full metrics dashboard example.
+
+## Testing
+
+```bash
+npm test # All tests
+npm run test:unit # Unit tests only
+npm run test:integration # Integration tests only
+```
+
+## Feed IDs
+
+For available feed IDs, select your desired report [from the report schema overview](/data-streams/reference/report-schema-overview).
diff --git a/src/content/data-streams/reference/overview.mdx b/src/content/data-streams/reference/overview.mdx
index 23005d27422..b7e8340c4e3 100644
--- a/src/content/data-streams/reference/overview.mdx
+++ b/src/content/data-streams/reference/overview.mdx
@@ -13,13 +13,13 @@ Chainlink Data Streams offers two distinct solutions for accessing low-latency m
### Which solution should I use?
-| Feature | [Data Streams API](#data-streams-api) | [Candlestick API](#candlestick-api) |
-| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **Primary Use Case** | Low-latency data for smart contracts | OHLC data for analytics, charting, and dashboards |
-| **Data Format** | Signed, verifiable data reports | Aggregated OHLC (candlestick) data |
-| **Interfaces** | SDKs ([Go](/data-streams/reference/data-streams-api/go-sdk), [Rust](/data-streams/reference/data-streams-api/rust-sdk)), [REST API](/data-streams/reference/data-streams-api/interface-api) & [WebSocket](/data-streams/reference/data-streams-api/interface-ws) | [REST API](/data-streams/reference/candlestick-api) (including a [streaming endpoint](/data-streams/reference/candlestick-api#get-streaming-price-updates)) |
-| **Authentication** | [HMAC Signature](/data-streams/reference/data-streams-api/authentication) (automatic with SDKs) | [JWT](/data-streams/reference/candlestick-api#authorize-and-get-token) (token-based) |
-| **Cryptographic Proof** | ā Yes (See [Verification methods](#verification)) | ā No |
+| Feature | [Data Streams API](#data-streams-api) | [Candlestick API](#candlestick-api) |
+| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Primary Use Case** | Low-latency data for smart contracts | OHLC data for analytics, charting, and dashboards |
+| **Data Format** | Signed, verifiable data reports | Aggregated OHLC (candlestick) data |
+| **Interfaces** | SDKs ([Go](/data-streams/reference/data-streams-api/go-sdk), [Rust](/data-streams/reference/data-streams-api/rust-sdk), [TypeScript](/data-streams/reference/data-streams-api/ts-sdk)), [REST API](/data-streams/reference/data-streams-api/interface-api) & [WebSocket](/data-streams/reference/data-streams-api/interface-ws) | [REST API](/data-streams/reference/candlestick-api) (including a [streaming endpoint](/data-streams/reference/candlestick-api#get-streaming-price-updates)) |
+| **Authentication** | [HMAC Signature](/data-streams/reference/data-streams-api/authentication) (automatic with SDKs) | [JWT](/data-streams/reference/candlestick-api#authorize-and-get-token) (token-based) |
+| **Cryptographic Proof** | ā Yes (See [Verification methods](#verification)) | ā No |
---
@@ -33,6 +33,7 @@ The [Data Streams API](/data-streams/reference/data-streams-api) provides crypto
- [Go SDK](/data-streams/reference/data-streams-api/go-sdk) - Native Go language integration
- [Rust SDK](/data-streams/reference/data-streams-api/rust-sdk) - Native Rust language integration
+- [TypeScript SDK](/data-streams/reference/data-streams-api/ts-sdk) - Native TypeScript language integration
#### Direct API Access
diff --git a/src/content/data-streams/tutorials/go-sdk-fetch.mdx b/src/content/data-streams/tutorials/go-sdk-fetch.mdx
index e7f4ea53e5c..7a3163b8207 100644
--- a/src/content/data-streams/tutorials/go-sdk-fetch.mdx
+++ b/src/content/data-streams/tutorials/go-sdk-fetch.mdx
@@ -31,6 +31,11 @@ import DataStreams from "@features/data-streams/common/DataStreams.astro"
url: "/data-streams/tutorials/rust-sdk-fetch",
icon: "/images/tutorial-icons/rust_logo_blk.svg",
},
+ {
+ name: "TypeScript SDK",
+ url: "/data-streams/tutorials/ts-sdk-fetch",
+ icon: "/images/tutorial-icons/ts_logo_black.svg",
+ },
]}
/>
diff --git a/src/content/data-streams/tutorials/go-sdk-stream.mdx b/src/content/data-streams/tutorials/go-sdk-stream.mdx
index 9053b4a38e2..d861dd07326 100644
--- a/src/content/data-streams/tutorials/go-sdk-stream.mdx
+++ b/src/content/data-streams/tutorials/go-sdk-stream.mdx
@@ -30,6 +30,11 @@ import DataStreams from "@features/data-streams/common/DataStreams.astro"
url: "/data-streams/tutorials/rust-sdk-stream",
icon: "/images/tutorial-icons/rust_logo_blk.svg",
},
+ {
+ name: "TypeScript SDK",
+ url: "/data-streams/tutorials/ts-sdk-stream",
+ icon: "/images/tutorial-icons/ts_logo_black.svg",
+ },
]}
/>
@@ -322,6 +327,71 @@ The decoded report details include:
For descriptions and data types of other report schemas, see the [Report Schema Overview](/data-streams/reference/report-schema-overview).
+### Subscribing to multiple streams
+
+You can subscribe to multiple streams by providing additional stream IDs as command-line arguments:
+
+```bash
+go run stream.go 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 0x00036fe43f87884450b4c7e093cd5ed99cac6640d8c2000e6afc02c8838d0265
+```
+
+This will subscribe to both ETH/USD and BTC/USD streams.
+
+### High Availability (HA) mode
+
+
+
+The example above demonstrates streaming data from a single crypto stream. For production environments, especially when subscribing to multiple streams, it's recommended to enable [High Availability (HA) mode](/data-streams/reference/data-streams-api/go-sdk#high-availability-ha-mode).
+
+High Availability (HA) mode creates multiple WebSocket connections to different origin endpoints for improved reliability. When HA mode is enabled, the Stream will maintain at least 2 concurrent connections to different instances to ensure high availability, fault tolerance and minimize the risk of report gaps.
+
+#### Enabling HA mode
+
+To enable HA mode in your streaming application, make these changes to the basic example:
+
+```go
+// ... existing code ...
+
+// Enable HA mode with mainnet endpoint
+cfg := streams.Config{
+ ApiKey: os.Getenv("API_KEY"),
+ ApiSecret: os.Getenv("API_SECRET"),
+ WsURL: "wss://ws.dataengine.chain.link", // Use mainnet endpoint for HA mode
+ WsHA: true, // Enable High Availability mode
+ Logger: streams.LogPrintf,
+}
+
+client, err := streams.New(cfg)
+if err != nil {
+ cfg.Logger("Failed to create client: %v\n", err)
+ os.Exit(1)
+}
+
+// ... existing code ...
+
+// Optional: Change streams subscription to use StreamWithStatusCallback for connection monitoring
+stream, err := client.StreamWithStatusCallback(
+ ctx, ids,
+ func(isConnected bool, host string, origin string) {
+ status := "DISCONNECTED"
+ if isConnected {
+ status = "CONNECTED"
+ }
+ cfg.Logger("Host: %s, Origin: %s, Status: %s\n", host, origin, status)
+ },
+)
+
+// ... existing code ...
+```
+
+When `WsHA` is `true`, the SDK automatically discovers multiple origin endpoints behind the single URL and establishes separate connections to each origin. You also must use a mainnet endpoint, as HA mode is not currently supported on testnet.
+
+The optional `StreamWithStatusCallback` can be used to monitor individual connection status. The SDK already provides comprehensive connection logs through `stream.Stats().String()`, so this callback is primarily useful for custom alerting or connection monitoring.
+
+See more details about HA mode in the [SDK Reference](/data-streams/reference/data-streams-api/go-sdk#high-availability-ha-mode).
+
### Payload for onchain verification
In this tutorial, you logged and decoded the `full_report` payloads to extract the report data. However, in a production environment, you should verify the data to ensure its integrity and authenticity.
diff --git a/src/content/data-streams/tutorials/overview.mdx b/src/content/data-streams/tutorials/overview.mdx
index 134fa664638..33883737ef2 100644
--- a/src/content/data-streams/tutorials/overview.mdx
+++ b/src/content/data-streams/tutorials/overview.mdx
@@ -18,13 +18,14 @@ Explore several tutorials to learn how to use the Data Streams.
## Fetch, Stream, and Decode Reports
-- [Fetch and decode reports](/data-streams/tutorials/go-sdk-fetch): Learn how to fetch and decode reports from the Data Streams Aggregation Network, using the [Go](/data-streams/reference/data-streams-api/go-sdk) or [Rust](/data-streams/reference/data-streams-api/rust-sdk) SDKs.
-- [Stream and decode reports (WebSocket)](/data-streams/tutorials/go-sdk-stream): Learn how to listen for real-time reports from the Data Streams Aggregation Network, decode the report data, and log their attributes, using the [Go](/data-streams/reference/data-streams-api/go-sdk) or [Rust](/data-streams/reference/data-streams-api/rust-sdk) SDKs.
+- [Fetch and decode reports](/data-streams/tutorials/go-sdk-fetch): Learn how to fetch and decode reports from the Data Streams Aggregation Network, using the [Go](/data-streams/reference/data-streams-api/go-sdk), [Rust](/data-streams/reference/data-streams-api/rust-sdk), or [TypeScript](/data-streams/reference/data-streams-api/ts-sdk) SDKs.
+- [Stream and decode reports (WebSocket)](/data-streams/tutorials/go-sdk-stream): Learn how to listen for real-time reports from the Data Streams Aggregation Network, decode the report data, and log their attributes, using the [Go](/data-streams/reference/data-streams-api/go-sdk), [Rust](/data-streams/reference/data-streams-api/rust-sdk), or [TypeScript](/data-streams/reference/data-streams-api/ts-sdk) SDKs.
diff --git a/src/content/data-streams/tutorials/rust-sdk-fetch.mdx b/src/content/data-streams/tutorials/rust-sdk-fetch.mdx
index 884cb6ce559..2c5d5a6684d 100644
--- a/src/content/data-streams/tutorials/rust-sdk-fetch.mdx
+++ b/src/content/data-streams/tutorials/rust-sdk-fetch.mdx
@@ -31,6 +31,11 @@ import DataStreams from "@features/data-streams/common/DataStreams.astro"
url: "/data-streams/tutorials/rust-sdk-fetch",
icon: "/images/tutorial-icons/rust_logo_blk.svg",
},
+ {
+ name: "TypeScript SDK",
+ url: "/data-streams/tutorials/ts-sdk-fetch",
+ icon: "/images/tutorial-icons/ts_logo_black.svg",
+ },
]}
/>
diff --git a/src/content/data-streams/tutorials/rust-sdk-stream.mdx b/src/content/data-streams/tutorials/rust-sdk-stream.mdx
index fd2d211a3a1..47fef9f173d 100644
--- a/src/content/data-streams/tutorials/rust-sdk-stream.mdx
+++ b/src/content/data-streams/tutorials/rust-sdk-stream.mdx
@@ -30,6 +30,11 @@ import DataStreams from "@features/data-streams/common/DataStreams.astro"
url: "/data-streams/tutorials/rust-sdk-stream",
icon: "/images/tutorial-icons/rust_logo_blk.svg",
},
+ {
+ name: "TypeScript SDK",
+ url: "/data-streams/tutorials/ts-sdk-stream",
+ icon: "/images/tutorial-icons/ts_logo_black.svg",
+ },
]}
/>
@@ -305,24 +310,7 @@ In this tutorial, you'll learn how to use the [Data Streams SDK](/data-streams/r
[Learn more about the decoded report details](#decoded-report-details).
-### High Availability (HA) Mode
-
-The example above demonstrates streaming data from a single crypto stream. For production environments, especially when subscribing to multiple streams, it's recommended to enable [High Availability (HA) mode](https://github.com/smartcontractkit/data-streams-sdk/blob/main/rust/docs/examples/wss_multiple.md). This can be achieved by:
-
-1. Adding multiple WebSocket endpoints in the configuration:
-
- ```rust
- "wss://ws.testnet-dataengine.chain.link,wss://ws.testnet-dataengine.chain.link"
- ```
-
-1. Enabling HA mode in the configuration:
- ```rust
- use chainlink_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.
+### Subscribing to multiple streams
You can subscribe to multiple streams by providing additional stream IDs as command-line arguments:
@@ -334,6 +322,43 @@ cargo run -- \
This will subscribe to both ETH/USD and BTC/USD streams.
+### High Availability (HA) mode
+
+
+
+The example above demonstrates streaming data from a single crypto stream. For production environments, especially when subscribing to multiple streams, it's recommended to enable [High Availability (HA) mode](/data-streams/reference/data-streams-api/rust-sdk#high-availability-mode).
+
+High Availability (HA) mode creates multiple WebSocket connections to different origin endpoints for improved reliability. When HA mode is enabled, the Stream will maintain at least 2 concurrent connections to different instances to ensure high availability, fault tolerance and minimize the risk of report gaps.
+
+#### Enabling HA mode
+
+To enable HA mode in your streaming application, make these changes to the basic example. You also must use a mainnet endpoint, as HA mode is not currently supported on testnet.
+
+```rust
+// ... existing code ...
+
+use chainlink_data_streams_sdk::config::{Config, WebSocketHighAvailability}; // Import WebSocketHighAvailability
+
+// ... existing code ...
+
+// Initialize the configuration with HA mode
+let config = Config::new(
+ api_key,
+ api_secret,
+ "https://api.dataengine.chain.link".to_string(), // Mainnet endpoint
+ "wss://ws.dataengine.chain.link,wss://ws.dataengine.chain.link".to_string(), // Multiple WebSocket endpoints
+)
+.with_ws_ha(WebSocketHighAvailability::Enabled) // Enable WebSocket High Availability Mode
+.build()?;
+
+
+// ... existing code ...
+```
+
+See more details about HA mode in the [SDK Reference](/data-streams/reference/data-streams-api/rust-sdk#high-availability-mode).
+
### Decoded report details
The decoded report details include:
diff --git a/src/content/data-streams/tutorials/ts-sdk-fetch.mdx b/src/content/data-streams/tutorials/ts-sdk-fetch.mdx
new file mode 100644
index 00000000000..2947743de21
--- /dev/null
+++ b/src/content/data-streams/tutorials/ts-sdk-fetch.mdx
@@ -0,0 +1,494 @@
+---
+section: dataStreams
+date: Last Modified
+title: "Fetch and decode Data Streams reports using the TypeScript SDK"
+metadata:
+ title: "Fetch and Decode Data Streams Reports with TypeScript SDK | Chainlink Data Streams"
+ description: "Learn how to use the TypeScript SDK to fetch and decode data reports from Chainlink Data Streams in your TypeScript applications."
+ keywords: ["TypeScript SDK", "JavaScript", "Cryptocurrency", "API Tutorial", "Data Streams", "Market Data"]
+---
+
+import { Aside, CopyText, PageTabs } from "@components"
+import DataStreams from "@features/data-streams/common/DataStreams.astro"
+
+
+
+
+
+In this tutorial, you'll learn how to use the [Data Streams SDK](/data-streams/reference/data-streams-api/ts-sdk) for TypeScript to fetch and decode [reports](/data-streams/reference/report-schema-overview) from the Data Streams Aggregation Network. You'll set up your TypeScript project, retrieve reports, decode them, and log their attributes.
+
+
+
+## Requirements
+
+- **Git**: Make sure you have Git installed. You can check your current version by running 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.
+- **Node.js**: Make sure you have Node.js 20.0 or higher. You can check your current version by running in your terminal and download the latest version from the official [Node.js website](https://nodejs.org/) if necessary.
+- **TypeScript**: Make sure you have TypeScript 5.3 or higher. You can check your current version by running in your terminal and install or update TypeScript by running if necessary.
+- **API Credentials**: Access to Data Streams 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.
+
+## Tutorial
+
+You'll start with the set up of your TypeScript project, installing the SDK and pasting example code. This will let you decode reports for both single and multiple [streams](/data-streams/crypto-streams), logging their attributes to your terminal.
+
+### Set up your TypeScript project
+
+1. Create a new directory for your project and navigate to it:
+
+ ```bash
+ mkdir my-data-streams-project
+ cd my-data-streams-project
+ ```
+
+1. Initialize a new Node.js project:
+
+ ```bash
+ npm init -y
+ ```
+
+1. Install the TypeScript SDK and other required packages:
+
+ ```bash
+ npm install @chainlink/data-streams-sdk dotenv
+ npm install -D tsx
+ ```
+
+1. Set your API credentials:
+
+ Option 1 - Environment variables:
+
+ ```bash
+ export API_KEY="your_api_key_here"
+ export USER_SECRET="your_user_secret_here"
+ ```
+
+ Option 2 - `.env` file:
+
+ ```bash
+ # Create .env file
+ touch .env
+
+ # Add your credentials
+ API_KEY="your_api_key_here"
+ USER_SECRET="your_user_secret_here"
+ ```
+
+### Fetch and decode a report with a single stream
+
+1. Create a new new TypeScript file, `singleStream.ts`, in your project directory:
+
+ ```bash
+ touch singleStream.ts
+ ```
+
+1. Insert the following code example and save your `singleStream.ts` file:
+
+ ```typescript
+ import { createClient, decodeReport, LogLevel, getReportVersion, formatReport } from "@chainlink/data-streams-sdk"
+ import "dotenv/config"
+
+ async function main() {
+ if (process.argv.length < 3) {
+ console.error("Please provide a feed ID as an argument")
+ console.error(
+ "Example: npx tsx singleStream.ts 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782"
+ )
+ process.exit(1)
+ }
+
+ const feedId = process.argv[2]
+ const version = getReportVersion(feedId)
+
+ try {
+ const config = {
+ apiKey: process.env.API_KEY || "YOUR_API_KEY",
+ userSecret: process.env.USER_SECRET || "YOUR_USER_SECRET",
+ endpoint: "https://api.testnet-dataengine.chain.link",
+ wsEndpoint: "wss://ws.testnet-dataengine.chain.link",
+ // Comment to disable SDK logging:
+ logging: {
+ logger: console,
+ logLevel: LogLevel.INFO,
+ },
+ }
+
+ const client = createClient(config)
+ console.log(`\nFetching latest report for feed ${feedId} (${version})...\n`)
+
+ // Get raw report data
+ const report = await client.getLatestReport(feedId)
+ console.log(`Raw Report Blob: ${report.fullReport}`)
+
+ // Decode the report
+ const decodedData = decodeReport(report.fullReport, report.feedID)
+
+ // Combine decoded data with report metadata
+ const decodedReport = {
+ ...decodedData,
+ feedID: report.feedID,
+ validFromTimestamp: report.validFromTimestamp,
+ observationsTimestamp: report.observationsTimestamp,
+ }
+ console.log(formatReport(decodedReport, version))
+ } catch (error) {
+ if (error instanceof Error) {
+ console.error("Error:", error.message)
+ } else {
+ console.error("Unknown error:", error)
+ }
+ process.exit(1)
+ }
+ }
+
+ main()
+ ```
+
+
+
+1. Read from a [testnet crypto stream](/data-streams/crypto-streams?page=1&testnetPage=1#testnet-crypto-streams). The below example executes the application, reading from the `ETH/USD` crypto stream:
+
+ ```bash
+ npx tsx singleStream.ts 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
+ ```
+
+ Expect output similar to the following in your terminal:
+
+ ```bash
+ Fetching latest report for feed 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 (V3)...
+
+ [2025-09-23T00:09:49.042Z] [DataStreams] Request successful: GET https://api.testnet-dataengine.chain.link/api/v1/reports/latest?feedID=0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 - 200
+ Raw Report Blob: 0x00090d9e8d96765a0c49e03a6ae05c82e8f8de70cf179baa632f18313e54bd690000000000000000000000000000000000000000000000000000000001f6f486000000000000000000000000000000000000000000000000000000030000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba7820000000000000000000000000000000000000000000000000000000068d1e54c0000000000000000000000000000000000000000000000000000000068d1e54c00000000000000000000000000000000000000000000000000004539f757bc7c0000000000000000000000000000000000000000000000000034754304206ea30000000000000000000000000000000000000000000000000000000068f9724c0000000000000000000000000000000000000000000000e3e84d950bcd8d80000000000000000000000000000000000000000000000000e3e48f23626b5660000000000000000000000000000000000000000000000000e3eb7a12d8af1b00000000000000000000000000000000000000000000000000000000000000000002e7c71643e93efb8e759b1d1a8826579853d3aa2c96f59a2813e833a374c786f8f13a497a753af14c6b7329f704f148779b20aae62ed450167c61b9b5d8fcb0e100000000000000000000000000000000000000000000000000000000000000024905f1b4a6313246988a33d2aa923e3023065bbc8c874956aa5df25ec8b7b3e918a25b251713158aae6be85a188c1292e6b5288f2f96e75d632c4e6b659dfa53
+
+ Report Metadata:
+ Feed ID: 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
+ Valid From: 1758586188
+ Observations: 1758586188
+
+ Decoded Data:
+ Native Fee: 76115265174652
+ LINK Fee: 14765629481447075
+ Expires At: 1761178188
+ Price: 4204150104000000000000
+ Bid Price: 4203880326000000000000
+ Ask Price: 4204378800000000000000
+ --------------------------------------------------
+ ```
+
+ Your application has successfully fetched and decoded data for both streams.
+
+ [Learn more about the decoded report details](#decoded-report-details).
+
+### Fetch and decode reports for multiple streams
+
+1. Create a new TypeScript file, `multipleStreams.ts`, in your project directory:
+
+ ```bash
+ touch multipleStreams.ts
+ ```
+
+1. Insert the following code example in your `multipleStreams.ts` file:
+
+ ```typescript
+ import { createClient, decodeReport, LogLevel, getReportVersion, formatReport } from "@chainlink/data-streams-sdk"
+ import "dotenv/config"
+
+ async function main() {
+ if (process.argv.length < 3) {
+ console.error("Please provide feed IDs as arguments")
+ console.error("Get latest reports for multiple feeds:")
+ console.error(" npx tsx multipleStreams.ts [feedID3...]")
+ console.error("\nExample:")
+ console.error(
+ " npx tsx multipleStreams.ts 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 0x00036fe43f87884450b4c7e093cd5ed99cac6640d8c2000e6afc02c8838d0265"
+ )
+ process.exit(1)
+ }
+
+ const feedIds = process.argv.slice(2)
+
+ try {
+ const config = {
+ apiKey: process.env.API_KEY || "YOUR_API_KEY",
+ userSecret: process.env.USER_SECRET || "YOUR_USER_SECRET",
+ endpoint: "https://api.testnet-dataengine.chain.link",
+ wsEndpoint: "wss://ws.testnet-dataengine.chain.link",
+ // Comment to disable SDK logging:
+ logging: {
+ logger: console,
+ logLevel: LogLevel.INFO,
+ },
+ }
+
+ const client = createClient(config)
+ console.log(`\nFetching latest reports for ${feedIds.length} feed(s):`)
+ feedIds.forEach((feedId) => {
+ const version = getReportVersion(feedId)
+ console.log(`- ${feedId} (${version})`)
+ })
+ console.log()
+
+ // Get latest reports for each feed ID
+ const reports = []
+ for (const feedId of feedIds) {
+ try {
+ const report = await client.getLatestReport(feedId)
+ reports.push(report)
+ } catch (error) {
+ console.error(`Failed to get report for ${feedId}:`, error)
+ continue
+ }
+ }
+
+ console.log(`Found ${reports.length} reports:\n`)
+
+ // Process reports
+ reports.forEach((report, index) => {
+ const version = getReportVersion(report.feedID)
+ console.log(`Raw Report Blob #${index + 1}: ${report.fullReport}`)
+
+ try {
+ // Decode the report
+ const decodedData = decodeReport(report.fullReport, report.feedID)
+
+ // Combine decoded data with report metadata
+ const decodedReport = {
+ ...decodedData,
+ feedID: report.feedID,
+ validFromTimestamp: report.validFromTimestamp,
+ observationsTimestamp: report.observationsTimestamp,
+ }
+ console.log(formatReport(decodedReport, version))
+ } catch (error) {
+ console.error(`Failed to decode report for ${report.feedID}:`, error)
+ }
+ })
+ } catch (error) {
+ if (error instanceof Error) {
+ console.error("Error:", error.message)
+ } else {
+ console.error("Unknown error:", error)
+ }
+ process.exit(1)
+ }
+ }
+
+ main()
+ ```
+
+1. Before running the example, verify that your API credentials are still set in your current terminal session:
+
+ ```bash
+ echo $API_KEY
+ echo $API_SECRET
+ ```
+
+ If the commands above don't show your credentials, set them again:
+
+ ```bash
+ export API_KEY=""
+ export USER_SECRET=""
+ ```
+
+1. Read from two testnet crypto streams (ETH/USD and LINK/USD) by running:
+
+ ```bash
+ npx tsx multipleStreams.ts 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 0x00036fe43f87884450b4c7e093cd5ed99cac6640d8c2000e6afc02c8838d0265
+ ```
+
+ Expect to see the output below in your terminal:
+
+ ```bash
+ [2025-09-24T01:50:28.313Z] [DataStreams] Data Streams client initialized
+
+ Fetching latest report for feed 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 (V3)...
+
+ [2025-09-24T01:50:28.607Z] [DataStreams] Request successful: GET https://api.testnet-dataengine.chain.link/api/v1/reports/latest?feedID=0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782 - 200
+ Raw Report Blob: 0x00090d9e8d96765a0c49e03a6ae05c82e8f8de70cf179baa632f18313e54bd690000000000000000000000000000000000000000000000000000000001fb09db000000000000000000000000000000000000000000000000000000030000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba7820000000000000000000000000000000000000000000000000000000068d34e640000000000000000000000000000000000000000000000000000000068d34e64000000000000000000000000000000000000000000000000000045686a2caed300000000000000000000000000000000000000000000000000347613062ce6c40000000000000000000000000000000000000000000000000000000068fadb640000000000000000000000000000000000000000000000e34fc8e3afa8f400000000000000000000000000000000000000000000000000e34cf02d97047e60000000000000000000000000000000000000000000000000e3533bbd1e9ba3400000000000000000000000000000000000000000000000000000000000000000021ae965e613bfb4580ea819f8c12736562222e515b412054c49ec77ded163d9ee4493fb7dfb713181ea1a0d4e1a7fc4b7a3618484f9c989c4262c201e749df2cd000000000000000000000000000000000000000000000000000000000000000217c165a50d34910db8667c1229128ea4110fba082eb0308b75282fffdb594f68467797ce8a8b515f8e3ab08e4723a1fe1a9cfa5079968cd4bb7a9ec1a7a943cc
+
+ Report Metadata:
+ Feed ID: 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
+ Valid From: 1758678628
+ Observations: 1758678628
+
+ Decoded Data:
+ Native Fee: 76314760228563
+ LINK Fee: 14766522869016260
+ Expires At: 1761270628
+ Price: 4193160000000000000000
+ Bid Price: 4192954886000000000000
+ Ask Price: 4193408500000000000000
+ --------------------------------------------------
+ ```
+
+### Decoded report details
+
+The decoded [crypto v3 report](/data-streams/reference/report-schema-v3) 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 | `1734216283` | The timestamp indicating when the data was captured. |
+| Benchmark Price | `3865052126782320350000` | The observed price in the report, with 18 decimals. For readability: `3,865.0521267823204` USD per ETH. |
+| Bid | `3864985478146740000000` | The highest price a buyer is willing to pay for an asset, with 18 decimals. For readability: `3,864.9854781467400` USD per ETH. Learn more about the [Bid price](/data-streams/concepts/liquidity-weighted-prices). (For [DEX State Price streams](/data-streams/concepts/dex-state-price-streams), this value equals `Benchmark Price`.) |
+| Ask | `3865140837060103650000` | The lowest price a seller is willing to accept for an asset, with 18 decimals. For readability: `3,865.1408370601037` USD per ETH. Learn more about the [Ask price](/data-streams/concepts/liquidity-weighted-prices). (For [DEX State Price streams](/data-streams/concepts/dex-state-price-streams), this value equals `Benchmark Price`.) |
+| Valid From Timestamp | `1734216283` | The start validity timestamp for the report, indicating when the data becomes relevant. |
+| Expires At | `1734302683` | The expiration timestamp of the report, indicating the point at which the data becomes outdated. |
+| Link Fee | `3379350941986000` | The fee to pay in LINK tokens for the onchain verification of the report data. With 18 decimals. For readability: `0.03379350941986` LINK. **Note:** This example fee is not indicative of actual fees. |
+| Native Fee | `25872872271800` | 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
+
+In this tutorial, you logged and decoded the `full_report` payloads to extract the report data. However, in a production environment, you should verify the data to ensure its integrity and authenticity.
+
+Refer to the [Verify report data onchain](/data-streams/tutorials/evm-onchain-report-verification) tutorial to learn more.
+
+## Explanation
+
+### Initializing the client and configuration
+
+The Data Streams TypeScript client is initialized in two steps:
+
+1. Configure the client with a config object:
+
+```typescript
+const config = {
+ apiKey: process.env.API_KEY || "YOUR_API_KEY",
+ userSecret: process.env.USER_SECRET || "YOUR_USER_SECRET",
+ endpoint: "https://api.testnet-dataengine.chain.link",
+ wsEndpoint: "wss://ws.testnet-dataengine.chain.link",
+ // Optional logging:
+ logging: {
+ logger: console,
+ logLevel: LogLevel.INFO,
+ },
+}
+```
+
+The configuration requires:
+
+- `apiKey` and `userSecret` for authentication (required)
+- `endpoint` for the API endpoint (required)
+- `logging` for debugging and error tracking (optional)
+
+See the [SDK Reference](/data-streams/reference/data-streams-api/ts-sdk) page for more configuration options.
+
+2. Create the client with `createClient`:
+
+```typescript
+const client = createClient(config)
+```
+
+The client handles:
+
+- Authentication with HMAC signatures
+- Connection management and timeouts
+- Error handling and retries
+
+### Fetching reports
+
+The TypeScript SDK provides two main methods to fetch reports:
+
+1. Latest report for a single stream with `getLatestReport`:
+
+```typescript
+const report = await client.getLatestReport(feedId)
+```
+
+- Takes a feed ID string
+- 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 by calling `getLatestReport` in a loop:
+
+```typescript
+for (const feedId of feedIds) {
+ const report = await client.getLatestReport(feedId)
+ reports.push(report)
+}
+```
+
+- Takes an array of feed ID strings
+- Calls `getLatestReport` for each feed ID individually
+- Returns the most recent data for each stream
+- Useful for monitoring multiple assets simultaneously
+- Each request gets the latest available data without timestamp constraints
+
+Each API request automatically:
+
+- Handles authentication with API credentials
+- Manages request timeouts via the Node/SDK configuration
+- Processes responses into structured types
+
+### Decoding reports
+
+Reports are decoded in two steps using the TypeScript SDK helper functions:
+
+1. Report decoding with `decodeReport` (auto-detects report version by feed ID):
+
+```typescript
+const decodedData = decodeReport(report.fullReport, report.feedID)
+```
+
+This step:
+
+1. Takes the raw `fullReport` bytes/string from the response
+2. Uses the report schema that matches the feed (SDK detects version)
+3. Validates the format and decodes into a structured object
+4. Returns decoded data that can be combined with report metadata and formatted using `formatReport()`
+
+For more details, see the [Report Format section of the SDK Reference](/data-streams/reference/data-streams-api/ts-sdk#report-format).
+
+### Error handling
+
+The TypeScript examples use standard try/catch patterns and optional timeouts:
+
+1. Request timeouts / cancellation
+
+Use your application's timeout/cancellation mechanism (for example, AbortController) when making requests to the SDK or wrap calls in a manual timeout.
+
+2. Error checking
+
+```typescript
+try {
+ const report = await client.getLatestReport(feedId)
+} catch (err) {
+ console.error("Failed to fetch report:", err)
+ process.exit(1) // fatal error
+}
+```
+
+- Fatal errors (client creation, missing credentials) typically exit the process
+- Non-fatal errors (single report decode) can be logged and skipped when processing multiple feeds
+- All errors should be logged with context for easier debugging
+
+Learn more about SDK error handling in the [SDK Reference](/data-streams/reference/data-streams-api/ts-sdk#error-handling).
+
+3. SDK logging
+
+The SDK can log requests and responses when `logging` is enabled in the config. In the example above we pass `console` as the logger and set `LogLevel.INFO`.
+
+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.
+
+For more information about SDK logging configuration and monitoring options, see the [SDK Reference](/data-streams/reference/data-streams-api/ts-sdk#observability-logs--metrics).
+
+> > > > > > > c98d3598 (draft ts-sdk-fetch)
diff --git a/src/content/data-streams/tutorials/ts-sdk-stream.mdx b/src/content/data-streams/tutorials/ts-sdk-stream.mdx
new file mode 100644
index 00000000000..61ef2c1b33b
--- /dev/null
+++ b/src/content/data-streams/tutorials/ts-sdk-stream.mdx
@@ -0,0 +1,447 @@
+---
+section: dataStreams
+date: Last Modified
+title: "Stream and decode Data Streams reports via WebSocket using the TypeScript SDK"
+metadata:
+ title: "Stream Real-time Data Streams Reports with TypeScript SDK | WebSocket Tutorial"
+ description: "Learn how to use the TypeScript SDK to stream and decode real-time data streams reports via WebSocket connections from Chainlink Data Streams."
+ keywords: ["WebSocket", "TypeScript SDK", "JavaScript", "Real-time", "Streaming", "Data Streams"]
+whatsnext:
+ {
+ "Learn how to verify your data onchain": "/data-streams/reference/data-streams-api/onchain-verification",
+ "Find the list of available Streams and view their schemas": "/data-streams/reference/report-schema-overview",
+ }
+---
+
+import { Aside, CopyText, PageTabs } from "@components"
+import DataStreams from "@features/data-streams/common/DataStreams.astro"
+
+
+
+
+
+In this tutorial, you'll learn how to use the [Data Streams SDK](/data-streams/reference/data-streams-api/ts-sdk) for TypeScript to subscribe to real-time [reports](/data-streams/reference/report-schema-overview) via a [WebSocket connection](/data-streams/reference/data-streams-api/interface-ws). You'll set up your TypeScript project, listen for real-time reports from the Data Streams Aggregation Network, decode the report data, and log their attributes to your terminal.
+
+
+
+## Requirements
+
+- **Git**: Make sure you have Git installed. You can check your current version by running 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.
+- **Node.js**: Make sure you have Node.js 20.0 or higher. You can check your current version by running in your terminal and download the latest version from the official [Node.js website](https://nodejs.org/) if necessary.
+- **TypeScript**: Make sure you have TypeScript 5.3 or higher. You can check your current version by running in your terminal and install or update TypeScript by running if necessary.
+- **API Credentials**: Access to Data Streams 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.
+
+## Tutorial
+
+First, you'll set up a basic TypeScript project, installing the SDK and pasting example code. This will let you stream reports for [streams](/data-streams/crypto-streams), logging their attributes to your terminal.
+
+### Set up your TypeScript project
+
+1. Create a new directory for your project and navigate to it:
+
+ ```bash
+ mkdir my-data-streams-project
+ cd my-data-streams-project
+ ```
+
+1. Initialize a new Node.js project:
+
+ ```bash
+ npm init -y
+ ```
+
+1. Install the TypeScript SDK and other required packages:
+
+ ```bash
+ npm install @chainlink/data-streams-sdk dotenv
+ npm install -D tsx
+ ```
+
+1. Set your API credentials:
+
+ Option 1 - Environment variables:
+
+ ```bash
+ export API_KEY="your_api_key_here"
+ export USER_SECRET="your_user_secret_here"
+ ```
+
+ Option 2 - `.env` file:
+
+ ```bash
+ # Create .env file
+ touch .env
+
+ # Add your credentials
+ API_KEY="your_api_key_here"
+ USER_SECRET="your_user_secret_here"
+ ```
+
+### Establish a WebSocket connection and listen for real-time reports
+
+1. Create a new TypeScript file, `stream.ts`, in your project directory:
+
+ ```bash
+ touch stream.ts
+ ```
+
+1. Insert the following code example and save your `stream.ts` file:
+
+ ```typescript
+ import { createClient, LogLevel, decodeReport, getReportVersion, formatReport } from "@chainlink/data-streams-sdk"
+ import "dotenv/config"
+
+ async function main() {
+ if (process.argv.length < 3) {
+ console.error("Please provide one or more feed IDs as arguments")
+ console.error("\nExamples:")
+ console.error(" Single feed:")
+ console.error(" npx tsx stream.ts 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782")
+ console.error(" Multiple feeds:")
+ console.error(
+ " npx tsx stream.ts 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782,0x00036fe43f87884450b4c7e093cd5ed99cac6640d8c2000e6afc02c8838d0265"
+ )
+ process.exit(1)
+ }
+
+ const feedIds = process.argv[2].split(",")
+
+ console.log("Chainlink Data Streams - Report Streaming")
+ console.log("=".repeat(60))
+ console.log(`š Feeds: ${feedIds.length} feed(s)`)
+ console.log("=".repeat(60))
+
+ try {
+ const client = createClient({
+ apiKey: process.env.API_KEY || "YOUR_API_KEY",
+ userSecret: process.env.USER_SECRET || "YOUR_USER_SECRET",
+ endpoint: "https://api.testnet-dataengine.chain.link",
+ wsEndpoint: "wss://ws.testnet-dataengine.chain.link",
+
+ // Comment to disable SDK logging:
+ logging: {
+ logger: console,
+ logLevel: LogLevel.INFO,
+ enableConnectionDebug: false, // Enable WebSocket ping/pong and connection state logs (logLevel should be DEBUG)
+ },
+ })
+
+ let reportCount = 0
+
+ // Create stream with custom options
+ const stream = client.createStream(feedIds, {
+ maxReconnectAttempts: 10,
+ reconnectInterval: 3000,
+ })
+
+ // Event: Process incoming reports
+ stream.on("report", (report) => {
+ reportCount++
+
+ try {
+ console.log(`\nš Report #${reportCount} - ${new Date().toISOString()}`)
+
+ // Show raw report blob
+ console.log(`\nRaw Report Blob: ${report.fullReport}`)
+
+ // Decode the report
+ const decodedData = decodeReport(report.fullReport, report.feedID)
+ const version = getReportVersion(report.feedID)
+
+ // Combine decoded data with report metadata
+ const decodedReport = {
+ ...decodedData,
+ feedID: report.feedID,
+ validFromTimestamp: report.validFromTimestamp,
+ observationsTimestamp: report.observationsTimestamp,
+ }
+
+ console.log(formatReport(decodedReport, version))
+ } catch (error) {
+ console.error(`ā Error processing report: ${error instanceof Error ? error.message : error}`)
+ }
+
+ // Display stats every 5 reports
+ if (reportCount % 5 === 0) {
+ const stats = stream.getMetrics()
+ console.log(
+ `\nš Stats: ${stats.accepted} reports | ${stats.activeConnections}/${stats.configuredConnections} connections`
+ )
+ }
+ })
+
+ // Event: Handle errors
+ stream.on("error", (error) => {
+ console.error(`\nā Error: ${error.message}`)
+
+ if (error.message.includes("authentication")) {
+ console.error("š” Check your API_KEY and USER_SECRET environment variables")
+ }
+ })
+
+ // Event: Handle disconnections
+ stream.on("disconnected", () => {
+ console.log("\nš“ Stream disconnected - reconnecting...")
+ })
+
+ // Event: Monitor reconnections
+ stream.on("reconnecting", (info: { attempt: number; delayMs: number; origin?: string; host?: string }) => {
+ console.log(
+ `š Reconnecting... attempt ${info.attempt} in ~${info.delayMs}ms${info.host ? ` (${info.host})` : ""}`
+ )
+ })
+
+ console.log("ā³ Connecting...\n")
+ await stream.connect()
+ console.log("ā Connected! Listening for reports...\n")
+
+ // Graceful shutdown
+ const shutdown = async () => {
+ console.log("\nš Shutting down...")
+ await stream.close()
+ console.log("ā Shutdown complete")
+ process.exit(0)
+ }
+
+ process.on("SIGINT", shutdown)
+ process.on("SIGTERM", shutdown)
+ } catch (error) {
+ console.error("ā Failed to start stream:", error instanceof Error ? error.message : error)
+ process.exit(1)
+ }
+ }
+
+ main()
+ ```
+
+
+
+1. Subscribe to a [testnet crypto stream](/data-streams/crypto-streams?page=1&testnetPage=1#testnet-crypto-streams). The below example executes the application, subscribing to the `ETH/USD` crypto stream:
+
+ ```bash
+ npx tsx stream.ts 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
+ ```
+
+ Expect output similar to the following in your terminal:
+
+ ```bash
+ Chainlink Data Streams - Report Streaming
+ ============================================================
+ š Feeds: 1 feed(s)
+ ============================================================
+ [2025-09-24T01:52:36.464Z] [DataStreams] Data Streams client initialized
+ [2025-09-24T01:52:36.465Z] [DataStreams] Initializing stream in single mode
+ [2025-09-24T01:52:36.465Z] [DataStreams] Stream created successfully for 1 feed(s)
+ ā³ Connecting...
+
+ [2025-09-24T01:52:36.465Z] [DataStreams] Connecting stream in single mode
+ [2025-09-24T01:52:36.465Z] [DataStreams] Initializing in single connection mode { origin: 'ws.testnet-dataengine.chain.link' }
+ [2025-09-24T01:52:36.919Z] [DataStreams] Connection conn-0 established to ws.testnet-dataengine.chain.link {
+ connectionId: 'conn-0',
+ host: 'ws.testnet-dataengine.chain.link',
+ oldState: 'connecting',
+ newState: 'connected',
+ reason: 'WebSocket connection established'
+ }
+ [2025-09-24T01:52:36.921Z] [DataStreams] Stream connected successfully with 1 origins: wss://ws.testnet-dataengine.chain.link
+ ā Connected! Listening for reports...
+
+
+ š Report #1 - 2025-09-24T01:52:37.639Z
+
+ Raw Report Blob: 0x00090d9e8d96765a0c49e03a6ae05c82e8f8de70cf179baa632f18313e54bd690000000000000000000000000000000000000000000000000000000001fb0b3d000000000000000000000000000000000000000000000000000000030000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba7820000000000000000000000000000000000000000000000000000000068d34ee50000000000000000000000000000000000000000000000000000000068d34ee500000000000000000000000000000000000000000000000000004566c7d15bf000000000000000000000000000000000000000000000000000346f5bdd1b7f7f0000000000000000000000000000000000000000000000000000000068fadbe50000000000000000000000000000000000000000000000e3535f4d688742fe400000000000000000000000000000000000000000000000e35216a3ce81ab00000000000000000000000000000000000000000000000000e355718e650ceb8c00000000000000000000000000000000000000000000000000000000000000000264deb1e4d7485843f79f802f8ffd29fa395c45a8f4c10d7771d91fb5c6c7f55bdf3b496949277bdba413cf9a07adf62d4ffac8d04572455c8707a578eec7988f000000000000000000000000000000000000000000000000000000000000000221d03f390a3a8bf14406a5026bca8a569908abd0e3bfc1152e0ee94cf8087b29648cffd6e505f392678ad3c2488862dc6016755aec3076e64fa68d13705a5980
+
+ Report Metadata:
+ Feed ID: 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
+ Valid From: 1758678757
+ Observations: 1758678757
+
+ Decoded Data:
+ Native Fee: 76307741367280
+ LINK Fee: 14759139131228031
+ Expires At: 1761270757
+ Price: 4193418510271345000000
+ Bid Price: 4193326000000000000000
+ Ask Price: 4193567763462320000000
+ --------------------------------------------------
+
+ š Report #2 - 2025-09-24T01:52:38.352Z
+
+ Raw Report Blob: 0x00090d9e8d96765a0c49e03a6ae05c82e8f8de70cf179baa632f18313e54bd690000000000000000000000000000000000000000000000000000000001fb0b3f000000000000000000000000000000000000000000000000000000030000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba7820000000000000000000000000000000000000000000000000000000068d34ee60000000000000000000000000000000000000000000000000000000068d34ee600000000000000000000000000000000000000000000000000004567035aadb500000000000000000000000000000000000000000000000000346f5006b572370000000000000000000000000000000000000000000000000000000068fadbe60000000000000000000000000000000000000000000000e354601f8dd7842d400000000000000000000000000000000000000000000000e35343330ef5aa80000000000000000000000000000000000000000000000000e3576b7b7e0d95bc0000000000000000000000000000000000000000000000000000000000000000029bbebb9390dfd84074ef0078b3b354a8c3f53915d24b664095b4360b20e495cfc1ee156fb32ffae29390a891b905b96fec0e949dbca19b7eded60a2178a0b7570000000000000000000000000000000000000000000000000000000000000002119306af79fb631fe3d281475b32e9e2c293fd6b544d4f5d44d74d9827d8897729c2bc6d5df3033d6b90aeb22df31f484f5ed7da9602c790213d3e12144544e1
+
+ Report Metadata:
+ Feed ID: 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
+ Valid From: 1758678758
+ Observations: 1758678758
+
+ Decoded Data:
+ Native Fee: 76308740222389
+ LINK Fee: 14759088289575479
+ Expires At: 1761270758
+ Price: 4193490798923085000000
+ Bid Price: 4193410600000000000000
+ Ask Price: 4193710169017200000000
+ --------------------------------------------------
+
+ š Report #3 - 2025-09-24T01:52:39.274Z
+
+ Raw Report Blob: 0x00090d9e8d96765a0c49e03a6ae05c82e8f8de70cf179baa632f18313e54bd690000000000000000000000000000000000000000000000000000000001fb0b42000000000000000000000000000000000000000000000000000000030000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba7820000000000000000000000000000000000000000000000000000000068d34ee70000000000000000000000000000000000000000000000000000000068d34ee70000000000000000000000000000000000000000000000000000456689e0e86300000000000000000000000000000000000000000000000000346d7b2d006b3a0000000000000000000000000000000000000000000000000000000068fadbe70000000000000000000000000000000000000000000000e355ee07f0ab7f00000000000000000000000000000000000000000000000000e353c9352421f6e2000000000000000000000000000000000000000000000000e3565e1f7be6e49700000000000000000000000000000000000000000000000000000000000000000245ddf834b20cdd13c559fdd131c27f3c52d38ba6a456d6064a64269b703bc2012d0ffbb4ab3df623c0bdfba83004ef4db50ea351314b648153d2f6002f78cb4e00000000000000000000000000000000000000000000000000000000000000026a6bbed7e57969d56e6485682afc481f8f8127f292e4bd300f6bb0a57b77b21a2ca0e3338ba16b0afbbae567fc4a728c4b95c2092169f412ae7b8fc53c81342a
+
+ Report Metadata:
+ Feed ID: 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782
+ Valid From: 1758678759
+ Observations: 1758678759
+
+ Decoded Data:
+ Native Fee: 76306702198883
+ LINK Fee: 14757074592361274
+ Expires At: 1761270759
+ Price: 4193602800000000000000
+ Bid Price: 4193448319936840000000
+ Ask Price: 4193634351084156000000
+ --------------------------------------------------
+ [...additional reports...]
+ ```
+
+ Your application has successfully subscribed to the report data.
+
+ [Learn more about the decoded report details](#decoded-report-details).
+
+### 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` | `1758588884` | The timestamp indicating when the data was captured. |
+| `Benchmark Price` | `4195298740000000000000` | The observed price in the report, with 18 decimals. For readability: `4,195.29874` USD per ETH. |
+| `Bid` | `4194910430000000000000` | The highest price a buyer is willing to pay for an asset, with 18 decimals. For readability: `4,194.91043` USD per ETH. Learn more about the [Bid price](/data-streams/concepts/liquidity-weighted-prices). (For [DEX State Price streams](/data-streams/concepts/dex-state-price-streams), this value equals `Benchmark Price`.) |
+| `Ask` | `4195448050000000000000` | The lowest price a seller is willing to accept for an asset, with 18 decimals. For readability: `4,195.44805` USD per ETH. Learn more about the [Ask price](/data-streams/concepts/liquidity-weighted-prices). (For [DEX State Price streams](/data-streams/concepts/dex-state-price-streams), this value equals `Benchmark Price`.) |
+| `Valid From Timestamp` | `1758588884` | The start validity timestamp for the report, indicating when the data becomes relevant. |
+| `Expires At` | `1761180884` | The expiration timestamp of the report, indicating the point at which the data becomes outdated. |
+| `Link Fee` | `14805490063735767` | The fee to pay in LINK tokens for the onchain verification of the report data, with 18 decimals. For readability: `0.014805490063735767` LINK. **Note:** This example fee is not indicative of actual fees. |
+| `Native Fee` | `76275680556912` | 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. |
+
+For descriptions and data types of other report schemas, see the [Report Schema Overview](/data-streams/reference/report-schema-overview).
+
+### Subscribing to multiple streams
+
+You can subscribe to multiple streams by providing additional stream IDs as command-line arguments:
+
+```bash
+npx tsx stream.ts 0x000359843a543ee2fe414dc14c7e7920ef10f4372990b79d6361cdc0dd1ba782,0x00036fe43f87884450b4c7e093cd5ed99cac6640d8c2000e6afc02c8838d0265
+```
+
+This will subscribe to both ETH/USD and BTC/USD streams.
+
+### High Availability (HA) mode
+
+
+
+The example above demonstrates streaming data from a single crypto stream. For production environments, especially when subscribing to multiple streams, it's recommended to enable [High Availability (HA) mode](/data-streams/reference/data-streams-api/ts-sdk#high-availability-mode).
+
+High Availability (HA) mode creates multiple WebSocket connections to different origin endpoints for improved reliability. When HA mode is enabled, the Stream will maintain at least 2 concurrent connections to different instances to ensure high availability, fault tolerance and minimize the risk of report gaps.
+
+#### Enabling HA mode
+
+To enable HA mode in your streaming application, make these changes to the basic example:
+
+```typescript
+// ... existing code ...
+
+const client = createClient({
+ apiKey: process.env.API_KEY || "YOUR_API_KEY",
+ userSecret: process.env.USER_SECRET || "YOUR_USER_SECRET",
+ endpoint: "https://api.dataengine.chain.link", // Mainnet endpoint
+ wsEndpoint: "wss://ws.dataengine.chain.link", // Single endpoint (mainnet only)
+ haMode: true, // Enable High Availability mode
+
+ // Optional: Advanced connection monitoring with origin tracking
+ connectionStatusCallback: (isConnected, host, origin) => {
+ const timestamp = new Date().toISOString().substring(11, 19)
+ const status = isConnected ? "š¢ UP" : "š“ DOWN"
+ console.log(`[${timestamp}] ${status} ${host}${origin || ""}`)
+
+ // Example: Send alerts for specific origins
+ if (!isConnected && origin) {
+ console.warn(`ā ļø Alert: Origin ${origin} on ${host} went offline`)
+ }
+ },
+
+ logging: {
+ logger: console,
+ logLevel: LogLevel.INFO,
+ },
+})
+
+// ... existing code ...
+```
+
+When `haMode` is `true`, the SDK automatically discovers multiple origin endpoints behind the single URL and establishes separate connections to each origin. You also must use a mainnet endpoint, as HA mode is not currently supported on testnet.
+
+The optional `connectionStatusCallback` can be used to integrate with external monitoring systems. The SDK already provides comprehensive connection logs, so this callback is primarily useful for custom alerting or metrics collection.
+
+See more details about HA mode in the [SDK Reference](/data-streams/reference/data-streams-api/ts-sdk#high-availability-mode).
+
+### Payload for onchain verification
+
+In this tutorial, you logged and decoded the `full_report` payloads to extract the report data. However, in a production environment, you should verify the data to ensure its integrity and authenticity.
+
+Refer to the [Verify report data onchain](/data-streams/tutorials/evm-onchain-report-verification) tutorial to learn more.
+
+## Explanation
+
+### Establishing a WebSocket connection and listening for reports
+
+Your application uses the `createClient` function from the [Data Streams SDK](/data-streams/reference/data-streams-api/ts-sdk) to create a client, then uses `client.createStream()` 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 `createStream` function. This subscription lets the client receive real-time updates whenever new report data is available for the specified streams.
+
+Fore further reference, see the [WebSocket Interface](/data-streams/reference/data-streams-api/interface-ws) section of the SDK Reference.
+
+### Event-driven streaming
+
+The TypeScript SDK uses an event-driven approach for handling streaming data:
+
+- **Connection events**: The [stream emits `connected`, `disconnected`, and `reconnecting` events](/data-streams/reference/data-streams-api/ts-sdk#streaming) to track connection status.
+- **Report events**: When new reports arrive, the `report` [event is triggered](/data-streams/reference/data-streams-api/ts-sdk#streaming) with the decoded report data.
+- **Error handling**: The stream [emits `error` events](/data-streams/reference/data-streams-api/ts-sdk#error-handling) for any issues that occur during streaming.
+- **Metrics**: [The `getMetrics()` method provides](/data-streams/reference/data-streams-api/ts-sdk#metrics-streamgetmetrics) real-time statistics about the stream performance.
+
+### Decoding and processing reports
+
+As data reports arrive via the established WebSocket connection, they are processed in real-time:
+
+- **Automatic decoding**: The SDK's `decodeReport` function automatically [detects the report version](/data-streams/reference/data-streams-api/ts-sdk#report-format) and parses the raw data into a structured format.
+- **Real-time processing**: Each received report triggers the `report` event handler, where you can process, log, or store the decoded data.
+- **Error resilience**: Individual report processing errors don't interrupt the stream, allowing continuous operation.
+
+### 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. The decoded data includes essential information such as benchmark prices, bid/ask spreads, and fee data for onchain verification.
+
+For more information about SDK streaming configuration and advanced options, see the [SDK Reference](/data-streams/reference/data-streams-api/ts-sdk).