Разработка Telegram Mini App для tap-to-earn
Notcoin в 2024 показал, что Telegram Mini App может собрать аудиторию в десятки миллионов пользователей через простейшую механику: нажимать кнопку, зарабатывать монеты. После него волна: Hamster Kombat, Blum, Major — каждый со своими вариациями. Tap-to-earn — это не про глубокую геймплейную механику, это про virality, retention и эффективный onboarding в TON экосистему.
С технической точки зрения: React приложение внутри Telegram WebApp, backend на Node.js/Go, TON Connect для кошелька, off-chain хранение очков с on-chain конвертацией при листинге.
Telegram Mini App: технический фундамент
Telegram предоставляет window.Telegram.WebApp — объект с данными пользователя и методами управления интерфейсом. Аутентификация через initData — строку, которую Telegram передаёт в момент открытия приложения.
// Frontend: получение данных пользователя
const tg = window.Telegram.WebApp
tg.ready() // сообщаем Telegram, что app готов
tg.expand() // разворачиваем на весь экран
const user = tg.initDataUnsafe.user
// { id: 123456789, first_name: "Ivan", username: "ivan_user", ... }
// ВАЖНО: initDataUnsafe — непроверенные данные на клиенте
// Для backend запросов передаём tg.initData (строка с подписью)
// Backend: верификация initData
import { createHmac } from 'crypto'
function verifyTelegramAuth(initData: string, botToken: string): boolean {
const params = new URLSearchParams(initData)
const hash = params.get('hash')
params.delete('hash')
// Сортируем и concatenate
const dataCheckString = Array.from(params.entries())
.sort(([a], [b]) => a.localeCompare(b))
.map(([k, v]) => `${k}=${v}`)
.join('\n')
const secretKey = createHmac('sha256', 'WebAppData').update(botToken).digest()
const expectedHash = createHmac('sha256', secretKey)
.update(dataCheckString).digest('hex')
return hash === expectedHash
}
Эта верификация — обязательная на каждом backend запросе. Без неё любой пользователь может подделать user.id и получить очки другого аккаунта.
Tap механика и оптимизация производительности
Tap = событие на frontend → send очки на backend. Наивная реализация: каждый tap = HTTP запрос. При 10 tap/сек × 100k concurrent пользователей = 1M RPS. Это не реально.
Batching тапов. Клиент аккумулирует тапы локально, отправляет батч каждые 2-5 секунд:
class TapBatcher {
private pendingTaps = 0
private flushInterval: ReturnType<typeof setInterval>
constructor(private userId: number, private flushEveryMs = 3000) {
this.flushInterval = setInterval(() => this.flush(), flushEveryMs)
}
tap(count: number = 1) {
this.pendingTaps += count
// Immediate optimistic UI update
}
async flush() {
if (this.pendingTaps === 0) return
const toSend = this.pendingTaps
this.pendingTaps = 0
try {
await api.post('/taps', { userId: this.userId, count: toSend })
} catch {
// Если запрос упал — добавляем обратно (или логируем потерю)
this.pendingTaps += toSend
}
}
}
Optimistic UI. Очки на экране обновляются мгновенно при тапе, без ожидания backend ответа. Это критично для feel — задержка убивает механику.
Energy система. Ограничение количества тапов в период через energy pool: каждый tap тратит 1 energy, energy регенерирует N/час. Это и game mechanic, и rate limiter.
Backend архитектура под высокую нагрузку
При запуске популярного tap-to-earn — тысячи concurrent пользователей.
Redis для real-time состояния. Все игровые данные в памяти: balance:{userId}, energy:{userId}, lastTap:{userId}. Lua script для атомарного обновления:
-- Атомарный tap: списать energy, добавить баланс
local energy = tonumber(redis.call('GET', KEYS[1])) or 1000
local taps = tonumber(ARGV[1])
local energyCost = taps
if energy < energyCost then
return {0, energy} -- не хватает energy
end
redis.call('DECRBY', KEYS[1], energyCost)
redis.call('INCRBY', KEYS[2], taps * tonumber(ARGV[2])) -- * reward per tap
return {1, energy - energyCost}
Lua script выполняется атомарно в Redis — race condition исключён. Это важно при параллельных запросах от одного пользователя.
PostgreSQL для persistence. Периодически (каждые N минут или по событию) данные из Redis записываются в PostgreSQL. При рестарте — восстановление из БД в Redis.
TON Connect и конвертация очков
Клик-монеты существуют off-chain как записи в базе данных. Конвертация в реальные TON токены — отдельный процесс, обычно происходит при TGE (Token Generation Event) или по расписанию.
// TON Connect интеграция
import { TonConnectUI } from '@tonconnect/ui-react'
const tonConnect = new TonConnectUI({
manifestUrl: 'https://your-app.com/tonconnect-manifest.json'
})
// Подключение кошелька
const wallet = await tonConnect.connectWallet()
// После листинга: claim токены
async function claimTokens(userId: number) {
const claimData = await api.post('/prepare-claim', { userId })
// claimData содержит подписанный payload от backend
await tonConnect.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 300,
messages: [{
address: CLAIM_CONTRACT_ADDRESS,
amount: '50000000', // 0.05 TON для gas
payload: claimData.payload, // base64 encoded
}]
})
}
TON Jetton стандарт (аналог ERC-20) — стандарт для fungible токенов в TON. Claim контракт на FunC/Tact верифицирует подпись backend-а и минтит Jettons пользователю.
Вирусные механики и реферальная система
Tap-to-earn без virality — нежизнеспособно. Реферальная система — обязательный элемент:
Реферальный код — deep link вида https://t.me/YourBot?startapp=ref_userId. При первом запуске с этим параметром: пользователь привязывается к рефереру, оба получают бонус.
Многоуровневые реферальные программы. Hamster Kombat делал: за друга 25k монет, за каждый tap друга 10% рефереру. Это экспоненциальный рост, но и экспоненциальная инфляция токена.
Daily tasks и combo. Ежедневные задания (подписка на канал, упоминание, invite X friends) дают бонусные монеты. Combo механика — угадать правильную комбинацию из карточек за bonus reward.
Безопасность и anti-cheat
Rate limiting по userId. Максимум N батчей в секунду на пользователя. Даже при batching, автоматизация может отправлять слишком часто.
Energy ceiling. Сервер хранит timestamp последнего energy update. Максимальный накопленный energy ограничен. Клиент не может «заявить» больше, чем позволяет физическое время.
Подозрительные паттерны. Если tap rate > физически возможного для человека (>15 tap/сек стабильно) → флаг. Ботов выявляют и банят.
Bot detection через Telegram данные. Аккаунты без username, без фото, созданные недавно — взвешиваются ниже или требуют дополнительной верификации.
Стек
| Компонент | Технологии |
|---|---|
| Frontend | React + TypeScript + Vite (внутри Telegram WebApp) |
| UI | Tailwind + Framer Motion (анимации тапов) |
| Backend | Node.js (Fastify) или Go |
| Real-time state | Redis + Lua scripts |
| Database | PostgreSQL |
| TON интеграция | TON Connect UI + @ton/core |
| Smart contracts | Tact (FunC wrapper) |
| Deploy | Docker + Nginx на VPS / Coolify |
Процесс разработки
Game design и tokenomics (1 неделя). Energy система, reward per tap, реферальная структура, вирусные механики. Это определяет всё дальнейшее.
Backend + Telegram auth (1-2 недели). initData верификация, Redis tap pipeline, energy система, реферальный механизм.
Frontend Mini App (1-2 недели). Tap интерфейс с анимациями, energy индикатор, leaderboard, referral onboarding.
TON интеграция (1 неделя). TON Connect подключение, Jetton контракт, claim механизм.
Тестирование и launch (1 неделя). Нагрузочное тестирование Redis pipeline, тест anti-cheat, soft launch.
Минимальный tap-to-earn Telegram Mini App без TON — 3-4 недели. С TON токеном, реферальной системой и полным anti-cheat — 6-8 недель.







