Discord NFT Role Distribution Bot Development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Discord NFT Role Distribution Bot Development
Medium
~3-5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Discord Bot for NFT Role Distribution

Token gating is standard practice for NFT communities. Hold an NFT from a collection and you get access to private channels, early access, exclusive drops. Technically it's verification: wallet with required NFT → Discord account → role. The task looks simple, but between "verification" and "permanent actual access" lies an infrastructure layer that fails predictably.

System Architecture

Wallet ↔ Discord Connection

User clicks "Verify" → redirects to verification page → connects wallet via WalletConnect v2 → signs a message (no gas required) → server verifies signature → saves {discordId: walletAddress}.

Message signing is not a transaction; users pay nothing. Standard verification message:

Verify Discord: username#1234
Nonce: a3f8b2c1
Timestamp: 1711234567

Nonce is a random string, unique per session, with 5-minute TTL. Without nonce, replay attacks are possible: a copied signature can be reused.

Backend signature verification:

import { verifyMessage } from 'viem';

const isValid = await verifyMessage({
    address: claimedAddress,
    message: expectedMessage,
    signature: userSignature
});

NFT Ownership Check: Three Approaches

Direct RPC call. balanceOf(wallet, tokenId) via ethers.js or viem. Simple, works for small collections. Problem: with 10,000 users, you make 10,000 RPC calls per check.

Alchemy/Moralis NFT API. getNFTsForOwner(wallet, contractAddress) — one request returns all tokens. Fast, but dependent on external service. If Alchemy goes down, bot doesn't work.

The Graph subgraph. Index Transfer events, build {owner: [tokenIds]} mapping. Fast GraphQL query. Indexing lag ~1-5 minutes — if token is sold quickly, user keeps role for 5 more minutes.

For production bots, we use Alchemy NFT API as primary with The Graph as backup and direct RPC as last fallback.

Discord Bot: Slash Commands and Event Handling

Bot implemented in discord.js v14. Key slash commands:

  • /verify — start verification, bot sends ephemeral message with link
  • /check — forced ownership check (for users who sold tokens)
  • /roles — show all roles and requirements

Roles assigned via guild.members.cache.get(userId)?.roles.add(roleId). Requires MANAGE_ROLES permission and bot role above assigned roles in hierarchy—common setup error.

async function syncUserRoles(userId: string, wallet: string): Promise<void> {
    const member = await guild.members.fetch(userId);
    const ownedTokens = await getNFTsForOwner(wallet, CONTRACT_ADDRESS);
    
    for (const [roleId, requirement] of ROLE_REQUIREMENTS) {
        const qualifies = checkQualification(ownedTokens, requirement);
        if (qualifies && !member.roles.cache.has(roleId)) {
            await member.roles.add(roleId);
        } else if (!qualifies && member.roles.cache.has(roleId)) {
            await member.roles.remove(roleId);
        }
    }
}

Periodic Resynchronization

Critical moment: user sells NFT and must lose role. Bot doesn't receive Discord event—it must check periodically itself.

Cron job every 10-30 minutes: for each verified user, check current balance, update roles. With 1,000 users and 30-minute interval — ~33 API requests per minute. Fits within Alchemy limits.

Optimization: listen to Transfer events via WebSocket (Alchemy WebSocket API). On any Transfer, check if verified wallet is involved, immediately update role. Reduces latency to seconds.

const provider = new WebSocketProvider(ALCHEMY_WS_URL);
const contract = new Contract(NFT_ADDRESS, erc721Abi, provider);

contract.on('Transfer', async (from, to, tokenId) => {
    const affectedWallets = [from, to].filter(w => w !== ethers.ZeroAddress);
    for (const wallet of affectedWallets) {
        await syncRolesForWallet(wallet);
    }
});

Multiple Collections and Trait-Based Roles

Real projects require complex conditions:

  • Hold ≥3 tokens from collection A → VIP role
  • Hold token with trait "Legendary" → Legendary role
  • Hold token from collection A and collection B → Collab role

For trait-based roles, need metadata access. Alchemy getNFTsForOwner returns tokenMetadata including attributes. Role config in JSON:

{
  "LEGENDARY_ROLE_ID": {
    "contract": "0x...",
    "minBalance": 1,
    "requiredTrait": {"trait_type": "Rarity", "value": "Legendary"}
  }
}

Stack

Component Technology
Bot discord.js v14, TypeScript
Wallet connect WalletConnect v2 (web app for verification)
NFT data Alchemy NFT API + WebSocket
Database PostgreSQL (userId ↔ wallet mapping)
Hosting Railway or Render (persistent process)
Signature verification viem verifyMessage

Timeline Estimates

Basic bot with one collection and one role — 3-4 days. Extended with multiple collections, trait-based roles and real-time sync via WebSocket — 4-5 days.