
Best before
On-chain price data with a freshness SLA. Stale data is refused, refunded, and logged on Hedera.
Demo
About
Best Before is a paid price data service for agents. The provider is responsible for meeting the freshness guarantee before delivering the data. When an agent queries a subgraph, it can get a valid response without knowing how stale the data is. The response has the right format, no errors, and HTTP 200, but the underlying data may still be far behind the chain. If an agent makes a bad decision using that data, the buyer has no way to tell whether the strategy was wrong or the input was stale. We saw this happen during development. The same subgraph deployment returned data that was 1 block behind the chain head, then about 20 million blocks behind, then 3 blocks behind, all within the same day. The deployment ID stayed the same, and every response reported hasIndexingErrors as false. This means freshness cannot be checked once and assumed to stay the same. It needs to be measured for every request. Best Before currently sells WETH/USDC price data from Aerodrome on Base. There are three pricing tiers, each with a different maximum data age. Before payment, a request returns HTTP 402 with the current measured age, block lag, and the tiers that the data currently satisfies. This gives the buyer a preview of the current state, but it is not the freshness guarantee. After payment is settled, Best Before measures freshness again. It compares the subgraph's _meta block with the current chain head to calculate the age and block lag. Both values come from sources that the buyer can query independently. The price is delivered only if the new measurement satisfies the tier the buyer paid for. If the data no longer meets the tier, Best Before does not deliver it and refunds the payment in full. The outcome is also recorded on a Hedera Consensus Service topic created without an admin key. The receipt includes the values used to make the decision, including the delivered block, chain head, deployment ID, measured age, and purchased SLA. This lets anyone reproduce the freshness calculation instead of simply trusting a result reported by Best Before. Freshness can also be checked on the buyer side, and several projects already do this. The difference is that a buyer side check happens after the buyer has paid. Best Before puts the check on the provider side. If the provider cannot meet the freshness requirement after payment, the data is not delivered and the buyer gets the payment back. That way, stale data costs the provider instead of the buyer.
How it's made
Best Before runs as a Hono server on Node 20 and is deployed on Railway, with a /health endpoint for health checks. The Graph is the main data source. Pool price and _meta are fetched in a single GraphQL request so the price and its freshness measurement always refer to the same indexed block. Fetching them separately could mean checking one block while returning a price from another. Block lag is calculated as chain_head - delivered_block. The chain head comes from the RPC of the chain indexed by the subgraph. A caller can retrieve these values independently and reproduce the calculation. Payments use x402 with the exact scheme on Hedera testnet, settled through the Blocky402 facilitator. We use the upfront payment flow because settlement needs to complete before the route handler runs, and it gives us a settled payer address for refunds. Prices are denominated in HBAR (asset 0.0.0) and represented in tinybar, so neither party needs HTS token association. Best Before has three freshness tiers: strict (<0s), realtime (<5s), and delayed (<60s). Strict is deliberately impossible to satisfy, giving us a reliable way to demonstrate the refusal and refund path without modifying the data source or adding a debug mode. Receipts are written to a Hedera Consensus Service topic created without an admin key. Delivered receipts are submitted asynchronously so they do not delay data delivery. For refusals and upstream failures, we wait for consensus before returning the response, so the refund has a public record before the request finishes. We also use Messari's standardized Lending Protocol schema. One query retrieves comparable TVL and freshness information across five protocols without a custom adapter for each one. That query also surfaced problems in the deployments themselves. Two Base deployments were unreachable: one had no indexer allocations, while all available indexers for the other returned HTTP 400. Another deployment had its manifest declare BASE while Protocol.network returned MAINNET. We caught the mismatch through the standardized schema itself. Receipts are validated when they are built. A paid request that was not delivered cannot have refund_status = NOT_APPLICABLE, and refund_tinybar must equal paid_tinybar. An UNAVAILABLE snapshot uses null for derived fields rather than zero, so a missing measurement cannot look like a real zero. We also ran into two Hedera SDK issues. new Hbar(2000000) means two million HBAR, not 0.02 HBAR. Tinybar amounts need Hbar.fromTinybars(); otherwise the mistake only shows up later as an insufficient balance error. Using @hiero-ledger/sdk alongside @x402/hedera can also load two separate SDK instances, causing internal instanceof checks to fail with "t.startsWith is not a function". Best Before avoids this by importing all Hedera primitives from @x402/hedera. Receipts store the inputs used to make a freshness decision, not just the result: delivered block, chain head, deployment ID, measured age, and purchased SLA. Anyone can use those values to reconstruct why a request was delivered or refused, without trusting what Best Before reported.