Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.dexpaprika.com/llms.txt

Use this file to discover all available pages before exploring further.

See it in action: Check out our Live Streaming Dashboard to see real-time updates flow across multiple chains before you build your own.

Tutorial overview

In this tutorial, you’ll learn how to:
  • Connect to the DexPaprika streaming API
  • Receive real-time token price updates
  • Receive real-time pool reserve updates (the DexPaprika differentiator)
  • Handle connection errors gracefully
  • Build a simple live display
Time to complete: 5 to 10 minutes Prerequisites: Basic JavaScript or Python knowledge

Step 1: Choose Your Asset

For this tutorial, we’ll stream the price of Ethereum (WETH).

Finding Token Addresses

Use the REST API to find token addresses:
  1. Search by name or symbol using the Search Endpoint:
curl "https://api.dexpaprika.com/search?query=WETH"
  1. Get network list using the Networks Endpoint:
curl "https://api.dexpaprika.com/networks"

Common Token Addresses

Or use these verified addresses for popular tokens:
Chain: ethereum
WETH: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
USDC: 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48

Step 2: Test with cURL

First, verify the stream works with a simple cURL command:
curl -N "https://streaming.dexpaprika.com/sse/prices?method=token_price&chain=ethereum&address=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&limit=3"
Live capture from production, three events back-to-back:
data: {"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","chain":"ethereum","price":"2255.213769366838","timestamp":1778847591,"timestamp_price":1778847590,"token_price":1778847590}
event: token_price

data: {"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","chain":"ethereum","price":"2255.5995720362835","timestamp":1778847592,"timestamp_price":1778847592,"token_price":1778847592}
event: token_price

data: {"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","chain":"ethereum","price":"2255.5995720362835","timestamp":1778847593,"timestamp_price":1778847593,"token_price":1778847593}
event: token_price
The limit=3 parameter closes the stream after three events, perfect for smoke tests. Drop it for a continuous feed.
Both orderings of event: and data: lines within a single SSE message are valid per the SSE specification, and the server has used both during rollout. Only the blank-line boundary between messages is significant. EventSource handles either order natively. Custom parsers should buffer one message at a time and dispatch on the parsed event type, not on field order.

Step 3: JavaScript Implementation

Here’s how to connect to the streaming API using JavaScript:
// Connect to streaming API
const url = new URL('https://streaming.dexpaprika.com/sse/prices');
url.searchParams.set('method', 'token_price');
url.searchParams.set('chain', 'ethereum');
url.searchParams.set('address', '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2');

const eventSource = new EventSource(url.toString());

// Handle price updates
eventSource.addEventListener('token_price', (event) => {
    const data = JSON.parse(event.data);
    const price = parseFloat(data.price);
    console.log(`WETH Price: $${price.toFixed(2)}`);
});

// Surface server-side notices (deprecations, etc.)
eventSource.addEventListener('warning', (event) => {
    const { message } = JSON.parse(event.data);
    console.warn('[stream warning]', message);
});

// Handle errors with reconnection
eventSource.onerror = () => {
    console.log('Connection lost, reconnecting...');
    eventSource.close();
    // Implement reconnection logic here
};
🎯 Live Example: See this code in action in our Interactive Streaming Dashboard - watch 6 tokens stream live across Ethereum, Solana, and BSC with real-time updates, connection status, and latency monitoring.

Step 4: Customize Your Stream

Stream Different Tokens

Modify the URL parameters to stream any token:
// Bitcoin on Ethereum
url.searchParams.set('chain', 'ethereum');
url.searchParams.set('address', '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599');

// SOL on Solana
url.searchParams.set('chain', 'solana');
url.searchParams.set('address', 'So11111111111111111111111111111111111111112');

// BNB on BSC
url.searchParams.set('chain', 'bsc');
url.searchParams.set('address', '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c');

Add Multiple Assets

To stream multiple assets, switch to the POST method:

Understanding the Code

Key Components

The EventSource API is the browser’s built-in way to handle SSE:
const eventSource = new EventSource(url);
eventSource.addEventListener('token_price', handler);
It automatically handles:
  • Persistent connections
  • Automatic reconnection
  • Event parsing
The onerror callback handles disconnections:
eventSource.onerror = () => {
    // Implement exponential backoff
    const delay = baseDelay * Math.pow(2, attempts);
    setTimeout(reconnect, delay);
};
Each token_price event contains:
{
    "address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
    "chain": "ethereum",
    "price": "2255.5995720362835",   // USD, string to preserve precision
    "timestamp": 1778847592,         // server send time (unix)
    "timestamp_price": 1778847592,   // price observation time
    "token_price": 1778847592        // alias of timestamp_price
}
The legacy t_p method emits a compact {a, c, p, t, t_p} shape and is deprecated.
Beyond token_price and reserve_update, the server may push:
  • ping every ~15s (keep-alive). Payload: {"time": <unix>}.
  • warning for non-fatal notices, including deprecation messages. Payload: {"message": "..."}.
  • error for stream-terminating problems (invalid asset, etc.).
Always filter on the event: line. Treat unknown event names as no-ops so future server-side additions cannot break your handler.

Now stream pool reserves

Token prices are useful. Block-level pool reserves are the killer feature. Instead of /sse/prices, point at /sse/reserves and pick one of two methods:
  • method=pool_reserves: subscribe to a specific pool. You receive events when that pool’s reserves change.
  • method=token_reserves: subscribe to a specific token. You receive events for every pool the token sits in.

Try it with cURL

Subscribe to a Uniswap V3 USDC/WETH pool on Ethereum:
curl -N "https://streaming.dexpaprika.com/sse/reserves?method=pool_reserves&chain=ethereum&address=0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640"
Each reserve_update event tells you the pool, the block it was observed in, both tokens’ raw reserves, the block’s delta, current USD prices, and the dollar value of the change. A live capture from production (block 25,100,507):
data: {"chain":"ethereum","pool_id":"0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640","block":"25100507","tokens":[{"token_id":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","reserve":"70835095690418","delta":"12018780248","price_usd":1.0000312133558542,"reserve_usd":70837306.69,"delta_usd":12019.15},{"token_id":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","reserve":"14194377792871748830512","delta":"-5325593173019115725","price_usd":2255.213769366838,"reserve_usd":32011356.24,"delta_usd":-12010.35}],"total_reserve_usd":102848662.93,"total_delta_usd":8.80}
event: reserve_update
That is a single swap: ~12,019ofUSDCcamein, 12,019 of USDC came in, ~12,010 of WETH went out, net dollar delta to the pool was +$8.80 (the trader paid the trading fee). The whole picture, in one event, no log decoding required.
The reserve, delta, block, and previous_block fields all arrive as JSON strings (note the quotes in the example above). The server encodes them that way because they routinely exceed Number.MAX_SAFE_INTEGER: the WETH delta above is a 19-digit integer. Use BigInt(reserve) for exact arithmetic, or Number(block) when you just want a quick block-height comparison. The pre-computed USD fields (reserve_usd, delta_usd, total_reserve_usd, total_delta_usd) and price_usd are regular JSON numbers, safe for floating-point math.

Same thing in JavaScript

async function subscribeReserves() {
  const url = new URL("https://streaming.dexpaprika.com/sse/reserves");
  url.searchParams.set("method", "pool_reserves");
  url.searchParams.set("chain", "ethereum");
  url.searchParams.set("address", "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640");

  const response = await fetch(url.toString(), { headers: { Accept: "text/event-stream" } });
  const decoder = new TextDecoder();
  let buffer = "";

  // Async-iterate the response body. This pattern handles gzip/transfer encodings
  // transparently in both Node and modern browsers, and never blocks on partial
  // chunks the way `getReader().read()` can.
  for await (const chunk of response.body) {
    buffer += decoder.decode(chunk, { stream: true });

    // SSE messages are separated by a blank line.
    const messages = buffer.split("\n\n");
    buffer = messages.pop() ?? "";

    for (const message of messages) {
      const lines = message.split("\n");
      const eventLine = lines.find((l) => l.startsWith("event:"));
      const dataLine = lines.find((l) => l.startsWith("data:"));
      if (!dataLine) continue;

      // The stream emits: `reserve_update`, `ping`, `warning`, `error`.
      // Filter for the one we care about so keep-alives and notices
      // never reach the reserve handler.
      const eventType = eventLine ? eventLine.slice(6).trim() : "message";
      if (eventType !== "reserve_update") continue;

      const update = JSON.parse(dataLine.slice(5).trim());
      console.log(`block ${update.block}  pool delta ${update.total_delta_usd.toFixed(2)} USD`);
    }
  }
}

subscribeReserves();
Want the deep dive on what reserves streaming unlocks (impermanent loss tracking, MEV detection, real-time TVL, slippage estimation)? See the Reserves Streaming page for the annotated wire example and use cases broken out by audience.

Implementation Notes

Browser Support

  • EventSource API works in all modern browsers
  • For direct browser connections, you’ll need to handle CORS (use a backend proxy)
  • No issues when streaming from server-side (Node.js, Python, etc.)

Best Practices

  • Implement exponential backoff for reconnection
  • Handle both connection errors and SSE error events
  • Parse prices as floats to maintain precision
  • Close connections properly on page unload

See It Live

🚀 Live Streaming Dashboard

Try the API without writing code. The interactive streaming demo lets you pick a chain, pick tokens (or paste a custom contract address), and watch SSE events flow in real time. You can also copy the generated subscription payload to use in your own code.What you’ll see:
  • Real-time price updates, sub-second latency
  • Multi-chain support (switch chains in the UI)
  • Connection status, latency, and update counts
  • The exact JSON the server pushes, line by line

Next Steps

Congratulations! You’ve built your first streaming application. Here’s what to explore next:

Reserves Streaming Deep Dive

What block-level reserve updates contain, both subscription methods, annotated wire example, and use cases for LPs, MEV builders, and analytics teams.

React Integration

Build streaming components for React and Next.js applications.

Stream Multiple Assets

The POST /sse/prices endpoint for multi-token price subscriptions.

Subscribe to Multiple Reserves

The POST /sse/reserves endpoint for multi-pool and multi-token subscriptions.

Get Help

Join Discord

Get help from our community.

API Reference

Read the complete API documentation.