Market Data
Market Data gives valuation, compliance, and reporting one governed price for an asset or currency pair, so they stop reconciling separate copies of the market.
Trusted issuers and external aggregators publish observations. The directory the institution governs selects, rather than merges, one active feed for each subject and topic, and consumers use the resulting indexed price, valuation, or exchange-rate series.
Valuation, compliance, and reporting all draw the same governed price, so none of them keeps a private copy of the market that could diverge from the others without anyone noticing.
A subject names what a value belongs to, and a topic names what it means, so the same two keys always resolve to the one feed currently active for them.
Every feed is pinned to one topic and one schema at creation, and an update naming a different one is rejected before anything else runs.
A read against a feed whose last observation has aged past the window that applies is refused rather than served, so a consumer never mistakes a stale number for a current one.
Replacing a feed's upstream source can never change the decimals, scale, or kind a consumer already relies on, so swapping a provider never silently changes what a stored value means.
Every accepted update and each change to the directory is recorded on chain, so an auditor can see what the platform accepted and from whom.
Why price needs a governed source
An institution running tokenized assets needs a price in more places than one moment suggests. A collateral desk marks a position to compute a margin call. A compliance check screens a transfer against a threshold. A net asset value for a regulatory filing comes from a reporting run. Before a trading venue lets an execution proceed, it checks that price against a reference. Each of these draws from Market Data, and each draws the same value for the same subject and topic at the same moment.
Without a governed source, each of those workflows would keep its own copy of the market, refreshed on its own schedule from whatever source it happened to integrate. Two copies drift the moment their update cadences differ, and a drifted copy is invisible until someone compares two numbers that should have matched and finds they did not. Asset Lifecycle names the general shape of this problem. A programme that runs each stage of an instrument's life in its own system meets a reconciliation at every boundary between those systems, and a reconciliation is where two records that should agree are instead found apart. A private price copy draws that same boundary around a number instead of a stage, and the risk is the same. An auditor asking which price was official at a given moment gets an answer that depends on which system they asked.
Governance is what keeps a shared price defensible rather than merely convenient. The institution, not the platform, decides which issuers or external aggregators it trusts and how often they must publish. Market Data's job is to hold that decision on chain and serve one answer from it. A shared price then traces back to a source someone chose and can name, instead of moving the drift problem from many private copies to one that no one can account for.
Why this governance runs on the platform, not beside it
The alternative to platform-governed pricing is a market-data terminal or a vendor feed, integrated once by whichever system needs it that quarter. That system picks its own idea of a stale quote, its own retry behavior when the vendor goes down, and its own storage shape for the number it keeps. Nothing forces it to match the next system that integrates the same vendor differently. An institution running compliance, reporting, custody, and a trading venue behind one platform would then repeat that integration once per consumer, each with its own definition of current.
Market Data closes that gap by sitting inside the same platform as its consumers instead of beside it. Trading Venue's price protection band checks an execution against this domain's feed, the same feed a compliance screen or a reporting run would read for the same subject and topic. The rule that decides when a value is too old to serve is derived once and applies wherever a consumer asks for it, so current means the same thing to every workflow that asks. An institution that wants a different one of its trusted sources to answer changes it in one governed place, and every consumer sees the change at the same moment instead of catching up on its own schedule.
What a subject and topic name
Market Data organizes every value it serves under two keys. A subject names what the value belongs to: the zero address for a global series, a token's own address for an asset-specific one. A topic names what the value means, pinned to a schema when its feed is created, so a price and a valuation for the same token are two different feeds even though they share a subject. Platform foreign-exchange feeds use a deterministic address derived from a currency's ISO 4217 numeric code as the subject, with the base and quote currencies recorded in the feed's own description.
Ask for a subject and a topic, and Market Data returns whichever feed the directory currently holds active for that pair. It never merges two sources into one answer and never asks the caller to choose between them: that choice was already made when the feed was registered.
Running feeds day to day
Operators manage feeds as a set of named slots. For each subject and topic, they register a compatible feed, watch its latest observation, and remove or replace it when the source changes.
Each feed is pinned to one topic and one schema at creation: the schema is that topic's registered encoding signature, the shape a value must take. An update naming a different topic or schema is refused before anything else runs.
A trusted issuer can publish a signed scalar update stating the value, the observation time, an expiry that bounds how long it may be submitted, and the next issuer nonce. The feed then runs its checks in order, starting with that pinned topic and schema, and any one of them failing leaves the last accepted observation exactly where it was.
Ten guards run in order, and the previous observation survives any one of them failing.
A feed built on an external aggregator can be registered in the same directory and selected the same way, since the directory still holds only one active feed for each subject and topic. A stable adapter can point consumers at the subject and topic while the underlying feed is replaced. Replacement must preserve the feed kind, schema, and decimal precision. Operations can therefore change the source without changing every consumer address, while the registration and update events remain available for reconciliation.
Deciding how long a value stays current
Market Data serves one active value for each subject and topic, and a value is only useful while it is recent. The platform enforces that rather than leaving it to each consumer. When a read finds the active feed's observation older than the window that applies, the on-chain price resolver refuses the read with DALP-1111 instead of returning the aged value. That refusal states the subject, the topic, the timestamp of the observation it rejected, and the window it measured against. That is how a consumer tells a stale feed from a subject and topic that has no feed registered at all: the second answers DALP-1022, and no fresh observation will fix it.
One window applies to a read, and it is decided in two layers: a deployment-wide default, and an optional override on a single feed that takes three forms. One read tells you which layer produced the answer.
| Layer | What it accepts, and where it applies |
|---|---|
| Global default. | A positive window in seconds or an explicit never-expires value. It applies wherever no per-feed override exists; a resolver with no observed global-window event keeps the on-chain default of one day, and never-expires applies once an event setting it has been observed. |
| Per-feed override, a window in seconds. | One window for one subject and topic, sized for a feed whose publisher runs faster or slower than the house rule. |
| Per-feed override, never expires. | No age limit, for one feed that genuinely does not age. Every other feed keeps a window. |
| Per-feed override, inherit global. | Clears the override, returning one feed to the house rule. |
Read the effective window for a subject and topic when you need to know what actually applies. The answer names both the window and the layer that produced it, so an override someone set months ago stays visible rather than inferred.
Choosing how much history a feed keeps
Retention decides how many rounds the feed contract keeps in its own storage, separate from the indexed history the API serves. The platform's issuer-signed feed create flow always uses Latest only and rejects zero or negative observations, so it cannot create a feed for an interest rate or an exchange-rate movement that can cross zero. An externally deployed feed may have different value and retention rules; registering it does not change those rules.
| Retention mode | What the contract keeps, and what that costs |
|---|---|
| Latest only. | The newest round. A historical round read against the contract answers DALP-0131; indexed history is unaffected. |
| Bounded. | A fixed number of rounds. Rounds past that depth leave contract storage. |
| Full. | Every round, at the most on-chain storage. It is the only mode where any round stays readable from the contract itself. |
The platform's create flow does not offer Bounded or Full retention, although the underlying feed contract supports both. Use the indexed API when a consumer needs the history of accepted native observations.
Retention is fixed in each feed contract. A consumer that requires older rounds directly from a contract needs a separately deployed compatible feed with that retention mode. Replacing the directory entry can select that feed if its kind, schema, and decimal precision match. The replacement starts with its own history, while the previous feed's rounds remain readable at its address for as long as it is deployed. Indexed history follows the events both contracts emit.
How the boundary works
Market Data separates three duties: the on-chain directory selects the active feed, each feed contract owns its own accepted observations, and the index follows their events to serve current and historical API views. An API response is an indexed view of on-chain state, not a fresh call to the source.
The directory permits one active entry per key. It verifies that the topic exists, that the feed schema matches the topic, and that a scalar feed exposes the AggregatorV3 interface. Subject zero is global; any other subject binds the feed to that address. A replacement keeps the same semantic and numeric contract, which protects consumers from a silent unit change.
The directory neither aggregates sources nor derives rates. An external aggregator computes its own answer upstream and publishes it through a compatible feed. Separately, the indexed foreign-exchange graph derives available cross-rates from confirmed currency-pair observations. It retains observation time and history, so a derived rate can still be tied to its underlying market-data series.
Three related values sit just outside this boundary, and naming them keeps the domain's edge from blurring. A token's own resolved price, and the price history that cascades onto that token's record, are outputs the token domain computes from this domain's feeds, not values Market Data stores as its own. A portfolio's or a system's value history is the same kind of downstream output, owned by the portfolio domain. A trading venue's own last-trade price is content the venue decides; publishing it reaches the chain through this domain's submission path, but the number itself is the venue's, not a value this domain derives.
The integration contract
Developers address Market Data by subject and topic. Feed-management routes register, replace, remove, submit, resolve, and read observations. Exchange-rate routes expose the latest positive observation, configured pairs, supported currencies, and paginated history for an ISO 4217 base and quote pair.
A feed value is a scaled integer. Its decimals define the scale, while its observation timestamp states when the source observed the value. Read both. A successful submission means the signed update passed the feed's authority, replay, time, and value checks and was recorded on-chain. A mutation request that was only accepted by the platform is not yet proof that the feed changed; use its transaction outcome and then the indexed feed state.
Consumers that need a stable contract address can use the scalar-feed adapter. It resolves the current feed from the directory on every call and forwards the AggregatorV3 reads. If no scalar feed is registered for that subject and topic, it fails rather than returning a default. Indexed API reads can lag the chain briefly, so do not treat an immediate missing record after registration as proof that the on-chain slot does not exist.
Handle the refusals by name rather than by status code alone. A subject and topic with nothing registered answers DALP-0129. An address that does not answer the AggregatorV3 interface answers DALP-9519, which usually means the wrong address rather than a broken feed. An observation timestamp further ahead of chain time than the feed's drift allowance answers DALP-0639. Check the observation timestamp and the signer host's clock before retrying. Price-topic submissions through the feed route require Feeds Manager authority and use the organization's submission signer. Token price operations also expose their own authorization rules.
Controls and evidence
Market Data separates the authority to select a source from the authority to publish an observation. Feed managers govern directory entries. For issuer-signed feeds, only an issuer trusted for that subject and topic can submit, and the signature must come from a key authorized by that issuer.
The feed prevents replay and stale overwrites before state changes. Within a feed, each issuer has its own strictly increasing nonce; an optional deadline bounds submission; observation time must be present; and an observation older than the current one cannot replace it. The platform's native issuer-signed feeds require positive values and allow no future drift from chain time. Other compatible feed contracts may enforce different value and time rules, fixed by their own contracts.
On-chain events record feed registration, replacement, removal, and accepted updates. An accepted signed round records the value, observation time, issuer, and signer. Those events are the durable record, while the configured history mode determines only how many rounds the contract itself keeps in its own storage; the indexed history provides the operational query surface. These records prove what the platform accepted and from whom. They do not prove that the off-chain market observation was economically correct, which remains part of source governance.
Frequently asked questions
Is a topic the same as a currency pair?
No. A topic defines the value's meaning and schema. Platform foreign-exchange feeds use the price topic and a deterministic currency address as the subject. The feed description records the base and quote currencies, such as EUR / USD.
Does replacing a feed change the decimals or scale of values a consumer already read?
No. A replacement is accepted only if it keeps the same feed kind, schema, and decimal precision as the entry it replaces, so a value a consumer already stored keeps the same meaning and scale. What resets is the upstream source and its round history: the new feed contract starts with no rounds of its own, while the previous feed's rounds stay readable at its own address for as long as it remains deployed.
Can more than one issuer publish to the same feed?
Yes. The trusted issuers registry can authorize several issuers for one subject and topic, and the feed accepts a signed update from any of them once its checks pass. Each issuer keeps its own strictly increasing nonce, so issuers never compete over sequence numbers, but the staleness check compares an incoming observation against whichever issuer's update is currently latest, not against that one issuer's own history. A newer submission from a second issuer can therefore supersede an older one from the first.
What happens if a signed update's nonce falls out of sync?
A submission is refused unless its nonce is exactly one more than the last nonce that issuer had accepted, even when the value and observation time are otherwise valid. The first accepted nonce is 1. Read the issuer's current nonce, sign a new update with the next value, and submit it. Observation time may equal the latest accepted timestamp; an earlier timestamp is rejected.
Does a change to the global default window affect a feed that already has its own override?
No. A per-feed override in seconds stays fixed for that feed regardless of what the global default becomes, until someone changes or clears it. Only a feed with no override, or one explicitly set to inherit the global default, picks up a change to that default. Reading the effective window for a subject and topic always shows which layer produced the answer, so an old override never hides behind a number that changed without notice.
Ledger Data
Ledger Data lets an integration answer a holder list, a transfer history, or a compliance check with one query, instead of decoding chain events itself.
Audit Trail
An audit trail lets you show a regulator or an auditor who did what, under which role, without relying on the requester's own account of the request.