A full-stack Web3 dashboard that replicates the functionality of t-sender.com, allowing admins to airdrop ERC20 tokens to multiple recipients via a highly gas-optimized smart contract (written in Huff). Built with modular Web3 hooks, secure wallet integration, and a responsive, user-focused interface.
🖼️ This shows the full flow:
- User fills the form with token + recipient data
- Wallet prompts for ERC20 approval
- User confirms the airdrop transaction
This is a Next.js project bootstrapped with create-next-app.
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun devOpen http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying app/page.tsx. The page auto-updates as you edit the file.
This project uses next/font to automatically optimize and load Geist, a new font family for Vercel.
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.
Build a front-end dashboard to interact with the TSender smart contract, enabling admins to airdrop ERC20 tokens to multiple recipients in a single, gas-optimized transaction.
This mimics the functionality of platforms like t-sender.com and demonstrates smart contract interaction, approval flows, and wallet integration with a user-friendly UI.
This dApp supports multiple EVM chains where the TSender airdrop smart contract has already been deployed.
| Chain | Chain ID | TSender Address | Explorer Link |
|---|---|---|---|
| Ethereum Mainnet | 1 | 0x3aD9F29AB266E4828450B33df7a9B9D7355Cd821 |
Etherscan |
| Optimism | 10 | 0xAaf523DF9455cC7B6ca5637D01624BC00a5e9fAa |
Optimistic Etherscan |
| Arbitrum One | 42161 | 0xA2b5aEDF7EEF6469AB9cBD99DE24a6881702Eb19 |
Arbiscan |
| Base | 8453 | 0x31801c3e09708549c1b2c9E1CFbF001399a1B9fa |
BaseScan |
| zkSync Era | 324 | 0x7e645Ea4386deb2E9e510D805461aA12db83fb5E |
zkSync Explorer |
| Sepolia Testnet | 11155111 | 0xa27c5C77DA713f410F9b15d4B0c52CAe597a973a |
Sepolia Etherscan |
| Anvil (Local) | 31337 | 0x5FbDB2315678afecb367f032d93F642f64180aa3 |
Local only |
- ✅ This frontend supports all chains listed above via RainbowKit + Wagmi.
- ✅ You can use any standard ERC20 token on these chains, including custom ones you deploy yourself.
- ✅ All deployments use the same TSender interface — no frontend changes needed across networks.
- ✅ As long as your ERC20 token implements
approve()andtransferFrom(), the UI works out of the box. - ✅ You can also deploy your own ERC20 token to these networks and use this dashboard to airdrop.
- Token:
OanskyToken - Address:
0xC3F8ffA25823E768500F9361D872d2bc7d275fa1 - ✅ Supports full
approve()→airdropERC20()flow - ✅ Fully tested with TSender on Sepolia
🚀 MVP Scope (Core Features Only)
| Feature Area | Feature Description | Status |
|---|---|---|
| 🧠 Smart Contract Logic | Connect wallet with RainbowKit | ✅ Done |
Check ERC20 allowance via readContract |
✅ Done | |
Approve tokens via writeContract |
✅ Done | |
Trigger airdrop via airdropERC20(...) |
✅ Done | |
| Show post-airdrop balances | ✅ Done 🆕 | |
| Graceful error handling | ||
| 🧾 Form & Input Handling | Use shadcn/ui with React Hook Form + Zod |
✅ Done |
| CSV support for addresses + amounts | ❌ Not Yet 🚧 | |
| Validate required fields | 🚧 In Progress | |
| 🔐 Wallet UX | Disable form if wallet not connected | |
| Show connected network visibly | ✅ Done | |
| Prevent double-submit during TX | ||
| 🌍 Deployment & Privacy | Deploy to Fleek or Vercel/Netlify | 🚧 In Progress |
Store secrets in .env.local |
✅ Done | |
| Avoid logging wallet addresses | ✅ Done |
1. 📦 Project Setup
-
Create a React / Next.js project (static).
-
Install and configure the following libraries:
pnpm add wagmi viem @rainbow-me/rainbowkit pnpm add @hookform/resolvers zod react-hook-form
-
Setup
shadcn/uifor the form, inputs, and components.
2. 🔌 Wallet Integration
- Configure wagmi and RainbowKit.
- Wrap your app in the required providers (
WagmiConfig,RainbowKitProvider, etc.). - Add a Connect Wallet button using RainbowKit.
- Create the Airdrop Form using
shadcn/uiwithForm,Input, andTextarea.
3. 🧠 Allowance + Airdrop Flow
The core smart contract function looks like:
function airdropERC20(
address tokenAddress, // ERC20 token to be airdropped
address[] calldata recipients, // Wallets to receive tokens
uint256[] calldata amounts, // Corresponding token amounts
uint256 totalAmount // Sum of all amounts
) external;✅ Step 1: Get Required Data with Wagmi Hooks
- Use
useAccount,useChainId, anduseConfigto access wallet and network info. - Use
useWatchto track form values in real time.
✅ Step 2: Fetch Allowance
- Create a
getApprovedAmounthelper function. - This encapsulates the logic for calling
allowance()on the ERC20 token contract usingreadContractfrom@wagmi/core. - Use it to check if the user has approved the TSender contract to spend tokens.
✅ Step 3: Conditional Logic
Compare the approvedAmount with the total amount needed:
- If
approvedAmount < total, callapprove(...)usingwriteContractAsync. - If approved, or already sufficient, proceed to the airdrop step.
✅ Step 4: Airdrop Tokens
- Call
airdropERC20(...)with the parsed recipient and amount lists. - Wait for transaction confirmation.
- Read and display recipient balances after airdrop using
balanceOf(...).
4. 🚀 Deployment
Deploy this static frontend to:
- Fleek (IPFS-based deployment)
- Vercel or Netlify (for non-IPFS)
- 🔐 Connect Wallet (MetaMask, WalletConnect via RainbowKit)
- 🌐 Supports multiple chains: Mainnet, Optimism, Arbitrum, ZK Sync, Base, Sepolia, Anvil
- 📥 Inputs:
- Token address
- Recipient addresses
- Amounts (textarea or CSV)
- 🔎 Dynamic token data fetching (name, decimals)
- 📊 Live transaction preview (total in wei & formatted)
- ✅ Step-by-step execution:
approvetoken spending for TSender(Airdrop)(Huff) smart contractairdropto multiple recipients
- 🚨 Handles mismatched address/amount inputs with clear errors
- 🧹 Clean, responsive, accessible UI built with Tailwind
📈 Full Roadmap (Planned Improvements)
🧠 Immediate Next Steps
These are either partially done or high-leverage polish tasks.
| 🔥 Priority | Task | Why | Tags |
|---|---|---|---|
| 🧪 High | Playwright E2E Testing | Ensure full user flows work across wallet UX | testing, web3, qa |
| Graceful error handling | Better UX for wallet errors / bad input | ux, web3, bug |
|
| ✅ Medium | CSV Upload Support | Scale-ready UX for large recipient lists | feature, enhancement |
| 🔍 Medium | Validate addresses (EIP-55) | Avoid invalid airdrop failures and wasted gas | security, web3, qa |
| 📊 Medium | Token Logo / Preview | Adds visual polish and trust to token interactions | ux, enhancement, web3 |
| 🔮 Medium | Use simulateContract() + gas |
UX clarity before TX, aligns with Web3 best practices | web3, ux, performance |
🔒 Security Checklist (Common Web3 Pitfalls)
-
✅ Input Sanitization
- Validate addresses (EIP-55 checksum)
- Sanitize all form inputs
- Handle malformed CSV uploads safely
-
✅ Wallet Interaction Safety
- Use
preparedWriteContract(wagmi) - Check for wallet connection before enabling form
- Disable send button during TX
- Use
-
✅ Smart Contract Precautions
- Check token allowance before
airdrop() - Show gas estimate before confirmation
- Graceful error messages on
revert
- Check token allowance before
-
✅ Sensitive Data Handling
- Avoid logging wallet addresses or TX hashes unnecessarily
- Don’t persist user data unless encrypted
-
✅ Read-Only Queries
- Use
publicClient.readContractfor non-sensitive reads - Prefer event listeners / The Graph over polling
- Use
-
✅ User Safety UX
- Warn on unsupported networks
- Show token symbol, icon, and decimals clearly
- Display connected chain/network name visibly
-
✅ Deployment Hygiene
- Store API keys in
.env.local - Never expose private keys or secrets client-side
- Store API keys in
🔁 Performance & Scaling
- Optimistic UI feedback (e.g. "Sending..." before confirmation)
- Progress tracker for large sends
- Pagination or batching for >1,000 recipients
🧠 Recipient Address Management
- ENS name resolution
- Address validation (checksum + format)
- Save recipient lists
- Option 1:
localStorage - Option 2: IPFS
- Option 1:
📊 Analytics & Token Insights
- Pie Chart (Recharts + Tailwind)
- Show % token distribution per recipient
- Optional: Group wallets by category
📚 Airdrop History & Analytics
- Integrate The Graph for historical airdrop data
- Display previous distributions
- Link to transaction explorer (e.g. Etherscan)
🎥 Project Demo & Documentation
- Write walkthrough script
- Record Loom video (1–2 min)
- Wallet connect
- Input form
- Submit → TX confirmation
- Design PDF or visual flow (Figma-style)
🚦 UX & Performance Audit
- Run Lighthouse Audit
- Performance
- Accessibility
- Best Practices
- SEO
- Include audit screenshot or score summary in docs
- Framework: Next.js (React + TypeScript)
- Styling: Tailwind CSS
- Libraries: Wagmi · Viem · RainbowKit · Ethers.js
- Network Support: Sepolia (testnet), Anvil (local)
- Smart Contract: Gas-optimized Huff contract (TSender)
- Wallet Connection: RainbowKit + custom hooks
- Form Handling: React Hook Form + Zod
- Logic: Custom hooks for allowance, airdrop, approval
- Validation: CSV + text input parsing
- ✅ Unit Testing: Jest
- ⚙️ Local Testnet: Anvil (via Foundry)
- 🔄 Planned: E2E testing with Playwright
- ✅ ESLint + Prettier
- ✅ Husky pre-commit hooks (
lint-staged, formatting) - ⏳ Planned: GitHub Actions for CI
- ⏳ Planned: Performance audits with Lighthouse
- ⏳ Planned: Recharts (token distribution graphs)
- ✅ Frontend: Netlify (Live on Sepolia)
- ⏳ Optional: Fleek (IPFS static hosting)
📂 Project Structure (Simplified)
/components → UI elements (buttons, form sections)
/hooks → Custom Web3 logic (approve, airdrop)
/pages → Next.js routes (index, success, etc.)
/lib → Constants, utilities, config (RainbowKit)
/public → Static assets
/docs → Detailed tech overview
- Built by @oanskyy
- Inspired by t-sender.com (gas optimization approach)
MIT © 2025 Oana Anghelachi



