Реализация подключения Snapshot для голосования DAO в мобильном приложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1735 услуг
Реализация подключения Snapshot для голосования DAO в мобильном приложении
Средний
~3-5 дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    495

Реализация подключения Snapshot для голосования DAO в мобильном приложении

Snapshot — это off-chain система голосования, где пользователь подписывает сообщение EIP-712 своим кошельком, а результат хранится в децентрализованной сети IPFS/Snapshot Hub. Голосование ничего не стоит — нет газа. При этом вес голоса определяется балансом токенов в блокчейне на момент создания предложения (snapshot block).

Интеграция Snapshot в мобильное приложение — это GraphQL API для чтения данных и REST API для отправки голосов с подписью.

Чтение данных: Snapshot 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()
}

Endpoint: https://hub.snapshot.org/graphql. Space ID — уникальный идентификатор DAO в Snapshot (например, uniswap.eth, aave.eth).

Голосование: подпись 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)
}

POST https://hub.snapshot.org/api/msg — endpoint для публикации. В ответ — id голоса (IPFS hash).

Стратегии голосования

Snapshot поддерживает кастомные стратегии определения веса голоса:

  • erc20-balance-of — стандартный баланс токена
  • erc20-votes — делегированный вес через getVotes()
  • delegation — с учётом входящих делегаций
  • quadratic — квадратный корень из баланса
  • Можно комбинировать несколько стратегий

Стратегии читаются из конфигурации Space через GET https://hub.snapshot.org/api/spaces/{spaceId}. Показывай пользователю, какая стратегия используется и сколько голосов у него будет.

Расчёт веса голоса до голосования

// 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
}

Endpoint: https://score.snapshot.org/api/scores. Показывай вес голоса прямо в форме голосования: «Ваш вес: 1 250.4 UNI».

Типы голосования Snapshot

Тип Описание
single-choice Один вариант
approval Несколько вариантов
ranked-choice Ранжирование (IRV)
quadratic Квадратичное голосование
weighted Распределить вес по вариантам

Для каждого типа — своя UI форма. weighted — слайдеры с процентами, сумма = 100%. ranked-choice — drag-and-drop или numbered list.

Сроки: 3–5 дней: GraphQL-запросы списка и деталей предложения, форма голосования с EIP-712 подписью через WalletConnect, отображение веса голоса, поддержка basic типов голосования (single-choice, approval).