פיתוח לוח מחוונים לתיק DeFi: אגרגציה, רווח והפסד, ריבוי שרשראות

ניהול תיק DeFi מפוזר על פני פרוטוקולים ורשתות מרובות מקשה על מעקב אחר פוזיציות ורווחים. אנחנו בונים דשבורדים שמאגדים את כל הנכסים שלכם לממשק אחד עם חישוב P&L מדויק. הצוות שלנו מספק את הפרויקט במפתח מלא, תוך הבטחת פעילות אמינה ותמיכה מתמשכת.

שירותי פיתוח בלוקצ'יין

שאלות נפוצות

העבודות האחרונות

  • פיתוח אתר חברה B2B ADVANCE
    פיתוח אתר חברה B2B ADVANCE
    1481
  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1336
  • פיתוח אתר עבור BELFINGROUP
    פיתוח אתר עבור BELFINGROUP
    1034
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1294
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    738
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1032

אנו בונים לוחות מחוונים (דשבורדים) מקיפים לניהול תיקי DeFi. דמיינו משתמש שמחזיק USDC ב-Aave, LP של ETH-USDC ב-Uniswap V3, wstETH ב-Lido, ופוזיציה פתוחה בחוזה עתידי (perpetual) ב-GMX. ארבעה פרוטוקולים שונים, ארבע דרכים שונות לייצוג פוזיציות, וארבעה APIs או subgraphs שונים. תפקידו של לוח המחוונים הוא לאחד את הכל למסך אחד עם מספרי רווח והפסד (P&L) אמיתיים. הניסיון שלנו מראה ש-80% מהמאמץ מושקע בשכבת הנתונים: נרמול נתונים ממקורות שונים וחישוב נכון של יתרות מיושנות לעומת יתרות חיות. אנו מבטיחים דיוק ברמת בלוק וזמן השהיה מינימלי. צרו קשר כדי להעריך את מחסן הטכנולוגיות של הפרויקט שלכם.

כיצד מחושבים רווח והפסד (P&L) והפסד בלתי-קבוע (Impermanent Loss)?

החלק הקשה ביותר הוא חישוב נכון של רווח והפסד לא ממומש (unrealized P&L) עבור פוזיציות LP. עבור Uniswap V3, פוזיציה היא NFT עם tickLower, tickUpper, ו-liquidity ספציפיים. הכמויות הנוכחיות של token0 ו-token1 תלויות ב-sqrtPriceX96 הנוכחי של הבריכה. הנוסחה אינה טריוויאלית:

function getAmountsFromLiquidity(
  sqrtPriceX96: bigint,
  sqrtRatioAX96: bigint,
  sqrtRatioBX96: bigint,
  liquidity: bigint
): [bigint, bigint] {
  if (sqrtPriceX96 <= sqrtRatioAX96) {
    const amount0 =
      (liquidity * (sqrtRatioBX96 - sqrtRatioAX96) * Q96) /
      (sqrtRatioBX96 * sqrtRatioAX96)
    return [amount0, 0n]
  } else if (sqrtPriceX96 < sqrtRatioBX96) {
    const amount0 =
      (liquidity * (sqrtRatioBX96 - sqrtPriceX96) * Q96) /
      (sqrtRatioBX96 * sqrtPriceX96)
    const amount1 = (liquidity * (sqrtPriceX96 - sqrtRatioAX96)) / Q96
    return [amount0, amount1]
  } else {
    const amount1 = (liquidity * (sqrtRatioBX96 - sqrtRatioAX96)) / Q96
    return [0n, amount1]
  }
}

הפסד בלתי-קבוע מחושב כהפרש בין הערך הנוכחי של הפוזיציה לבין הערך שהיה אם אותם נכסים היו פשוט מוחזקים מאז הכניסה. לוח המחוונים חייב לאחסן את מחיר הכניסה והכמויות הראשוניות בעת פתיחת הפוזיציה.

באילו מקורות נתונים אנו משתמשים?

אנו משלבים קריאות ישירות בשרשרת (on-chain) ואינדקסרים. הדרך המדויקת ביותר לקבל יתרה היא function getAmountsFromLiquidity( sqrtPriceX96: bigint, sqrtRatioAX96: bigint, sqrtRatioBX96: bigint, liquidity: bigint ): [bigint, bigint] { if (sqrtPriceX96 <= sqrtRatioAX96) { const amount0 = (liquidity * (sqrtRatioBX96 - sqrtRatioAX96) * Q96) / (sqrtRatioBX96 * sqrtRatioAX96) return [amount0, 0n] } else if (sqrtPriceX96 < sqrtRatioBX96) { const amount0 = (liquidity * (sqrtRatioBX96 - sqrtPriceX96) * Q96) / (sqrtRatioBX96 * sqrtPriceX96) const amount1 = (liquidity * (sqrtPriceX96 - sqrtRatioAX96)) / Q96 return [amount0, amount1] } else { const amount1 = (liquidity * (sqrtRatioBX96 - sqrtRatioAX96)) / Q96 return [0n, amount1] } } ישירה לחוזה. עבור יתרת טוקן — eth_call. עבור פוזיציית Aave — balanceOf(). זה תמיד עדכני אבל איטי: כל פרוטוקול דורש קריאות נפרדות, וזמן ההשהיה גדל ליניארית עם עשרות פרוטוקולים. הפתרון הוא Multicall3 (חוזה 0xC...A11, פרוס על כל רשתות ה-EVM המרכזיות): איגוד של 50+ קריאות בעסקה אחת. זמן התגובה הוא כמו קריאת RPC אחת במקום 50. השוואה: Multicall3 מהיר פי 20 מקריאות רציפות.

import { multicall } from 'viem'

const results = await multicall(client, {
  contracts: [
    {
      address: AAVE_POOL,
      abi: aavePoolAbi,
      functionName: 'getUserAccountData',
      args: [userAddress]
    },
    {
      address: USDC_TOKEN,
      abi: erc20Abi,
      functionName: 'balanceOf',
      args: [userAddress]
    },
    {
      address: UNISWAP_POSITION_MANAGER,
      abi: nftAbi,
      functionName: 'balanceOf',
      args: [userAddress]
    },
  ]
})

עבור נתונים היסטוריים (היסטוריית עסקאות, רווח והפסד לאורך זמן) קריאות ישירות לא עובדות — אנו זקוקים לאינדקסרים.

אנו משתמשים ב-The Graph עבור נתונים היסטוריים. ל-Uniswap, Aave, Compound, Curve ו-Balancer יש כולם subgraphs רשמיים ברשת The Graph. Subgraph מספק ממשק GraphQL לשאילתת אירועים היסטוריים: הפקדות, משיכות, החלפות ופירוקים (liquidations).

query UserPositions($user: String!) {
  aaveV3_deposits(where: { user: $user }, orderBy: timestamp, orderDirection: desc) {
    amount
    reserve {
      symbol
      decimals
      priceInUSD
    }
    timestamp
  }
  aaveV3_borrows(where: { user: $user }) {
    amount
    reserve {
      symbol
    }
    currentVariableBorrowRate
  }
}

בעיה: לגרסאות פרוטוקול שונות יש subgraphs שונים. Aave V2 ב-Ethereum, Aave V3 ב-Polygon, Aave V3 ב-Arbitrum — שלושה subgraphs שונים עם סכמות שונות. נרמול הוא משימת ההנדסה המרכזית של לוח המחוונים. אנו משתמשים בשכבת הפשטה אחידה שממפה את כל הסכמות למודל נתונים יחיד.

Alchemy ו-Moralis כ-API-over-RPC. Alchemy API מספקת מתודות מוכנות: getUserAccountData() מחזירה את כל יתרות ה-ERC-20 של כתובת ללא צורך במעבר על חוזים. import { multicall } from 'viem' const results = await multicall(client, { contracts: [ { address: AAVE_POOL, abi: aavePoolAbi, functionName: 'getUserAccountData', args: [userAddress] }, { address: USDC_TOKEN, abi: erc20Abi, functionName: 'balanceOf', args: [userAddress] }, { address: UNISWAP_POSITION_MANAGER, abi: nftAbi, functionName: 'balanceOf', args: [userAddress] }, ] }) מספקת היסטוריית העברות. זה מפשט משמעותית את היישום הראשוני, אבל עולה כסף בעומס גבוה. Moralis מצטיינת בנוסף באיגוד פוזיציות NFT ופוזיציות פרוטוקול DeFi דרך ה-DeFi API שלה — בתשלום, אבל חוסכת חודשים של פיתוח שכבת נתונים מותאמת אישית. עבור MVP, Alchemy + The Graph עבור פרוטוקולים מרכזיים הוא מוצדק. עבור ייצור עם עשרות אלפי משתמשים, אנו ממליצים על אינדקסר מותאם אישית.

מקור רעננות עלות מורכבות אינטגרציה
Multicall3 חי (ברמת בלוק) חינם (גז RPC) בינונית
The Graph פיגור של ~דקה חינם (מוגבל בקצב) גבוהה (סכמות שונות)
Alchemy API חי תשלום לפי בקשה נמוכה
Moralis חי מנוי נמוכה

איגוד רב-שרשרתי (Multi-Chain Aggregation)

משתמש טיפוסי פעיל ב-Ethereum mainnet, Arbitrum, Polygon ו-Base. לוח המחוונים חייב להציג את התיק הכולל על פני כל השרשרות. הגישה שלנו: בקשות מקבילות ל-RPC של כל שרשרת דרך query UserPositions($user: String!) { aaveV3_deposits(where: { user: $user }, orderBy: timestamp, orderDirection: desc) { amount reserve { symbol, decimals, priceInUSD } timestamp } aaveV3_borrows(where: { user: $user }) { amount reserve { symbol } currentVariableBorrowRate } } , נרמול יתרות לדולרים עם אורקל מחירים אחיד. אנו משתמשים ב-Coingecko API או ב-DefiLlama Price API כדי לקבל מחירים עדכניים לפי כתובת טוקן ומזהה שרשרת. בעיית הזהות בין-שרשרתית: כתובת המשתמש זהה בכל שרשראות ה-EVM (ECDSA), אבל ארנק חוזה חכם (Safe, Argent) עשוי להיות בעל כתובות שונות בשרשראות שונות אם הפריסה לא סונכרנה. אנו תומכים במצב רב-כתובות: המשתמש יכול להוסיף מספר כתובות לפרופיל אחד.

כיצד אנו מבטיחים ביצועים

צד שרת: Node.js + TypeScript עם viem ל-RPC. Redis לשמירת יתרות במטמון (TTL של 30 שניות לנתונים חיים, 5 דקות להיסטוריים). PostgreSQL לאחסון תמונות מצב היסטוריות של התיק (לבניית עקומות הון).

צד לקוח: React + wagmi v2 לחיבור ארנק, Recharts או TradingView Lightweight Charts לגרפים, Tanstack Query לאחזור נתונים עם רענון אוטומטי כל 30 שניות.

WebSocket לעדכונים בזמן אמת: הרשמה ל-getTokenBalances() מפעילה עדכוני יתרות בכל בלוק חדש — מספקת חיוניות ללא סבבי שאילתות מיותרים.

דוגמה לתצורת WebSocket
const transport = http('https://mainnet.infura.io/v3/YOUR_KEY') const client = createPublicClient({ transport }) 

מה כלול

  • תיעוד שכבת נתונים (סכמות נתונים, תיאור נרמול).
  • גישה מלאה למאגר קוד לוח המחוונים.
  • שעתיים של הדרכה מקוונת לצוות.
  • שבועיים של תמיכה חינמית לאחר הפריסה.
  • אפשרות ל-SLA לתחזוקה שוטפת.

רקורד שלנו: 5 שנים בפיתוח בלוקצ'יין, יותר מ-20 פרויקטי DeFi מוצלחים. אנו מבטיחים שלוח המחוונים יפעל ללא השבתות ובדיוק ברמת בלוק.

תהליך

  1. ניתוח (1–2 ימים). רשימת פרוטוקולים ושרשרות יעד, תעדוף לפי מקרי שימוש פופולריים של הקהל.
  2. שכבת נתונים (5–7 ימים). בניית מאגד Multicall, אינטגרציה עם The Graph לפרוטוקולים מרכזיים, נרמול לסכמת פוזיציות אחידה.
  3. Backend API (3–5 ימים). מתן REST/GraphQL API לצד לקוח, שמירה במטמון, היסטוריית תיק.
  4. צד לקוח (5–7 ימים). יישום חיבור ארנק, תצוגת יתרה כוללת, פירוט לפי פרוטוקול, גרפים.

הערכות לוחות זמנים

שלב לוח זמנים
MVP (5–7 פרוטוקולים, 2–3 שרשרות) 2–3 שבועות
לוח מחוונים מלא (היסטוריה, IL, התראות, מובייל) 6–8 שבועות

קבלו ייעוץ לפרויקט שלכם — נעריך את המורכבות ואת לוחות הזמנים בחינם.