אנו נתקלים באופן קבוע באתגר של איסוף TVL ו-APY מפרוטוקולי DeFi. על פני השטח, זה נראה פשוט: לשלוף את הנתונים, לאחסן אותם במסד נתונים, לשרת אותם דרך API. אבל בפועל, כל פרוטוקול משתמש בלוגיקת חישוב משלו — חלק מהנתונים חיים על השרשרת, חלק ב-subgraphs עם עיכובים, ו-APY מחושב מחדש בכל בלוק. פרוטוקולים רבים פורסים גרסאות מרובות על שרשראות שונות עם ABIs לא תואמים. יתר על כן, ספקי RPC מגבילים את תדירות הבקשות, ו-subgraphs של The Graph יכולים להתיישן (The Graph Protocol). ללא ארכיטקטורת גרידה מחושבת היטב, במקום נתונים נקיים, תקבלו בלגן של נקודות נתונים חסרות, TVL מנופח עקב מחירים מנופלים, ו-APY שגוי. לצוות שלנו יש ניסיון של 5+ שנים בהנדסת נתוני DeFi, עם מסירה של 50+ פרויקטי גרידה לפרוטוקולים מובילים.
מקורות נתונים והמוזרויות שלהם
The Graph: מקור ראשי לנתונים מצטברים
לרוב הפרוטוקולים הגדולים יש subgraphs רשמיים: Uniswap, Curve, Aave, Compound, Balancer, Yearn. The Graph Studio מאפשר שאילתות על נתונים היסטוריים ונוכחיים דרך GraphQL.
בעיות שאנו נתקלים בהן:
- אחזור (Latency). Subgraphs מתעדכנים בעיכוב של 1–10 דקות לאחר אירועים על השרשרת. לא מתאימים לניטור בזמן אמת, אבל טובים לנתונים היסטוריים ולדשבורדים.
- Subgraphs מיושנים. ה-subgraph של Uniswap v2 לא מתוחזק על ידי הצוות כבר זמן רב; הנתונים עשויים להיות חלקיים. עבור Uniswap v3, ה-subgraph הרשמי מפגר מעת לעת בזמן נפח גבוה.
-
פאג'ינציה. The Graph מחזיר מקסימום 1000 רשומות לכל שאילתה. כדי לשלוף את כל הבריכות של Uniswap v3 (מעל 50,000), יש צורך בפאג'ינציה באמצעות תבנית
skipאוid_gt.
query GetPools($lastId: String) {
pools(first: 1000, where: { id_gt: $lastId }, orderBy: id) {
id
token0 {
symbol
decimals
}
token1 {
symbol
decimals
}
totalValueLockedUSD
volumeUSD
feeTier
}
} - ניואנס של TVL ב-The Graph. ה-subgraph של Uniswap v3 מחשב TVL כסכום של ערכי טוקנים בדולרים באמצעות עדכון מחירים פנימי. עדכון מחירים זה לפעמים נותן ערכים שגויים לטוקנים עם נזילות נמוכה — בריכה עם TVL אמיתי של $500k עשויה להראות כ-$50M בגלל מחיר מנופל של טוקן אחד. יש לבדוק זאת מול מקור חיצוני.
שאילתות On-Chain לנתונים מדויקים
עבור נתונים שצריכים להיות מדויקים ועדכניים — query GetPools($lastId: String) { pools(first: 1000, where: { id_gt: $lastId }, orderBy: id) { id token0 { symbol, decimals } token1 { symbol, decimals } totalValueLockedUSD volumeUSD feeTier } } ישירות לחוזים:
- TVL של Aave v3:
Pool.getReserveData(asset)מחזירaToken.totalSupply() * liquidityIndex. עבור כל נכס בכל שוק. - APY של Curve:
Minter.minted(gauge, user)עבור פליטת CRV,gauge.inflation_rate()עבור שער נוכחי. APY אמיתי =(crv_per_year * crv_price) / gauge_tvl_usd. - APY מעמלות של Uniswap v3:
positions.tokensOwed0/1— עמלות מצטברות. עבור APY כללי של בריכה:pool.feeGrowthGlobal0X128— דלתא על פני תקופה / נזילות.
Multicall3 (0xcA11bde05977b3631167028862bE2a173976CA11) פרוס על כל השרשראות המרכזיות, ומאפשר אצווה של מאות GET /tvl/{protocol} → current TVL GET /protocol/{protocol} → historical TVL + breakdown GET /pools → APY по всем пулам (~10k записей) לתוך עסקה אחת. במקום 100 בקשות RPC בודדות — אצווה אחת. עבור גרידה, זה קריטי לביצועים. Multicall3 יעיל פי 10 מ-/pools רציף.
API של DeFi Llama
https://api.llama.fi — API ציבורי ללא מפתח לנתוני TVL של רוב הפרוטוקולים. מבנה הנתונים:
GET /tvl/{protocol} → current TVL
GET /protocol/{protocol} → historical TVL + breakdown
GET /pools → APY по всем пулам (~10k записей){ protocolId, chainId, poolAddress, tvlUsd, apy, timestamp } הוא מכרה זהב: הוא כבר מחשב APY עבור אלפי בריכות בכל השרשראות. עם זאת, DeFi Llama מעדכן נתונים כל כמה דקות — עבור משימות בזמן אמת, יש צורך בחישוב משלך.
| מקור | אחזור | דיוק TVL | עלות בקשה |
|---|---|---|---|
| The Graph | 1–10 דקות | בינוני (סיכון למניפולציה) | חינם (1000 בקשות/יום) |
| On-chain (eth_call) | זמן אמת | גבוה | גז, מגבלות RPC |
| DeFi Llama | כמה דקות | בינוני | חינם, ללא מפתח |
איך לנרמל נתונים מפרוטוקולים שונים?
כל פרוטוקול מחזיר נתונים בפורמט משלו. נורמליזציה היא המפתח. אנו ממירים הכל לסכמה אחידה: ethers.js. סכמה אחידה מאפשרת השוואות בין פרוטוקולים. לשם כך, אנו משתמשים בסקריפטים של Node.js עם TypeScript וספריית 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 (единый формат) ↓ TimescaleDB / PostgreSQL ↓ API (REST/GraphQL) . הנורמליזטור שלנו משתמש בתבנית מתאם אגנוסטית לסכמה כדי לטפל במוזרויות ספציפיות לפרוטוקול.
ארכיטקטורת מערכת הגרידה
שכבות איסוף נתונים
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 (единый формат)
↓
TimescaleDB / PostgreSQL
↓
API (REST/GraphQL)הנורמליזטור הוא הרכיב המרכזי. כל פרוטוקול מחזיר נתונים בפורמט משלו. נורמליזציה: { protocolId, chainId, poolAddress, tvlUsd, apy, timestamp }. סכמה אחידה מאפשרת השוואות בין פרוטוקולים.
חישוב APY
APY = תשואה שנתית באחוזים עם ריבית דריבית. עבור רוב פרוטוקולי DeFi, הנתונים הגולמיים הם APR (ללא ריבית דריבית), שצריך להמיר:
APY = (1 + APR/n)^n - 1, כאשר n הוא מספר תקופות הריבית דריבית בשנה.
עבור פרוטוקולי הלוואות, APR בדרך כלל כבר כולל ריבית דריבית (Aave v3 משתמש ב-liquidityRate). עבור עמדות LP, זה לא כך: עמלות נצברות ללא השקעה חוזרת.
רכיבי APY אמיתיים עבור עמדת LP של Uniswap v3:
- APR מעמלות מסחר (תלוי בנפח ובטווח העמדה)
- תגמולי כריית נזילות (אם קיימים תמריצים)
- מינוס הפסד בלתי קבוע (אומדן היסטורי)
למה APY ללא הפחתת IL מטעה?
APY כנה ללא הפחתת הפסד בלתי קבוע מראה תשואות מנופחות. במציאות, עם עמדת LP בטווח רחב, IL יכול לאכול עד 80% מהרווחים. אנו מציגים את שני המספרים: APY מעמלות ו-APY מעמלות מינוס IL.
טיפול בשגיאות והגבלת קצב
השכבה החינמית של Alchemy: 300 CUPS (יחידות מחשוב לשנייה). eth_call אחד = 10–40 CU, אצווה של Multicall3 = 20 CU ללא קשר למספר השאילתות בפנים. אנו עושים אצווה ככל האפשר.
The Graph: 1000 בקשות ביום בתוכנית החינמית. אנו משתמשים במטמון עם TTL — רוב הנתונים לא צריכים רענון יותר מכל 5 דקות.
ניסיון חוזר עם backoff אקספוננציאלי על כל בקשות ה-HTTP. תור של מכתבים מתים עבור שליפות שנכשלו — אנחנו לא מאבדים נתונים במהלך תקלות RPC זמניות.
| רכיב | מקור | מוזרויות |
|---|---|---|
| עמלות מסחר | On-chain / The Graph | תלוי בנפח ובטווח |
| תגמולים | Merkle drop / תמריצים | דורש ניטור |
| IL | מחיר On-chain | מוערך היסטורית |
מחסן הטכנולוגיות
TypeScript + Node.js עבור סקרפרים. PostgreSQL + TimescaleDB לאחסון סדרות זמן. Redis למטמון נתוני ביניים. Docker Compose לפיתוח מקומי.
ethers.js v6 לאינטראקציות על השרשרת. graphql-request עבור שאילתות The Graph. p-limit לבקרת מקביליות (לא להכות בספקי RPC). היפרטבלאות של TimescaleDB מאפשרות שאילתות סדרות זמן יעילות על מיליוני רשומות.
טעויות אופייניות בגרידת נתוני DeFi
- שימוש במקור אחד בלבד ללא אימות. TVL מ-subgraph לא מאומת יכול להיות גבוה פי 10 מהערך האמיתי בגלל מחירים מנופלים.
- אי התחשבות בהפסד בלתי קבוע בעת חישוב APY עבור עמדות LP.
- התעלמות ממגבלות קצב — הסקרפר נכשל עם שגיאות, נתונים אובדים.
- אחסון כל הנתונים בטבלה אחת ללא חלוקה — שאילתות היסטוריות הופכות לאיטיות.
מה העבודה כוללת
- ניתוח פרוטוקולים ומקורות נתונים עבור המשימה שלך.
- פיתוח סקרפר עם נורמליזציה ואימות.
- הגדרת TimescaleDB עם TTL וחלוקה.
- REST/GraphQL API עם מטמון.
- תיעוד של מבנה הנתונים ונקודות קצה.
- חודש של תמיכה לאחר המסירה.
- סקריפטי פריסה וגישה לדשבורד פרטי.
- דיוק נתונים מובטח עם אימות צולב ממספר מקורות.
הערכות לוחות זמנים
סקרפר עבור 2–3 פרוטוקולים על שרשרת אחת עם API בסיסי: 2–3 ימים. מערכת רב-פרוטוקולית ורב-שרשרתית עם נתונים היסטוריים ונורמליזציה: 1–2 שבועות, תלוי במספר המקורות ובדרישות דיוק APY. עלות פרויקט טיפוסית נעה בין $2,000 ל-$10,000.
אנו נעריך את הפרויקט שלך ונציע פתרון סוהר. צור קשר כדי לדון בפרטים. הזמן פיתוח של סקרפר נתוני DeFi.







