# Daily DEX OHLC and VWAP for a token, with exact fractions

> Original page: https://docs.blockvectra.com/en/guides/dex-daily-prices/

## What the DEX Daily Prices dataset is [#what-the-dex-daily-prices-dataset-is]

BlockVectra's DEX dataset indexes decentralized exchange trade activity and computes aggregated daily pricing metrics. The DEX daily prices endpoint (`getDexPrices`) provides the daily volume-weighted average price (VWAP), price indicators (fields `first_price`, `last_price`, `min_price`, and `max_price`), and volume metrics for a specified token over a given date range.

Availability of this dataset varies across networks; chains providing this dataset are subject to the [Supported Chains](/en/chains/) page.

This endpoint is not paginated: all matching daily rows within the requested date span are returned directly in `data`, and `next_cursor` is never present. If your application requires granular swap transactions rather than daily aggregates, use `GET /{chain}/dex/swaps` (see the [Data API Reference](/en/api/data/)).

## Request parameters and specification limits [#request-parameters-and-specification-limits]

The endpoint route is `GET https://dev-api.blockvectra.network/v1/data/{chain}/dex/prices`. All requests require authentication by supplying your API key in the `x-api-key` header.

The endpoint accepts the following query parameters:

| Parameter | Location | Type        | Required | Description                                                                  |
| --------- | -------- | ----------- | -------- | ---------------------------------------------------------------------------- |
| `chain`   | path     | string      | Yes      | Chain identifier, e.g. `robinhood_mainnet`                                   |
| `token`   | query    | string      | Yes      | 20-byte base token address, `0x` optional, either case                       |
| `quote`   | query    | string      | No       | Optional 20-byte quote token address to restrict to a single base/quote pair |
| `from`    | query    | date string | Yes      | UTC start date, inclusive, `YYYY-MM-DD`                                      |
| `to`      | query    | date string | Yes      | UTC end date, inclusive, `YYYY-MM-DD`. `to - from` must be `<= 90` days      |

### Specification constraints and error codes [#specification-constraints-and-error-codes]

When a request violates specification constraints, the API returns a structured error body `{"error":{"code","message"}}`:

* **HTTP 400 (`bad_request`)**: Missing required query parameters (`token`, `from`, or `to`), invalid `token`/`quote` address syntax, invalid `YYYY-MM-DD` calendar dates, or `from` is after `to`.
* **HTTP 409 (`span_exceeded`)**: `to - from` is more than 90 days.
* **HTTP 404 (`unknown_chain`)**: `{chain}` is not a chain listed by `GET /chains`.
* **HTTP 422 (`no_coverage`)**: The chain does not support the `dex_prices` dataset capability.
* **HTTP 503 (`unavailable`)**: Service temporarily unavailable; retry according to the `Retry-After` header.

## Request examples [#request-examples]

The following examples query daily DEX prices for a base token across September 2026:

<Tabs groupId="code-lang" items="['cURL', 'TypeScript', 'Python']">
  <Tab value="cURL">
    ```bash
    curl -s "https://dev-api.blockvectra.network/v1/data/robinhood_mainnet/dex/prices?token=0x2260fac5e5542a773aa44fbcfedf7c193bc2c599&from=2026-09-01&to=2026-09-30" \
      -H "x-api-key: $BLOCKVECTRA_API_KEY"
    ```
  </Tab>

  <Tab value="TypeScript">
    ```ts
    const url = new URL("https://dev-api.blockvectra.network/v1/data/robinhood_mainnet/dex/prices");
    url.searchParams.set("token", "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599");
    url.searchParams.set("from", "2026-09-01");
    url.searchParams.set("to", "2026-09-30");

    const res = await fetch(url, {
      headers: {
        "x-api-key": process.env.BLOCKVECTRA_API_KEY!,
      },
    });

    if (!res.ok) {
      throw new Error(`Request failed with status ${res.status}`);
    }

    const body = await res.json();
    console.log(body);
    ```
  </Tab>

  <Tab value="Python">
    ```python
    import os
    import requests

    res = requests.get(
        "https://dev-api.blockvectra.network/v1/data/robinhood_mainnet/dex/prices",
        params={
            "token": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
            "from": "2026-09-01",
            "to": "2026-09-30",
        },
        headers={
            "x-api-key": os.environ["BLOCKVECTRA_API_KEY"],
        },
    )
    res.raise_for_status()
    print(res.json())
    ```
  </Tab>
</Tabs>

## Detailed field reference [#detailed-field-reference]

Each entry in `data` represents aggregated daily DEX metrics for the token pair on that UTC date:

### Token and quote assets [#token-and-quote-assets]

* `day` (string): UTC date in `YYYY-MM-DD` format.
* `token` (string): 20-byte base token address in lowercase `0x`-prefixed hex.
* `token_symbol` (string or `null`): Base token symbol.
* `token_name` (string or `null`): Base token display name.
* `quote_token` (string): Quote asset address. The all-zero address (`0x0000000000000000000000000000000000000000`) represents native ETH as the quote asset.
* `quote_symbol` (string or `null`): Quote asset symbol (`"ETH"` when `quote_token` is the all-zero address).
* `quote_name` (string or `null`): Quote asset display name (`"Ether"` when `quote_token` is the all-zero address).
* `base_decimals` (integer or `null`): Base token decimals (0–255).
* `quote_decimals` (integer or `null`): Quote asset decimals (`18` when `quote_token` is the all-zero address).

### Volume and trade counts [#volume-and-trade-counts]

* `swap_count` (integer): Swap count for this row.
* `base_volume_raw` (string): Atomic base volume as an unsigned integer decimal string (`UInt256String`).
* `quote_volume_raw` (string): Atomic quote volume as an unsigned integer decimal string (`UInt256String`).
* `base_volume` (string or `null`): Human-readable base token volume scaled by `base_decimals` as a `DecimalString`; `null` when `base_decimals` is unknown.
* `quote_volume` (string or `null`): Quote volume scaled by quote decimals as a `DecimalString`, or `null`.

### Price indicators and VWAP [#price-indicators-and-vwap]

* `vwap` (string or `null`): Volume-weighted average price as a `DecimalString`, or `null`.
* `first_price` (string or `null`): First price indicator as a `DecimalString`, or `null`.
* `last_price` (string or `null`): Last price indicator as a `DecimalString`, or `null`.
* `min_price` (string or `null`): Minimum price indicator as a `DecimalString`, or `null`.
* `max_price` (string or `null`): Maximum price indicator as a `DecimalString`, or `null`.

### Exact fraction fields [#exact-fraction-fields]

* `first_price_numerator` / `first_price_denominator` (string): Exact integer numerator and denominator for `first_price` (`UInt256String`).
* `last_price_numerator` / `last_price_denominator` (string): Exact integer numerator and denominator for `last_price` (`UInt256String`).
* `min_price_numerator` / `min_price_denominator` (string): Exact integer numerator and denominator for `min_price` (`UInt256String`).
* `max_price_numerator` / `max_price_denominator` (string): Exact integer numerator and denominator for `max_price` (`UInt256String`).
* `refreshed_at` (string): Refresh timestamp for this row (ISO-8601 UTC timestamp).

### Envelope metadata (`meta`) [#envelope-metadata-meta]

* `chain`: Chain identifier.
* `chain_slug`: Canonical uppercase chain slug.
* `chain_external_id`: CAIP-2 formatted chain identifier.
* `as_of_block`: The indexed head block number from which this response's finality watermark was computed (reported by this dataset, not checked against request parameters).
* `finalized_block`: Reorg-safety watermark block number (not consensus finality).
* `coverage`: Coverage classification (reports `"full"` for this endpoint).
* `refreshed_at`: Metadata refreshed timestamp.

## Why prices use exact numerators and denominators [#why-prices-use-exact-numerators-and-denominators]

On-chain DEX pricing originates from Automated Market Maker (AMM) liquidity pool reserve ratios or swap formulas.

Standard JSON numbers rely on IEEE-754 double-precision floats, which present precision limitations:

1. **Floating-point truncation and drift**: Float64 values provide only 53 bits of precision, and dividing token quantities yields rounding drift that compounds across calculations.
2. **Transport safety**: Formatting values as decimal strings (`UInt256String`) ensures numbers travel across HTTP without losing precision in JSON parsers.

By providing the exact integer numerator and denominator for price indicators, BlockVectra enables exact mathematical calculations without floating-point conversion. Quantitative models, arbitrage monitors, and financial accounting systems can evaluate prices and ratios without floating-point inaccuracies.

### Handling exact fractions in TypeScript (BigInt) [#handling-exact-fractions-in-typescript-bigint]

In TypeScript, you can use native `BigInt` for cross-multiplication comparisons and fixed-point conversions without floating-point conversion:

```ts
interface DexDailyPrice {
  first_price_numerator: string;
  first_price_denominator: string;
  last_price_numerator: string;
  last_price_denominator: string;
}

// 1. Ratio comparison without floating-point conversion: check if close price is higher than open price
// a / b > c / d  is equivalent to  a * d > c * b
export function isPriceUp(row: DexDailyPrice): boolean {
  const openNum = BigInt(row.first_price_numerator);
  const openDen = BigInt(row.first_price_denominator);
  const closeNum = BigInt(row.last_price_numerator);
  const closeDen = BigInt(row.last_price_denominator);

  return closeNum * openDen > openNum * closeDen;
}

// 2. Convert fraction to a fixed-point decimal string with arbitrary scale (without floating-point loss)
export function fractionToFixedString(
  numeratorStr: string,
  denominatorStr: string,
  decimals = 18
): string {
  const num = BigInt(numeratorStr);
  const den = BigInt(denominatorStr);
  if (decimals === 0) {
    return (num / den).toString();
  }
  const scaleFactor = 10n ** BigInt(decimals);

  const scaled = (num * scaleFactor) / den;
  const intPart = scaled / scaleFactor;
  const remainder = scaled % scaleFactor;
  const fracPart = remainder.toString().padStart(decimals, "0");

  return `${intPart}.${fracPart}`;
}
```

### Handling exact fractions in Python [#handling-exact-fractions-in-python]

Python provides standard library modules built specifically for rational and decimal calculations: `fractions.Fraction` and `decimal.Decimal`.

```python
from decimal import Decimal, getcontext
from fractions import Fraction

# 1. Exact rational calculations with fractions.Fraction
open_price = Fraction(
    int(row["first_price_numerator"]),
    int(row["first_price_denominator"])
)
close_price = Fraction(
    int(row["last_price_numerator"]),
    int(row["last_price_denominator"])
)

# Exact price delta without floating-point rounding error
price_delta = close_price - open_price
print(f"Price delta (fraction): {price_delta}")

if open_price != 0:
    percentage_change = (price_delta / open_price) * 100
    print(f"Percentage change: {float(percentage_change):.4f}%")

# 2. Arbitrary-precision decimal arithmetic with decimal.Decimal
getcontext().prec = 50

if int(row["first_price_denominator"]) != 0:
    open_decimal = Decimal(row["first_price_numerator"]) / Decimal(row["first_price_denominator"])
    print(f"High-precision open: {open_decimal}")
```

## Backfilling one year of daily prices [#backfilling-one-year-of-daily-prices]

To backfill a year of data (365 days) within the 90-day span limit, divide the full date range into consecutive windows of at most 90 days and issue chunked requests:

```ts
interface DateSpan {
  from: string;
  to: string;
}

/**
 * Split a large date range into consecutive spans of at most maxDays (default: 90)
 */
export function splitDateRange(startDateStr: string, endDateStr: string, maxDays = 90): DateSpan[] {
  const spans: DateSpan[] = [];
  let currentStart = new Date(startDateStr);
  const end = new Date(endDateStr);

  while (currentStart <= end) {
    const chunkEnd = new Date(currentStart);
    chunkEnd.setUTCDate(chunkEnd.getUTCDate() + (maxDays - 1));
    const effectiveEnd = chunkEnd < end ? chunkEnd : end;

    spans.push({
      from: currentStart.toISOString().slice(0, 10),
      to: effectiveEnd.toISOString().slice(0, 10),
    });

    const nextStart = new Date(effectiveEnd);
    nextStart.setUTCDate(nextStart.getUTCDate() + 1);
    currentStart = nextStart;
  }

  return spans;
}

/**
 * Backfill token daily prices across multiple 90-day chunks
 */
export async function backfillTokenDailyPrices(
  chain: string,
  token: string,
  startDate: string,
  endDate: string,
  apiKey: string
) {
  const chunks = splitDateRange(startDate, endDate, 90);
  const allDailyPrices = [];

  for (const chunk of chunks) {
    const url = new URL(`https://dev-api.blockvectra.network/v1/data/${chain}/dex/prices`);
    url.searchParams.set("token", token);
    url.searchParams.set("from", chunk.from);
    url.searchParams.set("to", chunk.to);

    const res = await fetch(url, {
      headers: { "x-api-key": apiKey },
    });

    if (!res.ok) {
      throw new Error(`Failed to fetch span ${chunk.from}..${chunk.to}: HTTP ${res.status}`);
    }

    const json = await res.json();
    allDailyPrices.push(...json.data);
  }

  return allDailyPrices;
}
```

## Capacity and CU usage calculations [#capacity-and-cu-usage-calculations]

Every Data API endpoint meters consumption in Compute Units (CU). The per-call CU weight for `data.dex_prices` and the estimated consumption for token backfills are calculated below. All figures are computed at build time from active platform plan data:

<DexPricesEstimate lang="en" />

When scaling your backfill volume or requiring higher request concurrency, top up your account balance in the [Console](https://console.blockvectra.com/en/login/) to upgrade to a paid account. For active rates and unit conversions, see the [Pricing page](https://blockvectra.com/en/pricing/).

## Next steps [#next-steps]

* [Browse the datasets directory](https://blockvectra.com/en/data/) to see every dataset BlockVectra indexes.
* [See the free plan and pricing](https://blockvectra.com/en/pricing/#free) to check what your account includes.
* [Log in to the console](https://console.blockvectra.com/en/login/?next=%2Fen%2Fkeys%2F) to create an API key.
