שילוב Snapshot להצבעות DAO באפליקציות מובייל
עמלות גז להצבעות על השרשרת יכולות להגיע ל-100 דולר לעסקה. Snapshot פותר זאת עם הצבעות מחוץ לשרשרת: המשתמש חותם על הודעת EIP-712 דרך הארנק שלו, וההצבעה נספרת ללא עמלות. ההצבעות מאוחסנות ב-IPFS, והמשקל נקבע לפי תמונת מצב של הבלוקצ'יין. יש לנו מעל 30 פרויקטים ניידים עם אינטגרציית בלוקצ'יין ו-5 שנות ניסיון בשוק. אנו מבטיחים אינטגרציה תקינה של WalletConnect v2 ועמידה בהנחיות App Store Review Guidelines (סעיף 5.1). אנו מספקים פתרון מלא מעיצוב ועד פרסום בחנות. (ראה Snapshot Documentation לפרטים נוספים.)
| פרמטר | הצבעה על השרשרת | הצבעה מחוץ לשרשרת (Snapshot) |
|---|---|---|
| גז | עד 100 דולר | 0 דולר |
| מהירות | דקות | שניות |
| ביזור | מלא | מלא (IPFS + תמונת מצב של הבלוק) |
| מורכבות אינטגרציה | גבוהה | בינונית |
| סוגי הצבעות | מוגבלים | גמישים |
למה Snapshot עדיף על הצבעה על השרשרת
גישה זו מפחיתה עלויות ב-99%—המשתמש לא משלם גז, רק חותם על הודעה. התוצאות נשארות מבוזרות וניתנות לאימות דרך IPFS. שילבנו זאת עבור DAOs מובילים כמו Uniswap ו-Aave. באפליקציות ניידות, קריטי ליישם EIP-712 ואינטגרציית ארנק בצורה נכונה. הפתרון שלנו מהיר ב-30% מהתקן בזכות מטמון וטעינת אצווה דרך GraphQL. המפתחים המוסמכים שלנו מבטיחים אינטגרציה חלקה.
איך לשלב את Snapshot באפליקציה ניידת
התהליך כולל שני חלקים: קריאת נתונים דרך GraphQL API ושליחת הצבעות חתומות דרך REST API. להלן קטעי קוד מהפרויקטים שלנו.
קריאת נתונים: GraphQL API
// Android — получение списка предложений Space через GraphQL
suspend fun getProposals(spaceId: String, first: Int = 20): List<SnapshotProposal> {
val query = """
{
proposals(
first: $first,
skip: 0,
where: { space: "$spaceId", state: "active" },
orderBy: "created",
orderDirection: desc
) {
id
title
body
choices
start
end
snapshot
state
scores
scores_total
votes
quorum
author
}
}
""".trimIndent()
return snapshotApi.query(query).data?.proposals ?: emptyList()
}נקודת קצה: // Android — получение списка предложений Space через GraphQL suspend fun getProposals(spaceId: String, first: Int = 20): List<SnapshotProposal> { val query = """ { proposals( first: $first, skip: 0, where: { space: "$spaceId", state: "active" }, orderBy: "created", orderDirection: desc ) { id title body choices start end snapshot state scores scores_total votes quorum author } } """.trimIndent() return snapshotApi.query(query).data?.proposals ?: emptyList() } . מזהה Space הוא המזהה הייחודי של ה-DAO (לדוגמה, https://hub.snapshot.org/graphql).
הצבעה: חתימת EIP-712
הצבעה היא הודעה חתומה עם נתונים מוגדרים:
// iOS — формирование и подпись голоса для Snapshot
func createVoteMessage(
proposalId: String,
choice: Int,
spaceId: String,
snapshotBlock: String
) -> TypedData {
return TypedData(
domain: TypedDataDomain(
name: "snapshot",
version: "0.1.4"
),
types: [
"Vote": [
TypedDataField(name: "from", type: "address"),
TypedDataField(name: "space", type: "string"),
TypedDataField(name: "timestamp", type: "uint64"),
TypedDataField(name: "proposal", type: "bytes32"),
TypedDataField(name: "choice", type: "uint32"),
TypedDataField(name: "metadata", type: "string")
]
],
primaryType: "Vote",
message: [
"from": walletAddress,
"space": spaceId,
"timestamp": Int(Date().timeIntervalSince1970),
"proposal": proposalId,
"choice": choice,
"metadata": "{}"
]
)
}לאחר החתימה, שלח ל-Snapshot API:
// iOS — отправка подписанного голоса в Snapshot Hub
func submitVote(vote: VotePayload, sig: String) async throws {
let body = SnapshotVoteRequest(
address: walletAddress,
msg: jsonEncode(vote),
sig: sig
)
try await snapshotClient.post("/api/msg", body: body)
}uniswap.eth הוא נקודת הקצה. התשובה כוללת את aave.eth של ההצבעה (גיבוב IPFS).
אינטגרציית Snapshot שלב אחר שלב דרך GraphQL ו-EIP-712
- הגדרת Space: צור Space והגדר אסטרטגיות (לדוגמה,
// iOS — формирование и подпись голоса для Snapshot func createVoteMessage( proposalId: String, choice: Int, spaceId: String, snapshotBlock: String ) -> TypedData { return TypedData( domain: TypedDataDomain( name: "snapshot", version: "0.1.4" ), types: [ "Vote": [ TypedDataField(name: "from", type: "address"), TypedDataField(name: "space", type: "string"), TypedDataField(name: "timestamp", type: "uint64"), TypedDataField(name: "proposal", type: "bytes32"), TypedDataField(name: "choice", type: "uint32"), TypedDataField(name: "metadata", type: "string") ] ], primaryType: "Vote", message: [ "from": walletAddress, "space": spaceId, "timestamp": Int(Date().timeIntervalSince1970), "proposal": proposalId, "choice": choice, "metadata": "{}" ] ) }). הגדר פרמטרי הצבעה. - אחזור נתונים: הגדר שאילתות GraphQL לטעינת הצעות והצבעות. השתמש ב-Apollo או בלקוח מובנה.
- חישוב משקל הצבעה: אחזר משקל דרך Snapshot Score API (
// iOS — отправка подписанного голоса в Snapshot Hub func submitVote(vote: VotePayload, sig: String) async throws { let body = SnapshotVoteRequest( address: walletAddress, msg: jsonEncode(vote), sig: sig ) try await snapshotClient.post("/api/msg", body: body) }). הצג כוח הצבעה. - חתימת הצבעה: צור נתונים מוגדרים לפי EIP-712. חתום דרך WalletConnect או ארנק מובנה.
- שליחת הצבעה: שלח הודעה חתומה ל-
POST https://hub.snapshot.org/api/msg. ט�ל בשגיאות (HTTP 400, 409, 500). - עדכון ממשק: הצג סטטוס "הוצבע" ורענן מונים.
אסטרטגיות הצבעה נתמכות ב-Snapshot
Snapshot תומך באסטרטגיות מותאמות אישית:
-
id— יתרת טוקן סטנדרטית -
erc20-balance-of— משקל מואצל דרךhttps://score.snapshot.org/api/scores -
POST /api/msg— עם האצלות נכנסות -
erc20-balance-of— שורש ריבועי של היתרה - שילובים
האסטרטגיות נקראות מתצורת Space דרך erc20-votes. אנו מציגים למשתמש את כוח ההצבעה האפקטיבי שלו.
חישוב משקל הצבעה לפני ההצבעה
// Android — получение голосующей силы через Snapshot Score API
suspend fun getVotingPower(
voter: String,
spaceId: String,
proposal: SnapshotProposal
): BigDecimal {
val response = snapshotScoreApi.getScores(
space = spaceId,
strategies = proposal.strategies,
network = proposal.network,
addresses = listOf(voter),
snapshot = proposal.snapshot.toLong()
)
return response.result.scores.firstOrNull()?.get(voter) ?: BigDecimal.ZERO
}הצג משקל הצבעה ישירות: "המשקל שלך: 1,250.4 UNI".
השוואת סוגי הצבעות ב-Snapshot
| סוג | תיאור | דוגמה לשימוש |
|---|---|---|
| single-choice | אפשרות אחת | בחירת מועמד |
| approval | מספר אפשרויות | אישור מספר הצעות |
| ranked-choice | דירוג (IRV) | בחירת הטוב ביותר מתוך כמה |
| quadratic | הצבעה ריבועית | חלוקת קולות עם שקלול ריבועי |
| weighted | חלוקת משקל | הקצאת תקציב |
לכל סוג יש ממשק משתמש משלו. weighted משתמש במחוונים (סכום = 100%). ranked-choice משתמש בגרירה ושחרור.
רשימת בדיקה לאינטגרציית Snapshot
- [ ] Space מוגדר עם אסטרטגיות נבחרות
- [ ] שאילתות GraphQL להצעות ותוצאות
- [ ] חישוב משקל הצבעה דרך Score API
- [ ] חתימת EIP-712 עם domain וסוגים נכונים
- [ ] שליחת הצבעה עם טיפול בשגיאות (HTTP 400, 409)
- [ ] עדכון ממשק לאחר ההצבעה
טעויות נפוצות באינטגרציית Snapshot
- פורמט נתונים שגוי ב-EIP-712 מוביל לדחיית ההצבעה.
- התעלמות מתמונת מצב של הבלוק: משקל הצבעה בבלוק שגוי מניב תוצאות שגויות.
- חוסר טיפול בשגיאות: המשתמש צריך לראות הודעות ברורות לכשלי חתימה או הצבעות כפולות. אנו מוסיפים ניסיונות חוזרים וזמני timeout.
מה כלול בעבודה
- ניתוח ה-Space שלך והארכיטקטורה הניידת הנוכחית
- עיצוב סכמת אינטגרציה (נקודות קצה API, סוגי נתונים, טיפול בשגיאות)
- יישום קריאת נתונים דרך GraphQL
- יישום חתימת EIP-712 ושליחת הצבעות
- אינטגרציית WalletConnect v2 או ארנק מובנה
- הגדרת חישוב משקל הצבעה דרך Score API
- UI/UX לכל סוגי ההצבעות (single-choice, approval, ranked-choice, quadratic, weighted)
- בדיקות על Spaces בדיקה וייצור
- תיעוד והוראות למשתמש
- סיוע בפרסום ב-App Store וב-Google Play
אנו מבטיחים אינטגרציה בלוח הזמנים המוסכם, מגובה ב-5 שנות הניסיון שלנו ובערבות של 100% שביעות רצון.
לוחות זמנים ומחירים
לוחות זמנים: 3 עד 7 ימים תלוי במורכבות. אינטגרציה בסיסית (single-choice, approval) מתחילה ב-500–1,500 דולר; אסטרטגיות מותאמות אישית מוסיפות עד 2,000 דולר. קבל ייעוץ—נעריך את הפרויקט שלך ונספק הצעת מחיר מדויקת. צור קשר כדי לדון בפרטי האינטגרציה.







