From b41bae659e57a573b6f22c7f8d12f3523ba55722 Mon Sep 17 00:00:00 2001 From: Josh Neuroth Date: Wed, 26 Aug 2026 06:34:42 -0400 Subject: [PATCH 1/6] docs(data-streams): add How Report Timestamps Work page Adds a concepts page explaining that reports describe a span of time (validFromTimestamp through observationsTimestamp) rather than an instant, how gaps between reports are absorbed, and how timestamps anchor TWAP stream calculations. Cross-links it from Architecture, Best Practices, and the REST API reference. Co-Authored-By: Claude Opus 5 --- src/config/sidebar.ts | 4 + src/content/data-streams/architecture.mdx | 1 + .../data-streams/concepts/best-practices.mdx | 5 ++ .../how-report-timestamps-work.mdx | 88 +++++++++++++++++++ .../data-streams-api/interface-api.mdx | 2 + 5 files changed, 100 insertions(+) create mode 100644 src/content/data-streams/how-report-timestamps-work.mdx diff --git a/src/config/sidebar.ts b/src/config/sidebar.ts index 7000d697f3f..a9b24b7f3e4 100644 --- a/src/config/sidebar.ts +++ b/src/config/sidebar.ts @@ -1340,6 +1340,10 @@ export const SIDEBAR: Partial> = { title: "Architecture", url: "data-streams/architecture", }, + { + title: "How Report Timestamps Work", + url: "data-streams/how-report-timestamps-work", + }, { title: "Best Practices", url: "data-streams/concepts/best-practices", diff --git a/src/content/data-streams/architecture.mdx b/src/content/data-streams/architecture.mdx index 94667261fd5..4d85cf2d29e 100644 --- a/src/content/data-streams/architecture.mdx +++ b/src/content/data-streams/architecture.mdx @@ -8,6 +8,7 @@ metadata: whatsnext: { "Learn more about the Standard API Implementation": "/data-streams/tutorials/go-sdk-fetch", + "Learn how report timestamps work": "/data-streams/how-report-timestamps-work", "Find the list of available Stream IDs": "/data-streams/crypto-streams", "Find the schema of data to expect from Data Streams reports: Crypto": "/data-streams/reference/report-schema-v3", "Find the schema of data to expect from Data Streams reports: RWA": "/data-streams/reference/report-schema-v8", diff --git a/src/content/data-streams/concepts/best-practices.mdx b/src/content/data-streams/concepts/best-practices.mdx index abf7033cada..880575825f0 100644 --- a/src/content/data-streams/concepts/best-practices.mdx +++ b/src/content/data-streams/concepts/best-practices.mdx @@ -27,6 +27,7 @@ whatsnext: "Learn about Data Streams market hours and schedules": "/data-streams/market-hours", "Learn how to handle market events": "/data-streams/rwa-streams/handling-market-events", "Learn how to handle stock splits": "/data-streams/tokenized-asset-streams/handling-stock-splits", + "Learn how report timestamps work": "/data-streams/how-report-timestamps-work", } --- @@ -51,3 +52,7 @@ For best practices regarding RWA streams: ## Tokenized Assets For best practices regarding stock splits and reverse splits for tokenized assets, please see the [Handling Stock Splits](/data-streams/tokenized-asset-streams/handling-stock-splits) guide. + +## Report Timestamps + +Each report applies to a span of time defined by `validFromTimestamp` and `observationsTimestamp`, and that span isn't always exactly one second wide. Read both fields from each report rather than assuming a fixed cadence or deriving the window from your own clock. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including how gaps between reports are absorbed and how timestamps apply to TWAP streams. diff --git a/src/content/data-streams/how-report-timestamps-work.mdx b/src/content/data-streams/how-report-timestamps-work.mdx new file mode 100644 index 00000000000..75c10488c38 --- /dev/null +++ b/src/content/data-streams/how-report-timestamps-work.mdx @@ -0,0 +1,88 @@ +--- +section: dataStreams +date: "Last Modified" +title: "How Report Timestamps Work" +metadata: + title: "How Chainlink Data Streams Report Timestamps Work | validFromTimestamp and observationsTimestamp" + description: "Learn how Chainlink Data Streams report timestamps define a span of time rather than an instant, how gaps between reports are absorbed, and how timestamps apply to TWAP streams." + keywords: + [ + "Data Streams", + "Timestamps", + "validFromTimestamp", + "observationsTimestamp", + "TWAP", + "Time Weighted Average Price", + "Reports", + ] +whatsnext: + { + "See the REST API reference": "/data-streams/reference/data-streams-api/interface-api", + "See the WebSocket reference": "/data-streams/reference/data-streams-api/interface-ws", + "Learn about Data Streams architecture": "/data-streams/architecture", + "Review Data Streams best practices": "/data-streams/concepts/best-practices", + } +--- + +import { Aside } from "@components" +import DataStreams from "@features/data-streams/common/DataStreams.astro" + + + +Every Data Streams report carries two timestamps: `validFromTimestamp` and `observationsTimestamp`. Together they describe a span of time rather than a single instant. This page explains how that span is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. + +## Reports are spans, not ticks + +A report doesn't represent a price at an instant. It represents a price over a span of time: + +> From `validFromTimestamp` through `observationsTimestamp`, the price is X. + +- **`validFromTimestamp`** — the floor of the span +- **`observationsTimestamp`** — the ceiling of the span + +Both fields are Unix timestamps in seconds. + +This span can be 1 second wide or several seconds wide, depending on how frequently the Decentralized Oracle Network (DON) can observe the data and generate reports. Spans are contiguous by construction: each one starts the second after the previous one ended. No gaps, no overlaps — every second in time belongs to exactly one report. + +## Understanding real-time transmission + +Say wall-clock time is `12:05:00`. What price is "current" at that instant depends on whether a report exists for it yet. + +**Normal case** + +A report exists with `observationsTimestamp = 12:05:00`. Its window is 1 second wide. You'll receive it slightly after `12:05:00` — typically up to 1-2 seconds later — due to DON consensus and transmission to you. + +**Edge case: no report at that exact second** + +Sometimes there's no report observed with `observationsTimestamp = 12:05:00`. For example: + +- Last report: `observationsTimestamp = 12:04:59` +- Next report: `observationsTimestamp = 12:05:01` + +The next report's window absorbs the gap: its `validFromTimestamp` is `12:05:00`, making its window 2 seconds wide (`12:05:00` → `12:05:01`). + +In this example, the price for `12:05:00` is observed one second later at `12:05:01`. + + + +## How timestamps relate to TWAP streams + +TWAP streams function differently than traditional data reports. A TWAP report is an **aggregated calculation** derived from the underlying reports. + +A TWAP span is anchored to `observationsTimestamp`, not to Unix time. It doesn't pad or extend to hit a round boundary — it slides. + +For example, a 60-second TWAP requested "at `12:05:01`" covers `12:04:01` → `12:05:01`, not `12:04:00` → `12:05:00` or anything else artificially aligned to the clock. + +**Formula:** + +``` +TWAP = (sum of price × duration for each report in the window) / window length in seconds +``` + +- 30-second TWAP → divide by 30 +- 60-second TWAP → divide by 60 + +If a report's window is wider than 1 second (that is, it spans a gap where no intermediate report existed), that report's price is interpolated across the seconds it covers rather than treated as a single point. diff --git a/src/content/data-streams/reference/data-streams-api/interface-api.mdx b/src/content/data-streams/reference/data-streams-api/interface-api.mdx index 815be286a75..66cff20d0b6 100644 --- a/src/content/data-streams/reference/data-streams-api/interface-api.mdx +++ b/src/content/data-streams/reference/data-streams-api/interface-api.mdx @@ -37,6 +37,8 @@ All routes require the following three headers for user authentication: ## API endpoints +Report responses include `validFromTimestamp` and `observationsTimestamp`, which together define the span of time the report's price applies to rather than a single instant. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including what happens when no report exists for a given second. + ### Return a single report at a given timestamp ##### Endpoint From 36f50d7c84d33f581d0d929b18d081752d37577f Mon Sep 17 00:00:00 2001 From: devin distefano Date: Thu, 10 Sep 2026 13:55:34 -0500 Subject: [PATCH 2/6] updates --- .../how-report-timestamps-work.mdx | 16 ++--- src/content/data-streams/llms-full.txt | 71 +++++++++++++++++++ 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/src/content/data-streams/how-report-timestamps-work.mdx b/src/content/data-streams/how-report-timestamps-work.mdx index 75c10488c38..63048202c0b 100644 --- a/src/content/data-streams/how-report-timestamps-work.mdx +++ b/src/content/data-streams/how-report-timestamps-work.mdx @@ -29,20 +29,20 @@ import DataStreams from "@features/data-streams/common/DataStreams.astro" -Every Data Streams report carries two timestamps: `validFromTimestamp` and `observationsTimestamp`. Together they describe a span of time rather than a single instant. This page explains how that span is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. +Every Data Streams report carries two timestamps: -## Reports are spans, not ticks +- **`validFromTimestamp`** — when the report's price _starts being valid_ +- **`observationsTimestamp`** — when the report's price _was last observed_. -A report doesn't represent a price at an instant. It represents a price over a span of time: +Together, they describe a span of time rather than a single instant. Below find information about how that span is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. -> From `validFromTimestamp` through `observationsTimestamp`, the price is X. +## Report Spans -- **`validFromTimestamp`** — the floor of the span -- **`observationsTimestamp`** — the ceiling of the span +A report does not have verified price for a single instant in time. The `validFromTimestamp` marks the beginning of the span, and the `observationsTimestamp` marks the end. -Both fields are Unix timestamps in seconds. +Both fields are Unix timestamps in seconds. [Each report schema](/data-streams/reference/report-schema-overview) contains definitions, including the unit of time, for all fields. -This span can be 1 second wide or several seconds wide, depending on how frequently the Decentralized Oracle Network (DON) can observe the data and generate reports. Spans are contiguous by construction: each one starts the second after the previous one ended. No gaps, no overlaps — every second in time belongs to exactly one report. +The span of time can vary depending on how frequently the Decentralized Oracle Network (DON) can observe the data and generate reports. Spans are contiguous by construction: each one starts the immediately following the previous span. Each report is designed to have no gaps or overlap, with every price interval belonging to exactly one report. ## Understanding real-time transmission diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 17503c5e4fd..8d53fa72142 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -402,6 +402,10 @@ For best practices regarding RWA streams: For best practices regarding stock splits and reverse splits for tokenized assets, please see the [Handling Stock Splits](/data-streams/tokenized-asset-streams/handling-stock-splits) guide. +## Report Timestamps + +Each report applies to a span of time defined by `validFromTimestamp` and `observationsTimestamp`, and that span isn't always exactly one second wide. Read both fields from each report rather than assuming a fixed cadence or deriving the window from your own clock. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including how gaps between reports are absorbed and how timestamps apply to TWAP streams. + --- # Calculated Streams @@ -953,6 +957,71 @@ If you are using Data Streams credentials that were issued outside the self-serv --- +# How Report Timestamps Work +Source: https://docs.chain.link/data-streams/how-report-timestamps-work + + + +Every Data Streams report carries two timestamps: + +- **`validFromTimestamp`** — when the report's price *starts being valid* +- **`observationsTimestamp`** — when the report's price *was last observed*. + +Together, they describe a span of time rather than a single instant. Below find information about how that span is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. + +## Report Spans + +A report does not have verified price for a single instant in time. The `validFromTimestamp` marks the beginning of the span, and the `observationsTimestamp` marks the end. + +Both fields are Unix timestamps in seconds. [Each report schema](/data-streams/reference/report-schema-overview) contains definitions, including the unit of time, for all fields. + +The span of time can vary depending on how frequently the Decentralized Oracle Network (DON) can observe the data and generate reports. Spans are contiguous by construction: each one starts the immediately following the previous span. Each report is designed to have no gaps or overlap, with every price interval belonging to exactly one report. + +## Understanding real-time transmission + +Say wall-clock time is `12:05:00`. What price is "current" at that instant depends on whether a report exists for it yet. + +**Normal case** + +A report exists with `observationsTimestamp = 12:05:00`. Its window is 1 second wide. You'll receive it slightly after `12:05:00` — typically up to 1-2 seconds later — due to DON consensus and transmission to you. + +**Edge case: no report at that exact second** + +Sometimes there's no report observed with `observationsTimestamp = 12:05:00`. For example: + +- Last report: `observationsTimestamp = 12:04:59` +- Next report: `observationsTimestamp = 12:05:01` + +The next report's window absorbs the gap: its `validFromTimestamp` is `12:05:00`, making its window 2 seconds wide (`12:05:00` → `12:05:01`). + +In this example, the price for `12:05:00` is observed one second later at `12:05:01`. + + + +## How timestamps relate to TWAP streams + +TWAP streams function differently than traditional data reports. A TWAP report is an **aggregated calculation** derived from the underlying reports. + +A TWAP span is anchored to `observationsTimestamp`, not to Unix time. It doesn't pad or extend to hit a round boundary — it slides. + +For example, a 60-second TWAP requested "at `12:05:01`" covers `12:04:01` → `12:05:01`, not `12:04:00` → `12:05:00` or anything else artificially aligned to the clock. + +**Formula:** + +``` +TWAP = (sum of price × duration for each report in the window) / window length in seconds +``` + +- 30-second TWAP → divide by 30 +- 60-second TWAP → divide by 60 + +If a report's window is wider than 1 second (that is, it spans a gap where no intermediate report existed), that report's price is interpolated across the seconds it covers rather than treated as a single point. + +--- + # Chainlink Data Streams Source: https://docs.chain.link/data-streams @@ -4395,6 +4464,8 @@ All routes require the following three headers for user authentication: ## API endpoints +Report responses include `validFromTimestamp` and `observationsTimestamp`, which together define the span of time the report's price applies to rather than a single instant. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including what happens when no report exists for a given second. + ### Return a single report at a given timestamp ##### Endpoint From e6a2d83622e384d10297af173e294ca2d6f6196f Mon Sep 17 00:00:00 2001 From: devin distefano Date: Thu, 10 Sep 2026 20:12:32 -0500 Subject: [PATCH 3/6] more updates --- .../how-report-timestamps-work.mdx | 33 ++++++++----------- src/content/data-streams/llms-full.txt | 33 ++++++++----------- 2 files changed, 28 insertions(+), 38 deletions(-) diff --git a/src/content/data-streams/how-report-timestamps-work.mdx b/src/content/data-streams/how-report-timestamps-work.mdx index 63048202c0b..16a127935ec 100644 --- a/src/content/data-streams/how-report-timestamps-work.mdx +++ b/src/content/data-streams/how-report-timestamps-work.mdx @@ -34,7 +34,7 @@ Every Data Streams report carries two timestamps: - **`validFromTimestamp`** — when the report's price _starts being valid_ - **`observationsTimestamp`** — when the report's price _was last observed_. -Together, they describe a span of time rather than a single instant. Below find information about how that span is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. +Together, they describe a span of time rather than a single instant. Below, find information about how that span is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. ## Report Spans @@ -44,37 +44,32 @@ Both fields are Unix timestamps in seconds. [Each report schema](/data-streams/r The span of time can vary depending on how frequently the Decentralized Oracle Network (DON) can observe the data and generate reports. Spans are contiguous by construction: each one starts the immediately following the previous span. Each report is designed to have no gaps or overlap, with every price interval belonging to exactly one report. -## Understanding real-time transmission +## Determining current price -Say wall-clock time is `12:05:00`. What price is "current" at that instant depends on whether a report exists for it yet. +Because each report covers a span rather than an instant, the "current" price at any given moment is the price of the report whose span contains that moment. Whether such a report exists yet depends on how recently the DON observed the data and delivered the report. -**Normal case** +**Normal case: a report exists at that exact moment** -A report exists with `observationsTimestamp = 12:05:00`. Its window is 1 second wide. You'll receive it slightly after `12:05:00` — typically up to 1-2 seconds later — due to DON consensus and transmission to you. +For example, a report exists with `observationsTimestamp = 12:05:00` and a 1-second window. The report is delivered slightly after `12:05:00` (for reports with second-precision timestamps, typically up to 1-2 seconds later) due to DON consensus and transmission. -**Edge case: no report at that exact second** +**Edge case: no report at that exact moment** -Sometimes there's no report observed with `observationsTimestamp = 12:05:00`. For example: +It is possible for no report to be observed with `observationsTimestamp = 12:05:00`. For example: - Last report: `observationsTimestamp = 12:04:59` - Next report: `observationsTimestamp = 12:05:01` -The next report's window absorbs the gap: its `validFromTimestamp` is `12:05:00`, making its window 2 seconds wide (`12:05:00` → `12:05:01`). +The next report's `validFromTimestamp` is `12:05:00`, absorbing the gap and creating a 2-second window (`12:05:00` → `12:05:01`). In this example, the price for `12:05:00` is observed one second later at `12:05:01`. -In this example, the price for `12:05:00` is observed one second later at `12:05:01`. +Because windows can vary in width, **do not assume every report covers exactly one second**. Read `validFromTimestamp` and `observationsTimestamp` from each report rather than deriving the window from the previous report's timestamp or from your own clock. - +## TWAP streams -## How timestamps relate to TWAP streams +Time Weighted Average Price (TWAP) streams report the average price over a rolling window, rather than a single observed price. A TWAP report is an **aggregated calculation** derived from the underlying reports. See the [TWAP report schema](/data-streams/reference/report-schema-v2#time-weighted-average-price-twap) for the full field definitions. -TWAP streams function differently than traditional data reports. A TWAP report is an **aggregated calculation** derived from the underlying reports. +A TWAP window is anchored to the latest observation and moves forward with each new report. Unlike standard streams, it doesn't align to the clock or snap to round numbers. -A TWAP span is anchored to `observationsTimestamp`, not to Unix time. It doesn't pad or extend to hit a round boundary — it slides. - -For example, a 60-second TWAP requested "at `12:05:01`" covers `12:04:01` → `12:05:01`, not `12:04:00` → `12:05:00` or anything else artificially aligned to the clock. +For example, a 60-second TWAP requested "at `12:05:01`" covers `12:04:01` to `12:05:01`. **Formula:** @@ -85,4 +80,4 @@ TWAP = (sum of price × duration for each report in the window) / window length - 30-second TWAP → divide by 30 - 60-second TWAP → divide by 60 -If a report's window is wider than 1 second (that is, it spans a gap where no intermediate report existed), that report's price is interpolated across the seconds it covers rather than treated as a single point. +The TWAP is constructed from underlying reports that fall within its window. Each underlying report normally covers about 1 second, but if a report's window is wider because it absorbed a gap, its price is weighted across the full window covered in the TWAP calculation. diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 8d53fa72142..cef36f955a5 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -967,7 +967,7 @@ Every Data Streams report carries two timestamps: - **`validFromTimestamp`** — when the report's price *starts being valid* - **`observationsTimestamp`** — when the report's price *was last observed*. -Together, they describe a span of time rather than a single instant. Below find information about how that span is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. +Together, they describe a span of time rather than a single instant. Below, find information about how that span is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. ## Report Spans @@ -977,37 +977,32 @@ Both fields are Unix timestamps in seconds. [Each report schema](/data-streams/r The span of time can vary depending on how frequently the Decentralized Oracle Network (DON) can observe the data and generate reports. Spans are contiguous by construction: each one starts the immediately following the previous span. Each report is designed to have no gaps or overlap, with every price interval belonging to exactly one report. -## Understanding real-time transmission +## Determining current price -Say wall-clock time is `12:05:00`. What price is "current" at that instant depends on whether a report exists for it yet. +Because each report covers a span rather than an instant, the "current" price at any given moment is the price of the report whose span contains that moment. Whether such a report exists yet depends on how recently the DON observed the data and delivered the report. -**Normal case** +**Normal case: a report exists at that exact moment** -A report exists with `observationsTimestamp = 12:05:00`. Its window is 1 second wide. You'll receive it slightly after `12:05:00` — typically up to 1-2 seconds later — due to DON consensus and transmission to you. +For example, a report exists with `observationsTimestamp = 12:05:00` and a 1-second window. The report is delivered slightly after `12:05:00` (for reports with second-precision timestamps, typically up to 1-2 seconds later) due to DON consensus and transmission. -**Edge case: no report at that exact second** +**Edge case: no report at that exact moment** -Sometimes there's no report observed with `observationsTimestamp = 12:05:00`. For example: +It is possible for no report to be observed with `observationsTimestamp = 12:05:00`. For example: - Last report: `observationsTimestamp = 12:04:59` - Next report: `observationsTimestamp = 12:05:01` -The next report's window absorbs the gap: its `validFromTimestamp` is `12:05:00`, making its window 2 seconds wide (`12:05:00` → `12:05:01`). +The next report's `validFromTimestamp` is `12:05:00`, absorbing the gap and creating a 2-second window (`12:05:00` → `12:05:01`). In this example, the price for `12:05:00` is observed one second later at `12:05:01`. -In this example, the price for `12:05:00` is observed one second later at `12:05:01`. +Because windows can vary in width, **do not assume every report covers exactly one second**. Read `validFromTimestamp` and `observationsTimestamp` from each report rather than deriving the window from the previous report's timestamp or from your own clock. - - -## How timestamps relate to TWAP streams +## TWAP streams -TWAP streams function differently than traditional data reports. A TWAP report is an **aggregated calculation** derived from the underlying reports. +Time Weighted Average Price (TWAP) streams report the average price over a rolling window, rather than a single observed price. A TWAP report is an **aggregated calculation** derived from the underlying reports. See the [TWAP report schema](/data-streams/reference/report-schema-v2#time-weighted-average-price-twap) for the full field definitions. -A TWAP span is anchored to `observationsTimestamp`, not to Unix time. It doesn't pad or extend to hit a round boundary — it slides. +A TWAP window is anchored to the latest observation and moves forward with each new report. Unlike standard streams, it doesn't align to the clock or snap to round numbers. -For example, a 60-second TWAP requested "at `12:05:01`" covers `12:04:01` → `12:05:01`, not `12:04:00` → `12:05:00` or anything else artificially aligned to the clock. +For example, a 60-second TWAP requested "at `12:05:01`" covers `12:04:01` to `12:05:01`. **Formula:** @@ -1018,7 +1013,7 @@ TWAP = (sum of price × duration for each report in the window) / window length - 30-second TWAP → divide by 30 - 60-second TWAP → divide by 60 -If a report's window is wider than 1 second (that is, it spans a gap where no intermediate report existed), that report's price is interpolated across the seconds it covers rather than treated as a single point. +The TWAP is constructed from underlying reports that fall within its window. Each underlying report normally covers about 1 second, but if a report's window is wider because it absorbed a gap, its price is weighted across the full window covered in the TWAP calculation. --- From 90077f29276dbf1dc95770db779c53a25af661e0 Mon Sep 17 00:00:00 2001 From: devin distefano Date: Thu, 10 Sep 2026 20:18:16 -0500 Subject: [PATCH 4/6] nits and standardize on window --- .../data-streams/how-report-timestamps-work.mdx | 14 +++++++------- src/content/data-streams/llms-full.txt | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/content/data-streams/how-report-timestamps-work.mdx b/src/content/data-streams/how-report-timestamps-work.mdx index 16a127935ec..d00ae1aadbc 100644 --- a/src/content/data-streams/how-report-timestamps-work.mdx +++ b/src/content/data-streams/how-report-timestamps-work.mdx @@ -34,19 +34,19 @@ Every Data Streams report carries two timestamps: - **`validFromTimestamp`** — when the report's price _starts being valid_ - **`observationsTimestamp`** — when the report's price _was last observed_. -Together, they describe a span of time rather than a single instant. Below, find information about how that span is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. +Together, they describe a window of time rather than a single instant. This page explains how that window is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. -## Report Spans +## Report windows -A report does not have verified price for a single instant in time. The `validFromTimestamp` marks the beginning of the span, and the `observationsTimestamp` marks the end. +A report does not have verified price for a single instant in time. The `validFromTimestamp` marks the beginning of the window, and the `observationsTimestamp` marks the end. Both fields are Unix timestamps in seconds. [Each report schema](/data-streams/reference/report-schema-overview) contains definitions, including the unit of time, for all fields. -The span of time can vary depending on how frequently the Decentralized Oracle Network (DON) can observe the data and generate reports. Spans are contiguous by construction: each one starts the immediately following the previous span. Each report is designed to have no gaps or overlap, with every price interval belonging to exactly one report. +The window of time can vary depending on how frequently the Decentralized Oracle Network (DON) can observe the data and generate reports. Windows are contiguous by construction: each one starts immediately following the previous window. Each report is designed to have no gaps or overlap, with every time interval belonging to exactly one report. ## Determining current price -Because each report covers a span rather than an instant, the "current" price at any given moment is the price of the report whose span contains that moment. Whether such a report exists yet depends on how recently the DON observed the data and delivered the report. +Because each report covers a window rather than an instant, the "current" price at any given moment is the price of the report whose window contains that moment. Whether such a report exists yet depends on how recently the DON observed the data and delivered the report. **Normal case: a report exists at that exact moment** @@ -69,7 +69,7 @@ Time Weighted Average Price (TWAP) streams report the average price over a rolli A TWAP window is anchored to the latest observation and moves forward with each new report. Unlike standard streams, it doesn't align to the clock or snap to round numbers. -For example, a 60-second TWAP requested "at `12:05:01`" covers `12:04:01` to `12:05:01`. +For example, a 60-second TWAP requested "at `12:05:01`" covers `12:04:01` → `12:05:01`. **Formula:** @@ -80,4 +80,4 @@ TWAP = (sum of price × duration for each report in the window) / window length - 30-second TWAP → divide by 30 - 60-second TWAP → divide by 60 -The TWAP is constructed from underlying reports that fall within its window. Each underlying report normally covers about 1 second, but if a report's window is wider because it absorbed a gap, its price is weighted across the full window covered in the TWAP calculation. +The TWAP is constructed from the underlying reports that fall within its window. Each underlying report normally covers about 1 second, but if a report's window is wider because it absorbed a gap, its price is weighted across the full window it covers. diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index cef36f955a5..77ee0b912ef 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -967,19 +967,19 @@ Every Data Streams report carries two timestamps: - **`validFromTimestamp`** — when the report's price *starts being valid* - **`observationsTimestamp`** — when the report's price *was last observed*. -Together, they describe a span of time rather than a single instant. Below, find information about how that span is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. +Together, they describe a window of time rather than a single instant. This page explains how that window is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. -## Report Spans +## Report windows -A report does not have verified price for a single instant in time. The `validFromTimestamp` marks the beginning of the span, and the `observationsTimestamp` marks the end. +A report does not have verified price for a single instant in time. The `validFromTimestamp` marks the beginning of the window, and the `observationsTimestamp` marks the end. Both fields are Unix timestamps in seconds. [Each report schema](/data-streams/reference/report-schema-overview) contains definitions, including the unit of time, for all fields. -The span of time can vary depending on how frequently the Decentralized Oracle Network (DON) can observe the data and generate reports. Spans are contiguous by construction: each one starts the immediately following the previous span. Each report is designed to have no gaps or overlap, with every price interval belonging to exactly one report. +The window of time can vary depending on how frequently the Decentralized Oracle Network (DON) can observe the data and generate reports. Windows are contiguous by construction: each one starts immediately following the previous window. Each report is designed to have no gaps or overlap, with every time interval belonging to exactly one report. ## Determining current price -Because each report covers a span rather than an instant, the "current" price at any given moment is the price of the report whose span contains that moment. Whether such a report exists yet depends on how recently the DON observed the data and delivered the report. +Because each report covers a window rather than an instant, the "current" price at any given moment is the price of the report whose window contains that moment. Whether such a report exists yet depends on how recently the DON observed the data and delivered the report. **Normal case: a report exists at that exact moment** @@ -1002,7 +1002,7 @@ Time Weighted Average Price (TWAP) streams report the average price over a rolli A TWAP window is anchored to the latest observation and moves forward with each new report. Unlike standard streams, it doesn't align to the clock or snap to round numbers. -For example, a 60-second TWAP requested "at `12:05:01`" covers `12:04:01` to `12:05:01`. +For example, a 60-second TWAP requested "at `12:05:01`" covers `12:04:01` → `12:05:01`. **Formula:** @@ -1013,7 +1013,7 @@ TWAP = (sum of price × duration for each report in the window) / window length - 30-second TWAP → divide by 30 - 60-second TWAP → divide by 60 -The TWAP is constructed from underlying reports that fall within its window. Each underlying report normally covers about 1 second, but if a report's window is wider because it absorbed a gap, its price is weighted across the full window covered in the TWAP calculation. +The TWAP is constructed from the underlying reports that fall within its window. Each underlying report normally covers about 1 second, but if a report's window is wider because it absorbed a gap, its price is weighted across the full window it covers. --- From 9b24b1478384b25b7e6df1e04df37c4bda1e13b7 Mon Sep 17 00:00:00 2001 From: devin distefano Date: Thu, 10 Sep 2026 20:32:08 -0500 Subject: [PATCH 5/6] cross linking --- src/content/data-streams/concepts/best-practices.mdx | 2 +- .../data-streams/how-report-timestamps-work.mdx | 4 ++-- src/content/data-streams/llms-full.txt | 10 +++++----- .../reference/data-streams-api/interface-api.mdx | 2 +- .../data-streams/reference/report-schema-v2.mdx | 2 +- src/features/feeds/components/reportSchemaData.ts | 8 +++++++- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/content/data-streams/concepts/best-practices.mdx b/src/content/data-streams/concepts/best-practices.mdx index 3168421a3fc..c90ef8410e3 100644 --- a/src/content/data-streams/concepts/best-practices.mdx +++ b/src/content/data-streams/concepts/best-practices.mdx @@ -56,7 +56,7 @@ For best practices regarding stock splits and reverse splits for tokenized asset ## Report Timestamps -Each report applies to a span of time defined by `validFromTimestamp` and `observationsTimestamp`, and that span isn't always exactly one second wide. Read both fields from each report rather than assuming a fixed cadence or deriving the window from your own clock. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including how gaps between reports are absorbed and how timestamps apply to TWAP streams. +Each report applies to a span of time defined by `validFromTimestamp` and `observationsTimestamp`, and that span can vary in width. Read both fields from each report rather than assuming a fixed cadence or deriving the window from your own clock. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including how gaps between reports are absorbed and how timestamps apply to TWAP streams. ## Rate Limits diff --git a/src/content/data-streams/how-report-timestamps-work.mdx b/src/content/data-streams/how-report-timestamps-work.mdx index d00ae1aadbc..77642fed301 100644 --- a/src/content/data-streams/how-report-timestamps-work.mdx +++ b/src/content/data-streams/how-report-timestamps-work.mdx @@ -34,7 +34,7 @@ Every Data Streams report carries two timestamps: - **`validFromTimestamp`** — when the report's price _starts being valid_ - **`observationsTimestamp`** — when the report's price _was last observed_. -Together, they describe a window of time rather than a single instant. This page explains how that window is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. +Together, they describe a window of time rather than a single instant. This page explains how that window is constructed, what to expect when no report exists for a given moment, and how timestamps apply to Time Weighted Average Price (TWAP) streams. ## Report windows @@ -61,7 +61,7 @@ It is possible for no report to be observed with `observationsTimestamp = 12:05: The next report's `validFromTimestamp` is `12:05:00`, absorbing the gap and creating a 2-second window (`12:05:00` → `12:05:01`). In this example, the price for `12:05:00` is observed one second later at `12:05:01`. -Because windows can vary in width, **do not assume every report covers exactly one second**. Read `validFromTimestamp` and `observationsTimestamp` from each report rather than deriving the window from the previous report's timestamp or from your own clock. +Because windows can vary in width, **do not assume every report covers the same window**. Read `validFromTimestamp` and `observationsTimestamp` from each report rather than deriving the window from the previous report's timestamp or from your own clock. ## TWAP streams diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 41847413170..93d07ee00e6 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -404,7 +404,7 @@ For best practices regarding stock splits and reverse splits for tokenized asset ## Report Timestamps -Each report applies to a span of time defined by `validFromTimestamp` and `observationsTimestamp`, and that span isn't always exactly one second wide. Read both fields from each report rather than assuming a fixed cadence or deriving the window from your own clock. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including how gaps between reports are absorbed and how timestamps apply to TWAP streams. +Each report applies to a span of time defined by `validFromTimestamp` and `observationsTimestamp`, and that span can vary in width. Read both fields from each report rather than assuming a fixed cadence or deriving the window from your own clock. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including how gaps between reports are absorbed and how timestamps apply to TWAP streams. ## Rate Limits @@ -975,7 +975,7 @@ Every Data Streams report carries two timestamps: - **`validFromTimestamp`** — when the report's price *starts being valid* - **`observationsTimestamp`** — when the report's price *was last observed*. -Together, they describe a window of time rather than a single instant. This page explains how that window is constructed, what to expect when no report exists for a given second, and how timestamps apply to Time Weighted Average Price (TWAP) streams. +Together, they describe a window of time rather than a single instant. This page explains how that window is constructed, what to expect when no report exists for a given moment, and how timestamps apply to Time Weighted Average Price (TWAP) streams. ## Report windows @@ -1002,7 +1002,7 @@ It is possible for no report to be observed with `observationsTimestamp = 12:05: The next report's `validFromTimestamp` is `12:05:00`, absorbing the gap and creating a 2-second window (`12:05:00` → `12:05:01`). In this example, the price for `12:05:00` is observed one second later at `12:05:01`. -Because windows can vary in width, **do not assume every report covers exactly one second**. Read `validFromTimestamp` and `observationsTimestamp` from each report rather than deriving the window from the previous report's timestamp or from your own clock. +Because windows can vary in width, **do not assume every report covers the same window**. Read `validFromTimestamp` and `observationsTimestamp` from each report rather than deriving the window from the previous report's timestamp or from your own clock. ## TWAP streams @@ -4780,7 +4780,7 @@ All routes require the following three headers for user authentication: ## API endpoints -Report responses include `validFromTimestamp` and `observationsTimestamp`, which together define the span of time the report's price applies to rather than a single instant. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including what happens when no report exists for a given second. +Report responses include `validFromTimestamp` and `observationsTimestamp`, which together define the span of time the report's price applies to rather than a single instant. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including what happens when no report exists for a given moment. ### Discover data streams @@ -6273,7 +6273,7 @@ Cryptocurrency streams adhere to the report schema outlined below. ## Time-Weighted Average Price (TWAP) -The v2 schema is used by TWAP streams. The `price` field carries the time-weighted average price for the stream's configured window, not a spot or median price. Each TWAP stream is scoped to one asset and one window length (for example, 30 seconds or 60 seconds). The window length is part of the stream's name and metadata. +The v2 schema is used by TWAP streams. The `price` field carries the time-weighted average price for the stream's configured window, not a spot or median price. Each TWAP stream is scoped to one asset and one window length (for example, 30 seconds or 60 seconds). The window length is part of the stream's name and metadata. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for how timestamps apply to TWAP streams. ## Schema Fields diff --git a/src/content/data-streams/reference/data-streams-api/interface-api.mdx b/src/content/data-streams/reference/data-streams-api/interface-api.mdx index cb942434bd1..3c9420afd0b 100644 --- a/src/content/data-streams/reference/data-streams-api/interface-api.mdx +++ b/src/content/data-streams/reference/data-streams-api/interface-api.mdx @@ -37,7 +37,7 @@ All routes require the following three headers for user authentication: ## API endpoints -Report responses include `validFromTimestamp` and `observationsTimestamp`, which together define the span of time the report's price applies to rather than a single instant. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including what happens when no report exists for a given second. +Report responses include `validFromTimestamp` and `observationsTimestamp`, which together define the span of time the report's price applies to rather than a single instant. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for details, including what happens when no report exists for a given moment. ### Discover data streams diff --git a/src/content/data-streams/reference/report-schema-v2.mdx b/src/content/data-streams/reference/report-schema-v2.mdx index de1d1debc0a..b2d3b4f3ece 100644 --- a/src/content/data-streams/reference/report-schema-v2.mdx +++ b/src/content/data-streams/reference/report-schema-v2.mdx @@ -20,7 +20,7 @@ Cryptocurrency streams adhere to the report schema outlined below. ## Time-Weighted Average Price (TWAP) -The v2 schema is used by TWAP streams. The `price` field carries the time-weighted average price for the stream's configured window, not a spot or median price. Each TWAP stream is scoped to one asset and one window length (for example, 30 seconds or 60 seconds). The window length is part of the stream's name and metadata. +The v2 schema is used by TWAP streams. The `price` field carries the time-weighted average price for the stream's configured window, not a spot or median price. Each TWAP stream is scoped to one asset and one window length (for example, 30 seconds or 60 seconds). The window length is part of the stream's name and metadata. See [How Report Timestamps Work](/data-streams/how-report-timestamps-work) for how timestamps apply to TWAP streams. ## Schema Fields diff --git a/src/features/feeds/components/reportSchemaData.ts b/src/features/feeds/components/reportSchemaData.ts index dba1c6f7ef5..66b0f420861 100644 --- a/src/features/feeds/components/reportSchemaData.ts +++ b/src/features/feeds/components/reportSchemaData.ts @@ -21,11 +21,17 @@ export interface SchemaDefinition { // Fields present in every report schema const COMMON_FIELDS: SchemaField[] = [ { field: "feedId", type: "bytes32", description: "Unique identifier for the Data Streams feed" }, - { field: "validFromTimestamp", type: "uint32", description: "Earliest timestamp when the price is valid (seconds)" }, + { + field: "validFromTimestamp", + type: "uint32", + description: "Earliest timestamp when the price is valid (seconds)", + link: { label: "How report timestamps work", href: "/data-streams/how-report-timestamps-work" }, + }, { field: "observationsTimestamp", type: "uint32", description: "Latest timestamp when the price is valid (seconds)", + link: { label: "How report timestamps work", href: "/data-streams/how-report-timestamps-work" }, }, { field: "nativeFee", type: "uint192", description: "Legacy onchain verification fee field" }, { From 2d5270c94430cf8c25f62da9a2f6c20d8d47ec2f Mon Sep 17 00:00:00 2001 From: devin distefano Date: Thu, 10 Sep 2026 20:34:37 -0500 Subject: [PATCH 6/6] intro fix --- src/content/data-streams/how-report-timestamps-work.mdx | 2 +- src/content/data-streams/llms-full.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/data-streams/how-report-timestamps-work.mdx b/src/content/data-streams/how-report-timestamps-work.mdx index 77642fed301..3d94f4c47bc 100644 --- a/src/content/data-streams/how-report-timestamps-work.mdx +++ b/src/content/data-streams/how-report-timestamps-work.mdx @@ -34,7 +34,7 @@ Every Data Streams report carries two timestamps: - **`validFromTimestamp`** — when the report's price _starts being valid_ - **`observationsTimestamp`** — when the report's price _was last observed_. -Together, they describe a window of time rather than a single instant. This page explains how that window is constructed, what to expect when no report exists for a given moment, and how timestamps apply to Time Weighted Average Price (TWAP) streams. +Together, they describe a window of time rather than a single instant. This page explains how the two timestamps define a [report's window](#report-windows), what to expect when [no report exists for a given moment](#determining-current-price), and how timestamps apply to [Time Weighted Average Price (TWAP) streams](#twap-streams). ## Report windows diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 93d07ee00e6..611e842c3c0 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -975,7 +975,7 @@ Every Data Streams report carries two timestamps: - **`validFromTimestamp`** — when the report's price *starts being valid* - **`observationsTimestamp`** — when the report's price *was last observed*. -Together, they describe a window of time rather than a single instant. This page explains how that window is constructed, what to expect when no report exists for a given moment, and how timestamps apply to Time Weighted Average Price (TWAP) streams. +Together, they describe a window of time rather than a single instant. This page explains how the two timestamps define a [report's window](#report-windows), what to expect when [no report exists for a given moment](#determining-current-price), and how timestamps apply to [Time Weighted Average Price (TWAP) streams](#twap-streams). ## Report windows