פיתוח לוח מחוונים מותאם אישית לזכאות לאיירדרופ
אנו בונים לוח מחוונים שלא רק מציג "זכאי או לא", אלא מספק למשתמשים צעדים מעשיים לשיפור הציון שלהם לפני הצילום (snapshot). זהו כלי שימור חזק: המשתמשים רואים כמה נקודות יש להם, אילו פעולות הם יכולים עדיין לבצע, וכמה הם רחוקים מהדרג הבא. טכנית, זהו מאגד נתונים ממספר מקורות on-chain עם מטמון (caching) — כי שאילתת on-chain אמיתית עבור כל כתובת בכל ביקור הייתה הורגת כל RPC. הניסיון שלנו — למעלה מחמש שנים ב-Web3 ו-30+ פרויקטים מוצלחים — מבטיח יציבות וסקלביליות. קבלו ייעוץ כדי לדון בארכיטקטורה עבור הפרוטוקול שלכם.
לוח המחוונים לא רק מציג סטטוס אלא גם נותן המלצות מעשיות: "אתה צריך עוד שתי הצבעות ב-Snapshot ו-500$ בנפח מסחר כדי להגיע לדרג הזהב." משוב זה מגביר את מעורבות המשתמשים ואת הסבירות להמשך השתתפות באקוסיסטם. אנו בונים בגמישות: חוקי ניקוד ודרגות ניתנים להגדרה כך שיתאימו לכלכלת הטוקנים של כל פרויקט.
כיצד פועל לוח מחוונים לזכאות לאיירדרופ
ארכיטקטורה: מקורות נתונים
ה-subgraph של The Graph הוא המקור העיקרי לפעילות on-chain. ה-subgraph מתעדכן על אירועי חוזה ומספק API מסוג GraphQL. נתונים עבור לוח המחוונים:
query UserActivity($address: String!) {
user(id: $address) {
totalVolume
transactionCount
firstInteractionTimestamp
liquidityProvisions {
amount
timestamp
pool {
id
symbol
}
}
referrals {
count
totalVolume
}
}
}שאילתות ל-The Graph הן בחינם עד למגבלה, מהירות (<200ms), ואינן מכבידות על צמתי RPC.
ה-API של Snapshot.org משמש למעקב אחר השתתפות בממשל. אנו מקבלים את רשימת ההצבעות של משתמש במרחב נתון. לבדיקת יתרות on-chain, אנו משתמשים ב-query UserActivity($address: String!) { user(id: $address) { totalVolume transactionCount firstInteractionTimestamp liquidityProvisions { amount timestamp pool { id symbol } } referrals { count totalVolume } } } של viem — הוא מקבץ מספר קריאות לבקשה אחת של RPC:
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
chain: mainnet,
transport: http()
})
const results = await client.multicall({
contracts: [
{
address: TOKEN_ADDRESS,
abi: erc20Abi,
functionName: 'balanceOf',
args: [userAddress]
},
{
address: STAKING_ADDRESS,
abi: stakingAbi,
functionName: 'stakedAmount',
args: [userAddress]
},
{
address: VESTING_ADDRESS,
abi: vestingAbi,
functionName: 'vestingInfo',
args: [userAddress]
},
]
})בקשת HTTP אחת במקום שלוש — קריטי בעומס גבוה. חוסך עד 66% בקריאות RPC.
מערכת ניקוד וקריטריונים
הזכאות היא בדרך כלל רב-גורמית. מבנה אופייני:
interface EligibilityScore {
total: number
breakdown: {
volumeScore: number // 0-40 баллов: торговый объём
loyaltyScore: number // 0-20 баллов: дата первого взаимодействия
governanceScore: number // 0-20 баллов: голосования на Snapshot
referralScore: number // 0-10 баллов: приведённые пользователи
holdingScore: number // 0-10 баллов: удержание токенов
}
tier: 'bronze' | 'silver' | 'gold' | 'platinum'
estimatedAllocation: bigint | null // null до объявления
missingCriteria: string[]
} multicall הוא החלק השימושי ביותר עבור המשתמש. "אתה צריך עוד שתי הצבעות ב-Snapshot ו-500$ בנפח מסחר לדרג הבא" — זהו מידע מעשי. כיצד מחושב loyaltyScore?
LoyaltyScore תלוי בתאריך האינטראקציה הראשונה של המשתמש עם הפרוטוקול. ככל שהמשתמש התחיל מוקדם יותר, כך הציון גבוה יותר. לדוגמה, אינטראקציה בתוך 30 הימים הראשונים לאחר ההשקה מעניקה מקסימום 20 נקודות, ואז יורדת לינארית לאפס עד היום ה-180. זה מעודד פעילות מוקדמת ומתגמל משתתפים לטווח ארוך.
צד שרת: מטמון ו-API
נתוני on-chain לא משתנים כל שנייה — מטמון הוא חובה.
async function getUserEligibility(address: string): Promise<EligibilityScore> {
const cacheKey = `eligibility:${address.toLowerCase()}`
const cached = await redis.get(cacheKey)
if (cached) return JSON.parse(cached)
const [subgraphData, snapshotVotes, onchainBalances] = await Promise.all([
fetchSubgraphData(address),
fetchSnapshotVotes(address),
fetchOnchainBalances(address),
])
const score = calculateScore(subgraphData, snapshotVotes, onchainBalances)
await redis.setex(cacheKey, 300, JSON.stringify(score))
return score
}TTL של 5 דקות מספיק עבור רוב הנתונים. עבור נתוני snapshot לאחר המועד הסופי, שמרו במטמון לנצח. זה מפחית עומס על RPC ומאיץ את טעינת הדף.
צד לקוח: לוח מחוונים ב-React
לוח המחוונים בנוי על React באמצעות wagmi ו-RainbowKit. רכיב ה-import { createPublicClient, http } from 'viem' import { mainnet } from 'viem/chains' const client = createPublicClient({ chain: mainnet, transport: http() }) const results = await client.multicall({ contracts: [ { address: TOKEN_ADDRESS, abi: erc20Abi, functionName: 'balanceOf', args: [userAddress] }, { address: STAKING_ADDRESS, abi: stakingAbi, functionName: 'stakedAmount', args: [userAddress] }, { address: VESTING_ADDRESS, abi: vestingAbi, functionName: 'vestingInfo', args: [userAddress] }, ] }) מקבל נתונים דרך React Query, שומר אותם במטמון בצד הלקוח, ומציג פס התקדמות דרגות, פירוט ניקוד, ורשימת קריטריונים חסרים. המשתמשים רואים לא רק את הסטטוס הנוכחי שלהם אלא גם את ההקצאה הפוטנציאלית (estimatedAllocation) אם האיירדרופ הוכרז.
הפצת Merkle ותביעה
לאחר הכרזת האיירדרופ — ממשק תביעה. תכנית סטנדרטית: חוזה interface EligibilityScore { total: number breakdown: { volumeScore: number // 0-40 баллов: торговый объём loyaltyScore: number // 0-20 баллов: дата первого взаимодействия governanceScore: number // 0-20 баллов: голосования на Snapshot referralScore: number // 0-10 баллов: приведённые пользователи holdingScore: number // 0-10 баллов: удержание токенов } tier: 'bronze' | 'silver' | 'gold' | 'platinum' estimatedAllocation: bigint | null // null до объявления missingCriteria: string[] } , הוכחה שנוצרת בשרת:
import { StandardMerkleTree } from '@openzeppelin/merkle-tree'
async function getMerkleProof(address: string): Promise<{ proof: string[], amount: bigint }> {
const tree = await loadMerkleTree()
const [index, [addr, amount]] = tree.entries().find(([, [a]]) => a.toLowerCase() === address.toLowerCase())
return { proof: tree.getProof(index), amount: BigInt(amount) }
}בצד הלקוח, כפתור ה-Claim מופעל אם missingCriteria. לאחר התביעה, אנו מציגים את ה-tx hash ומעדכנים את הסטטוס דרך async function getUserEligibility(address: string): Promise<EligibilityScore> { const cacheKey = `eligibility:${address.toLowerCase()}` const cached = await redis.get(cacheKey) if (cached) return JSON.parse(cached) const [subgraphData, snapshotVotes, onchainBalances] = await Promise.all([ fetchSubgraphData(address), fetchSnapshotVotes(address), fetchOnchainBalances(address), ]) const score = calculateScore(subgraphData, snapshotVotes, onchainBalances) await redis.setex(cacheKey, 300, JSON.stringify(score)) return score } . החוזים עוברים ביקורת (Slither, Mythril, Echidna) ובדיקות להתקפות reentrancy ו-flash loan. הזמינו פיתוח לוח מחוונים — אנו מבטיחים אבטחה וביצועים.
מדוע להזמין פיתוח לוח מחוונים מאיתנו?
אנו לא רק מעתיקים פתרונות קוד פתוח. כל לוח מחוונים מעוצב עבור פרוטוקול ספציפי: מדדים ייחודיים, אינטגרציות עם מערכות שותפים, מאפייני כלכלת טוקנים. תהליך העבודה שלנו כולל:
| שלב | משך | תוצאה |
|---|---|---|
| אנליטיקה | 2-5 ימים | מפרט מדדים, מקורות נתונים |
| עיצוב | 3-7 ימים | ארכיטקטורה, מוקאפים, תיעוד API |
| פיתוח | 10-20 ימים | צד שרת, צד לקוח, חוזים חכמים (במידת הצורך) |
| בדיקות | 3-5 ימים | בדיקות יחידה, אינטגרציה, בדיקות עומס |
| השקה ותמיכה | 2-3 ימים | השקה, ניטור, SLA 99.9% |
סה"כ בין שלושה לשישה שבועות תלוי במורכבות. אנו נעריך את הפרויקט שלכם בחינם — פשוט צרו קשר.
מה כלול?
- פיתוח API בצד שרת עם מטמון (Redis, Node.js/Python)
- אינטגרציה עם The Graph, Snapshot, RPC (Ethereum, L2)
- מערכת ניקוד ודרגות עם חוקים מותאמים אישית
- לוח מחוונים בצד לקוח (React, Next.js, wagmi, RainbowKit)
- הפצת Merkle וממשק תביעה
- תיעוד והדרכת צוות
- תמיכה לאחר השקה
צרו קשר כדי לדון בפרויקט שלכם. ב-80% מהמקרים, אנו מציעים פתרון זול ומהיר יותר מאשר גיוס צוות נפרד. קבלו ייעוץ — ואנו נבחר את הארכיטקטורה האופטימלית לתקציב שלכם.







