Розробка Discord-бота верифікації NFT-HOLDERS
NFT-проект без системи верифікації HOLDERS — це публічний Discord, де обдатели токенів ничем не відрізняються від випадкових відвідувачів. Holder-only канали, early access до нових мінтів, governance-голосування — все це вимагає proof of ownership, який оновлюється при кожному трансфері токена. Технічно завдання складається з трьох шарів: on-chain перевірка через RPC, OAuth авторизація через Discord, та періодична ревалідація ролей при зміні балансу.
Архітектура системи верифікації
Wallet signature flow
Стандартний flow верифікації без зберігання приватних ключів:
- Користувач натискає
/verifyв Discord - Бот відправляє йому DM з унікальним challenge message (UUID + timestamp)
- Користувач підписує message в MetaMask через WalletConnect або custody wallet
- Відправляє підпис боту
- Бот відновлює адресу через
ecrecover(абоviem.verifyMessage()), перевіряє баланс NFT через RPC
import { verifyMessage } from 'viem';
const recoveredAddress = await verifyMessage({
address: claimedAddress,
message: challengeMessage,
signature: userSignature,
});
if (!recoveredAddress) throw new Error('Invalid signature');
const balance = await publicClient.readContract({
address: NFT_CONTRACT,
abi: erc721Abi,
functionName: 'balanceOf',
args: [claimedAddress],
});
Challenge message повинен містити timestamp з коротким TTL (5-10 хвилин). Без TTL — атакуючий може повторно використати перехоплену підпис (signature replay). Храним використані challenges у Redis з автоматичним истеченням.
Мультиконтрактна верифікація
Більшість реальних проектів верифікує не один контракт, а кілька: основна колекція + companion collection + staking контракт. Ролі видаються по комбінації умов:
Gold holder = balance(MainNFT) >= 1 AND balance(CompanionNFT) >= 1
Diamond holder = balance(MainNFT) >= 5
Staker = stakedBalance(StakingContract, address) >= 1
Для staking-контрактів потрібен окремий ABI виклик: стандартний balanceOf ERC-721 не враховує застейканих токенів (вони належать staking контракту, не користувачу). Викликаємо stakedTokensOf(address) або аналог з кастомного staking контракту.
Періодична ревалідація ролей
Це критична частина, яку часто пропускають. Користувач продав NFT — його Discord роль повинна бути відозвана. Реалізуємо через scheduled job:
// Cron job кожні 6-12 годин
async function revalidateAllHolders() {
const verifiedUsers = await db.getAllVerifiedUsers();
for (const user of verifiedUsers) {
const currentBalance = await checkNFTBalance(user.walletAddress);
const requiredRoles = calculateRoles(currentBalance);
await syncDiscordRoles(user.discordId, requiredRoles);
}
}
Частота ревалідації — баланс між актуальністю та RPC rate limits. Для високоактивних колекцій (> 100 трансфертів/день) — кожні 6 годин. Для повільних — раз в 24 годин. Альтернатива — event listening через WebSocket subscription на Transfer события контракту, але це вимагає стабільного WebSocket з'єднання 24/7.
Зберігання даних та GDPR
Храним мінімум: {discordId, walletAddress, verifiedAt}. Без додаткових on-chain даних. В ЄС при наявності європейської аудиторії — право на видалення через /unverify команду. Реалізуємо purge при видаленні запису з Discord сервера.
Пароль до wallet — ніколи не запитуємо. Підпис message ≠ доступ до коштів, але явно пояснюємо це користувачам у інтерфейсі бота.
Стек реалізації
Discord.js v14 — основний фреймворк бота. Slash commands (не message commands — Discord deprecated). Кнопки для inline верифікації без DM якщо потрібно.
viem для on-chain взаємодії — легше ethers.js по bundle size, строго типізований.
PostgreSQL для зберігання верифікованих користувачів. Redis для challenge message cache.
Alchemy/QuickNode як RPC провайдер — нативні WebSocket для event subscriptions, вищі rate limits ніж публічні ноди.
Для multi-chain колекцій (Ethereum + Polygon, наприклад) — окремий publicClient для кожного чейна, агрегація результатів перед виданням ролей.
Процес роботи
Настройка (0.5 дня). Реєстрація Discord Application, настройка bot permissions (MANAGE_ROLES обов'язково), конфігурація ролей на сервері.
Розробка (2-3 дні). Core бот з verify flow, мультиконтрактна логіка, scheduled ревалідація, база даних, деплой на VPS (Docker + PM2).
Тестування (0.5-1 день). Тестування на staging сервері: коректність видачі ролей, ревалідація після трансфера, edge cases (нулевий баланс, множественні гаманці).
Базовий бот з верифікацією однієї контракту — 2-3 дні. З мультиконтрактною логікою, кастомними ролями та event-driven ревалідацією — 4-5 днів. Вартість розраховується індивідуально.







