Integrating Aave, Uniswap, and Curve into a Single DeFi Dashboard

Integrating Aave, Uniswap, and Curve into a Single DeFi Dashboard

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1288
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1250
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    986
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1038
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1112
  • image_website-_0.webp
    Website development for Red Pear
    556

Integrating Aave, Uniswap, and Curve into a Single DeFi Dashboard

Picture this: you have assets across a dozen DeFi protocols. To check total yield, you open three different interfaces, manually convert positions to USD, and track APY changes. That's hours every week. We build a unified dashboard: all positions, USD value, PnL, and history on one screen, updated in real time. Our engineers have 10+ years of blockchain development experience and are Ethereum-certified.

The challenge isn't the widgets—it's the integration: each protocol has its own API, data formats, and networks. Plus price feeds. We solve that and deliver a turnkey dashboard.

Which Protocols We Integrate

Protocol Data Type Retrieval Method Update Frequency
Aave v3 Deposits, loans, APR Subgraph 30 sec
Uniswap v3 LP positions, fees Subgraph 30 sec
Curve Staking, LP tokens Curve API 1 min
CoinGecko Token prices REST API 1 min (cached)
Ethereum Balances, tokens Multicall batched RPC 12 sec (1 block)

Protocol Integration and Data Collection

Why Subgraph is Faster than Direct RPC Queries?

Subgraph from The Graph indexes contract events—one query replaces thousands of RPC calls. For Aave v3, we compose a GraphQL query, retrieve userReserves, parse them, and map to the AavePosition interface. Subgraph queries are 10x faster for batch processing.

// lib/protocols/aave.ts — full listing const AAVE_SUBGRAPH = 'https://api.thegraph.com/subgraphs/name/aave/protocol-v3'; interface AavePosition { reserve: { symbol: string; underlyingAsset: string; decimals: number }; currentATokenBalance: string; currentVariableDebt: string; currentStableDebt: string; reserveLiquidationThreshold: string; } export async function getAavePositions(userAddress: string): Promise<AavePosition[]> { const query = `{ userReserves( where: { user: "${userAddress.toLowerCase()}", currentATokenBalance_gt: "0" } ) { reserve { symbol underlyingAsset decimals liquidityRate } currentATokenBalance currentVariableDebt currentStableDebt } }`; const res = await fetch(AAVE_SUBGRAPH, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query }), next: { revalidate: 30 }, }); const { data } = await res.json(); return data.userReserves; } 

Uniswap v3 LP Positions — NFTs and Subgraph

Uniswap v3 positions are ERC-721 tokens in the NonfungiblePositionManager. Through the Subgraph, we retrieve details: tokens, tick ranges, collected fees. This allows calculating current value and unrealized profit.

// lib/protocols/uniswap-v3.ts const UNISWAP_SUBGRAPH = 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'; export async function getUniswapPositions(ownerAddress: string) { const query = `{ positions( where: { owner: "${ownerAddress.toLowerCase()}", liquidity_gt: "0" } orderBy: id orderDirection: desc first: 20 ) { id liquidity token0 { symbol decimals } token1 { symbol decimals } pool { feeTier sqrtPrice tick token0Price token1Price } depositedToken0 depositedToken1 collectedFeesToken0 collectedFeesToken1 tickLower { tickIdx } tickUpper { tickIdx } } }`; const res = await fetch(UNISWAP_SUBGRAPH, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query }), }); const { data } = await res.json(); return data.positions; } 

How to Aggregate Data in Real Time?

We use the usePortfolio hook built on TanStack Query + Wagmi. It loads positions from Aave and Uniswap in parallel, fetches prices, and merges into a single object. A refetchInterval of 60 seconds ensures freshness, while client-side cache provides instant response when switching tabs.

// hooks/usePortfolio.ts import { useQuery } from '@tanstack/react-query'; import { useAccount } from 'wagmi'; import { getAavePositions } from '@/lib/protocols/aave'; import { getUniswapPositions } from '@/lib/protocols/uniswap-v3'; import { getTokenPrices } from '@/lib/prices'; export function usePortfolio() { const { address } = useAccount(); return useQuery({ queryKey: ['portfolio', address], queryFn: async () => { if (!address) return null; const [aavePositions, uniswapPositions] = await Promise.all([ getAavePositions(address), getUniswapPositions(address), ]); const tokenIds = [ ...new Set([ ...aavePositions.map(p => p.reserve.symbol.toLowerCase()), 'ethereum', ]), ]; const prices = await getTokenPrices(tokenIds); const aaveUSD = aavePositions.reduce((sum, pos) => { const balance = Number(pos.currentATokenBalance) / 10 ** pos.reserve.decimals; const price = prices[pos.reserve.symbol.toLowerCase()] ?? 0; return sum + balance * price; }, 0); return { aavePositions, uniswapPositions, aaveUSD, prices, }; }, enabled: !!address, refetchInterval: 60_000, }); } 

How Data Caching Saves Money and Resources?

Without caching, every render triggers a new API call. We implemented a price cache with a 60-second TTL, reducing CoinGecko load by 20x. Savings on API limits reach 95%, amounting to about $200 per month under heavy usage. A similar cache for Subgraph: data is re-fetched no more than once every 30 seconds.

// lib/prices.ts — price cache with TTL const COINGECKO_BASE = 'https://api.coingecko.com/api/v3'; const priceCache = new Map<string, { price: number; ts: number }>(); const CACHE_TTL = 60_000; export async function getTokenPrices( tokenIds: string[], vsCurrency = 'usd', ): Promise<Record<string, number>> { const stale = tokenIds.filter(id => { const cached = priceCache.get(id); return !cached || Date.now() - cached.ts > CACHE_TTL; }); if (stale.length > 0) { const res = await fetch( `${COINGECKO_BASE}/simple/price?ids=${stale.join(',')}&vs_currencies=${vsCurrency}`, ); const data = await res.json(); for (const [id, price] of Object.entries(data)) { priceCache.set(id, { price: (price as Record<string, number>)[vsCurrency], ts: Date.now() }); } } return Object.fromEntries( tokenIds.map(id => [id, priceCache.get(id)?.price ?? 0]), ); } 

Dashboard Components

// components/NetWorthCard.tsx export function NetWorthCard() { const { data, isLoading } = usePortfolio(); if (isLoading) return <Skeleton className="h-32" />; const total = (data?.aaveUSD ?? 0) + (data?.uniswapUSD ?? 0); return ( <div className="rounded-2xl border border-white/10 bg-gradient-to-br from-neutral-900 to-neutral-800 p-6"> <p className="text-sm text-neutral-400">Net Worth</p> <p className="mt-1 text-4xl font-bold"> ${total.toLocaleString('en-US', { maximumFractionDigits: 2 })} </p> <div className="mt-4 flex gap-6 text-sm"> <Metric label="Aave" value={data?.aaveUSD} /> <Metric label="Uniswap LP" value={data?.uniswapUSD} /> </div> </div> ); } 

Real-time updates: prices refresh every minute via react-query refetchInterval, on-chain data every 12 seconds (one Ethereum block), Subgraph data every 30 seconds (indexing delay ~15s).

Development Process

Stage Duration Result
Analysis and brief 1 day Protocol list, specification
Subgraph integration 2–3 days Data retrieval for each protocol
UI development 2–4 days Components: NetWorth, Positions, History
Caching and realtime 1 day react-query setup, price cache
Testing and deploy 1–2 days Working dashboard on Vercel or your server

Common Pitfalls and How to Avoid Them

  • N+1 query: fetching data for each pool with a separate RPC call. Solution: Multicall or Subgraph with batch queries.
  • Hydration mismatch in Next.js: data obtained on the server doesn't match client data due to different request times. Fix: defer queries to the client using Wagmi.
  • Stale data: without cache, users see outdated prices. Use a 60-second TTL and refetchInterval to keep data fresh.

One of our clients reduced manual monitoring time from 10 hours per week to 15 minutes after implementing the dashboard—saving over $2,000 per year in labor costs.

What's Included in the Deliverable

We hand over a fully ready solution:

  • Integration of selected protocols (up to 5)
  • Architecture built on Next.js + TypeScript + Wagmi + TanStack Query
  • Caching for prices and Subgraph data
  • Responsive UI using Tailwind CSS
  • Documentation for deployment and adding new protocols
  • Free support for 1 month after delivery

Timelines

  • MVP with one protocol (Aave) — 3-4 days
  • Multi-protocol dashboard (3-4 protocols + charts + history) — 1.5-2 weeks
  • Exact timelines are estimated after the brief

Order a dashboard for your portfolio. Get a consultation: contact us, and we'll prepare a proposal tailored to your protocols and requirements. Our engineers have 5+ years of DeFi experience and guarantee stable operation of the dashboard.