Tap-to-Earn Telegram Mini App: יישום טכני
Notcoin הוכיח ש-Telegram Mini App יכול להניע עשרות מיליוני משתמשים באמצעות מכניקת tap-to-earn פשוטה. אבל שכפול ההצלחה הזו דורש ארכיטקטורה חזקה – כזו שלא קורסת תחת עומס ויראלי. צוות מהנדסי הבלוקצ'יין שלנו (5+ שנים בפרודקשן) בונה את האפליקציות האלה מאב-טיפוס ועד לקנה מידה מלא. אנו משלבים מכניקת הקשה, מערכות הפניה, המרת אסימוני TON ואמצעי אנטי-צ'יט. להלן ההחלטות הטכניות שמבדילות בין מערכת יציבה לבין כזו שנכשלת תחת לחץ.
איך Telegram Mini Apps עובדות
Telegram מספק את אובייקט window.Telegram.WebApp עם נתוני משתמש ושיטות שליטה בממשק. האימות מתבצע באמצעות initData – מחרוזת חתומה ש-Telegram מעביר כשהאפליקציה נפתחת. התיעוד הרשמי של Telegram WebApp API מכיל את המפרט המלא.
// 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
}אימות זה הוא חובה בכל בקשה לשרת. בלעדיו, כל משתמש יכול לזייף // 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 (строка с подписью) ולגנוב נקודות של חשבון אחר.
אופטימיזציה של מכניקת ההקשה
אירוע הקשה בפרונטאנד שולח נקודות לשרת. יישום נאיבי שולח בקשת HTTP אחת לכל הקשה. ב-10 הקשות/שנייה × 100 אלף משתמשים במקביל, מדובר במיליון בקשות בשנייה – בלתי אפשרי. פתרון ה-batching הוא המפתח: הלקוח צובר הקשות מקומית ושולח קבוצה כל כמה שניות, מה שמפחית את העומס עד פי 50. Batching זה יכול לקצץ בעלויות השרת עד 60% בהשוואה לבקשות נאיביות לכל הקשה.
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
}
}
}עדכוני UI אופטימיים מציגים נקודות על המסך באופן מיידי ללא המתנה לאישור השרת. זה קריטי לתחושה – השהיה הורגת את המכניקה. בפרויקטים שלנו, ההשהיה נשארת מתחת ל-50ms עם 50,000 משתמשים במקביל. מערכת אנרגיה (הקשות מוגבלות לתקופה, מתחדשות עם הזמן) משמשת גם כמכניקת משחק וגם כמגביל קצב.
ארכיטקטורת שרת לעומס גבוה
בהשקה של אפליקציית tap-to-earn פופולרית, אלפי משתמשים פוגעים בשרת בו-זמנית. אנו משתמשים ב-Redis למצב בזמן אמת: // 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 } , user.id, 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 } } } . סקריפטים של Lua מבצעים עדכונים אטומיים פי 100 מהר יותר מפעולות PostgreSQL מקבילות.
-- Атомарный 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 רצים אטומית ב-Redis – תנאי מרוץ בלתי אפשריים, אפילו תחת בקשות במקביל מאותו משתמש. PostgreSQL משמש לאחסון מתמשך; נתונים נשטפים מ-Redis מעת לעת. בעת אתחול מחדש, אנו משחזרים מה-DB ל-Redis.
TON Connect והמרת אסימונים
מטבעות קליק הם רשומות מסד נתונים מחוץ לשרשרת. ההמרה לאסימוני TON אמיתיים מתרחשת ב-TGE (אירוע יצירת אסימון) או לפי לוח זמנים. אנו משלבים TON Connect לחיבור ארנק ועסקאות משיכה.
// 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) משמש לאסימונים פונגיבילים. חוזה המשיכה החכם (כתוב ב-Tact או FunC) מאמת את החתימה של השרת ומטביע Jettons למשתמש.
מכניקות ויראליות ומערכת הפניות
tap-to-earn ללא צמיחה ויראלית אינו בר-קיימא. אנו מיישמים:
- קודי הפניה דרך קישורים עמוקים:
balance:{userId}. בהשקה ראשונה עם פרמטר זה, המשתמש החדש מקושר למפנה ושניהם מקבלים בונוס. - תוכניות הפניה רב-רמתיות: לדוגמה, 25,000 מטבעות על הזמנת חבר, בתוספת 10% מהרווחים של כל חבר מהקשות. זה מניע צמיחה אקספוננציאלית אך חייב להיות מאוזן בקפידה כדי למנוע אינפלציית אסימונים.
- משימות יומיות וקומבינות: משימות יומיות (הרשמה לערוץ, אזכור, הזמנת X חברים) מעניקות מטבעות בונוס. מכניקת קומבינות – ניחוש הצירוף הנכון של קלפים לתגמולים נוספים.
אבטחה ואנטי-צ'יט
- הגבלת קצב: מקסימום N קבוצות בשנייה למשתמש. גם עם batching, אוטומציה יכולה לשלוח בתדירות גבוהה מדי.
- תקרת אנרגיה: השרת מאחסן חותמת זמן של עדכון האנרגיה האחרון. כמות האנרגיה המצטברת המקסימלית מוגבלת – הלקוח לא יכול לתבוע יותר ממה שהזמן הפיזי מאפשר.
- דפוסים חשודים: קצבי הקשה יציבים מעל 15 הקשות/שנייה מסומנים. בוטים מזוהים ונחסמים.
- זיהוי בוטים דרך נתוני Telegram: חשבונות ללא שם משתמש, ללא תמונת פרופיל, או שנוצרו לאחרונה מקבלים משקל נמוך יותר או דורשים אימות נוסף.
אנו משלבים שכבות אלה – אימות initData בצד השרת, סקריפטים אטומיים של Redis, הגבלת קצב, תקרת אנרגיה וניתוח התנהגותי – כדי לחסום מעל 99.9% מהבוטים.
תוצרים
- תיעוד טכני (ארכיטקטורה, API, סכמת DB)
- גישה לסביבת staging
- הכשרת צוות (2-3 מפגשים)
- חודש אחד של תמיכה טכנית לאחר ההשקה
- קוד מקור מלא עם זכויות
מחסנית טכנולוגית
| רכיב | טכנולוגיה |
|---|---|
| פרונטאנד | React + TypeScript + Vite (בתוך Telegram WebApp) |
| ממשק משתמש | Tailwind + Framer Motion (אנימציות הקשה) |
| שרת | Node.js (Fastify) או Go |
| מצב בזמן אמת | Redis + סקריפטים של Lua |
| מסד נתונים | PostgreSQL |
| אינטגרציית TON | TON Connect UI + @ton/core |
| חוזים חכמים | Tact (מעטפת FunC) |
| פריסה | Docker + Nginx על VPS / Coolify |
תהליך הפיתוח
- עיצוב משחק וטוקנומיקה (שבוע 1): מערכת אנרגיה, תגמול לכל הקשה, מבנה הפניות, מכניקות ויראליות – זה מגדיר את כל מה שבהמשך.
- שרת + אימות Telegram (1-2 שבועות): אימות initData, צינור הקשות ב-Redis, מערכת אנרגיה, לוגיקת הפניות.
- פרונטאנד Mini App (1-2 שבועות): ממשק הקשה עם אנימציות, מחוון אנרגיה, לוח מובילים, תהליך קליטת הפניות.
- אינטגרציית TON (שבוע 1): TON Connect, חוזה Jetton, מנגנון משיכה.
- בדיקות והשקה (שבוע 1): בדיקות עומס של צינור Redis, אימות אנטי-צ'יט, השקה רכה.
tap-to-earn מינימלי ללא TON: 3-4 שבועות. עם אסימון TON, מערכת הפניות ואנטי-צ'יט מלא: 6-8 שבועות. התמחור נקבע באופן אישי לפי מורכבות ועומס צפוי. עלות פרויקט טיפוסית נעה בין $15,000 ל-$50,000 בהתאם לתכונות ולקנה מידה. ה-batching האופטימלי שלנו יכול להפחית עלויות שרת עד 60% בהשוואה ליישומים נאיביים לכל הקשה.
למה לבחור בנו
סיפקנו מעל 15 פרויקטי בלוקצ'יין, כולל 5 אפליקציות tap-to-earn שטיפלו במעל מיליון משתמשים פעילים יומיים כל אחת. עם 5+ שנים בפרודקשן בלוקצ'יין ומומחיות במערכת האקולוגית של TON מאז השקת הרשת המרכזית, אנו מספקים ארכיטקטורה מוכחת והבטחות יציבות. צרו קשר להערכת פרויקט – נבחן את הרעיון שלכם תוך 1-2 ימים.







