Разработка системы quest/task-платформы для крипто-проекта
Quest-платформы — это Galxe, Zealy, Layer3 в роли модели. Механика понятна: пользователь выполняет задания (подписывается на Twitter, совершает swap, холдит токен), получает XP или NFT. Техническая сложность не в самих заданиях, а в верификации — как доказать, что пользователь действительно сделал on-chain действие, а не просто нажал кнопку.
Верификация заданий: on-chain vs off-chain
Off-chain задания
Twitter follow, Discord join, email подписка — верификация через OAuth:
- Twitter: OAuth 2.0 с PKCE, проверка через Twitter API v2 (
GET /2/users/:id/following) - Discord: OAuth2 + Discord Bot API для проверки членства в сервере и наличия роли
- Telegram: Telegram Login Widget + Bot API (
getChatMember)
Всё это серверная логика. Важно хранить OAuth токены зашифрованными и обновлять их — Twitter access token живёт 2 часа.
On-chain задания
Это интереснее и сложнее. Типичные категории:
Holder verification — пользователь должен держать X токенов или NFT определённой коллекции. Верификация: balanceOf(address) вызов через RPC. Просто, но нужно решить проблему времени проверки — баланс мог быть на момент snapshot, а сейчас нет.
Transaction verification — пользователь сделал swap, предоставил ликвидность, сделал бридж. Верификация через индексер или RPC:
// Проверяем, делал ли адрес swap на Uniswap v3 за последние N дней
const logs = await publicClient.getLogs({
address: UNISWAP_V3_ROUTER,
event: parseAbiItem('event Swap(address indexed sender, address indexed recipient, ...)'),
args: { recipient: userAddress },
fromBlock: BigInt(fromBlock),
toBlock: 'latest',
})
const completed = logs.length > 0
Contract interaction — пользователь вызвал конкретную функцию вашего контракта. Самый надёжный способ: emit event в контракте, индексируй его.
Sybil resistance
Главная проблема quest-платформ — sybil атаки. Один человек создаёт 1000 кошельков, выполняет все задания, собирает награды. Механизмы защиты:
-
Gitcoin Passport — score на основе Web2 и Web3 активности. API:
GET /registry/score/:address. Порог score (например, 15+) отсекает большинство sybil аккаунтов. - Proof of Humanity / Worldcoin — biometric proof of unique human. Более надёжно, но friction для пользователей.
- On-chain activity score — проверяем возраст кошелька, количество транзакций, наличие ETH/активов. Новый кошелёк с нулевой историей — красный флаг.
- Rate limiting по IP + fingerprint — не безупречно, но отсекает ленивых ботоводов.
Архитектура системы
Backend
REST API (Next.js API routes или Express)
├── /api/quests — список квестов, статус
├── /api/verify/:taskId — верификация конкретного задания
├── /api/claim — получение награды после выполнения всех заданий
└── /api/leaderboard — топ пользователей по XP
База данных — PostgreSQL:
-
users: address, twitter_id, discord_id, passport_score -
quests: id, title, reward_type, reward_amount, requirements JSON -
task_completions: user_id, task_id, verified_at, proof JSON -
rewards_claimed: user_id, quest_id, tx_hash
Smart contract для наград
Если награда — токены или NFT, нужен контракт:
contract QuestRewards {
mapping(address => mapping(uint256 => bool)) public claimed;
function claimReward(
uint256 questId,
bytes32[] calldata merkleProof
) external {
require(!claimed[msg.sender][questId], "Already claimed");
require(
MerkleProof.verify(merkleProof, questRoots[questId],
keccak256(abi.encodePacked(msg.sender))),
"Invalid proof"
);
claimed[msg.sender][questId] = true;
token.transfer(msg.sender, questRewards[questId]);
}
}
Merkle tree подход: бэкенд формирует список eligible адресов, считает Merkle root, публикует его on-chain. Пользователь получает Merkle proof с сервера и клеймит сам, платя gas. Это снижает нагрузку на сервер и decentralizes claiming.
Frontend
Ключевые экраны:
- Dashboard — активные квесты, прогресс, накопленный XP
- Quest detail — список заданий с статусами (locked/available/completed/claimed)
- Leaderboard — топ участников, можно делать по неделям/всего
- Profile — история наград, connected socials
UX-деталь: статус проверки задания не должен быть синхронным. Пользователь нажал "Verify" — показываем spinner, делаем запрос на бэкенд, бэкенд проверяет on-chain/off-chain данные, возвращает результат. Типичное время — 2–5 секунд для on-chain verification.
Разработка занимает 1–2 недели: базовая система с несколькими типами заданий, верификацией и простой системой наград — 1 неделя. Полная платформа с anti-sybil, Merkle-based claiming, social integrations и leaderboard — 2 недели.







