DeFi Data Aggregation: TVL, APY, Pool Liquidity from Multiple Sources

We regularly encounter the challenge of collecting TVL and APY from DeFi protocols. On the surface, it seems simple: pull the data, store it in a database, serve it via an API. But in practice, each protocol uses its own calculation logic — part of the data lives on-chain, part in subgraphs with del

Blockchain Development Services

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1309
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1270
  • image_logo-advance_0.webp
    B2B Advance company logo design
    719
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    1011
  • image_logo-aider_0.webp
    AIDER company logo development
    954
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1062

We regularly encounter the challenge of collecting TVL and APY from DeFi protocols. On the surface, it seems simple: pull the data, store it in a database, serve it via an API. But in practice, each protocol uses its own calculation logic — part of the data lives on-chain, part in subgraphs with delays, and APY is recalculated every block. Many protocols deploy multiple versions on different chains with incompatible ABIs. Moreover, RPC providers throttle request frequency, and The Graph subgraphs can become stale (The Graph Protocol). Without a well-thought-out scraping architecture, instead of clean data, you end up with a mess of missing data points, inflated TVL due to manipulated prices, and incorrect APY. Our team has 5+ years of experience in DeFi data engineering, having delivered 50+ scraping projects for leading protocols.

Data Sources and Their Peculiarities

The Graph: Primary Source for Aggregated Data

Most major protocols have official subgraphs: Uniswap, Curve, Aave, Compound, Balancer, Yearn. The Graph Studio allows querying historical and current data via GraphQL.

Problems we encounter:

  • Latency. Subgraphs update with a 1–10 minute delay after on-chain events. Not suitable for real-time monitoring, but fine for historical data and dashboards.
  • Stale subgraphs. The Uniswap v2 subgraph hasn't been maintained by the team for a long time; data may be incomplete. For Uniswap v3, the official subgraph periodically lags during high volume.
  • Pagination. The Graph returns a maximum of 1000 records per query. To fetch all Uniswap v3 pools (over 50,000), you need pagination using skip or id_gt pattern.
query GetPools($lastId: String) { pools(first: 1000, where: { id_gt: $lastId }, orderBy: id) { id token0 { symbol, decimals } token1 { symbol, decimals } totalValueLockedUSD volumeUSD feeTier } } 
  • TVL nuance in The Graph. The Uniswap v3 subgraph calculates TVL as the sum of token values in USD using an internal price feed. This price feed sometimes gives incorrect values for low-liquidity tokens — a pool with a real TVL of $500k might show as $50M due to a manipulated price of one token. This needs to be cross-checked with an external source.

On-Chain Queries for Accurate Data

For data that needs to be exact and current — direct eth_call to contracts:

  • Aave v3 TVL: Pool.getReserveData(asset) returns aToken.totalSupply() * liquidityIndex. For each asset in each market.
  • Curve APY: Minter.minted(gauge, user) for CRV emission, gauge.inflation_rate() for current rate. Real APY = (crv_per_year * crv_price) / gauge_tvl_usd.
  • Uniswap v3 fee APY: positions.tokensOwed0/1 — accumulated fees. For general pool APY: pool.feeGrowthGlobal0X128 — delta over period / liquidity.

Multicall3 (0xcA11bde05977b3631167028862bE2a173976CA11) is deployed on all major chains, allowing batching hundreds of eth_call into one transaction. Instead of 100 individual RPC requests — one batch. For scraping, this is critical for performance. Multicall3 is 10 times more efficient than sequential eth_call.

DeFi Llama API

https://api.llama.fi — public API without key for TVL data of most protocols. Data structure:

GET /tvl/{protocol} → current TVL GET /protocol/{protocol} → historical TVL + breakdown GET /pools → APY for all pools (~10k records) 

/pools is a goldmine: it already calculates APY for thousands of pools across all chains. However, DeFi Llama updates data every few minutes — for real-time tasks, you need your own calculation.

Source Latency TVL Accuracy Request Cost
The Graph 1–10 min Medium (manipulation risk) Free (1000 requests/day)
On-chain (eth_call) Real-time High Gas, RPC limits
DeFi Llama few min Medium Free, no key

How to Normalize Data from Different Protocols?

Each protocol returns data in its own format. Normalization is key. We convert everything to a unified schema: { protocolId, chainId, poolAddress, tvlUsd, apy, timestamp }. A unified schema enables cross-protocol comparisons. For this, we use Node.js scripts with TypeScript and the ethers.js library. Our normalizer employs a schema-agnostic adapter pattern to handle protocol-specific quirks.

Scraping System Architecture

Data Collection Layers

Scheduler (cron / event-driven) ├── GraphQL Fetcher (The Graph subgraphs) ├── On-chain Fetcher (Multicall3 + ethers.js) ├── HTTP Fetcher (DeFi Llama, CoinGecko) └── WebSocket Listener (real-time events) ↓ Normalizer (unified format) ↓ TimescaleDB / PostgreSQL ↓ API (REST/GraphQL) 

The Normalizer is the key component. Each protocol returns data in its own format. Normalization: { protocolId, chainId, poolAddress, tvlUsd, apy, timestamp }. A unified schema enables cross-protocol comparisons.

APY Calculation

APY = Annual Percentage Yield with compounding. For most DeFi protocols, raw data is APR (without compounding), which needs to be converted:

APY = (1 + APR/n)^n - 1, where n is the number of compounding periods per year.

For lending protocols, APR usually already includes compounding (Aave v3 uses liquidityRate). For LP positions, it does not: fees are accrued without reinvestment.

Real APY components for a Uniswap v3 LP position:

  1. Trading fees APR (depends on volume and position range)
  2. Liquidity mining rewards (if incentives exist)
  3. Minus impermanent loss (historical estimate)

Why APY Without Subtracting IL Is Misleading?

An honest APY without subtracting impermanent loss shows inflated returns. In reality, with a wide range LP position, IL can eat up to 80% of profits. We show both numbers: fee APY and fee APY minus IL.

Error Handling and Rate Limiting

Alchemy free tier: 300 CUPS (compute units per second). One eth_call = 10–40 CU, Multicall3 batch = 20 CU regardless of the number of queries inside. We batch as much as possible.

The Graph: 1000 requests per day on the free plan. We use a cache with TTL — most data doesn't need to be refreshed more often than every 5 minutes.

Retry with exponential backoff on all HTTP requests. Dead letter queue for failed fetches — we don't lose data during temporary RPC failures.

Component Source Peculiarities
Trading fees On-chain / The Graph Depends on volume and range
Rewards Merkle drop / incentives Requires monitoring
IL On-chain price Estimated historically

Tech Stack

TypeScript + Node.js for scrapers. PostgreSQL + TimescaleDB for time-series storage. Redis for caching intermediate data. Docker Compose for local development.

ethers.js v6 for on-chain interactions. graphql-request for The Graph queries. p-limit for concurrency control (don't hammer RPC providers). TimescaleDB hypertables enable efficient time-series queries over millions of records.

Typical Mistakes When Scraping DeFi Data

  • Using only one source without validation. TVL from an unverified subgraph can be 10x higher than the real value due to manipulated prices.
  • Not accounting for impermanent loss when calculating APY for LP positions.
  • Ignoring rate limits — the scraper fails with errors, data is lost.
  • Storing all data in a single table without partitioning — historical queries become slow.

What the Work Includes

  1. Analysis of protocols and data sources for your task.
  2. Development of a scraper with normalization and validation.
  3. Setup of TimescaleDB with TTL and partitioning.
  4. REST/GraphQL API with caching.
  5. Documentation of data structure and endpoints.
  6. One month of support after delivery.
  7. Deployment scripts and access to a private dashboard.
  8. Guaranteed data accuracy with cross-validation from multiple sources.

Timeline Estimates

A scraper for 2–3 protocols on a single chain with a basic API: 2–3 days. A multi-protocol, multi-chain system with historical data and normalization: 1–2 weeks, depending on the number of sources and APY accuracy requirements. Typical project cost ranges from $2,000 to $10,000.

We will evaluate your project and offer a turnkey solution. Contact us to discuss the details. Order development of a DeFi data scraper.