A modern, secure Ethereum Sepolia testnet faucet built with Next.js 15, featuring wallet connectivity, Twitter verification, and comprehensive claim management.
- Multi-wallet Support: Connect with MetaMask, Coinbase Wallet, WalletConnect, and more via RainbowKit
- Twitter Verification: Tweet-to-earn system with 2x bonus rewards
- Mainnet Balance Check: Requires minimum 0.0025 ETH on Ethereum Mainnet to prevent abuse
- Rate Limiting:
- 5-minute cooldown between claims
- Maximum 3 claims per day per wallet
- Daily token budget system for sustainable distribution
- Database Tracking: Complete claim history with wallet addresses, IP addresses, and timestamps
- Responsive Design: Mobile-first UI with Tailwind CSS and custom PayRam branding
- Real-time Status: Transaction tracking and claim verification
- FAQ Section: Comprehensive help documentation for users
- Framework: Next.js 15.0.3 (App Router)
- Language: TypeScript 5
- Styling: Tailwind CSS 3.4
- Blockchain:
- Ethers.js 6.13
- Wagmi 2.12
- Viem 2.21
- RainbowKit 2.1.5
- Database: PostgreSQL with TypeORM 0.3.20
- APIs: Twitter API via twitterapi.io
- Icons: Lucide React
- State Management: React 19 with Hooks
- Node.js 18+ and npm
- PostgreSQL database (can use Neon, Supabase, or local)
- Ethereum wallet private keys for treasury wallets
- Alchemy or Infura RPC endpoints
- Twitter API key (optional, for tweet verification)
- WalletConnect Project ID
-
Clone the repository
git clone https://github.com/yourusername/faucet-payram.git cd faucet-payram -
Install dependencies
npm install
If you encounter peer dependency issues with React 19:
npm install --legacy-peer-deps
-
Configure environment variables
Copy the example environment file:
cp .env.local.example .env.local
Edit
.env.localwith your configuration:# Database Configuration DB_HOST=your-database-host DB_PORT=5432 DB_USERNAME=your-username DB_PASSWORD=your-password DB_DATABASE=faucet_db # Ethereum Configuration ETHEREUM_MAINNET_RPC=https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY SEPOLIA_RPC=https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY # Treasury Wallet Private Keys (comma separated for rotation) TREASURY_PRIVATE_KEYS=0xYOUR_PRIVATE_KEY_1,0xYOUR_PRIVATE_KEY_2 # Faucet Configuration MIN_MAINNET_BALANCE=0.0025 COOLDOWN_MINUTES=5 DAILY_CLAIM_LIMIT=3 MAX_DAILY_CLAIMS=100 FAUCET_AMOUNT=0.05 # Maximum total amount that can be claimed from the faucet in ETH in a day (daily budget) MAX_DAILY_CLAIMS=0.15 # Twitter API (for tweet verification) TWITTER_API_KEY=your_TWITTER_API_KEY # WalletConnect Project ID NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id
-
Set up the database
The database schema will be automatically created when you first run the application thanks to TypeORM's synchronization feature. The
FaucetClaimentity includes:to_wallet_address: Recipient walletfrom_wallet_address: Treasury wallet that sent the fundstweet_id: Unique tweet identifiertweet_account: Twitter account usernameamount: Amount of ETH sentip_address: User's IP address (for additional fraud prevention)time_stamp: Claim timestamp
-
Run the development server
npm run dev
Open http://localhost:3000 in your browser.
faucet-payram/
βββ app/
β βββ api/
β β βββ check-balance/
β β β βββ route.ts # Mainnet balance verification
β β βββ claim/
β β β βββ route.ts # Main claim processing endpoint
β β βββ status/
β β βββ route.ts # Faucet status and health check
β βββ globals.css # Global styles and RainbowKit customization
β βββ layout.tsx # Root layout with providers
β βββ page.tsx # Main faucet interface
β βββ providers.tsx # Wagmi and RainbowKit providers
βββ components/
β βββ LoadingSpinner.tsx # Loading animation component
β βββ StatusBadge.tsx # Status indicator component
β βββ TransactionLink.tsx # Etherscan link component
βββ data/
β βββ FAQ.json # FAQ content
βββ hooks/
β βββ useFaucet.ts # Custom faucet logic hook
βββ lib/
β βββ entities/
β β βββ FaucetClaim.ts # TypeORM entity definition
β βββ config-validator.ts # Environment validation
β βββ constants.ts # App constants and messages
β βββ database.ts # Database connection
β βββ utils.ts # Helper functions
β βββ wagmi-config.ts # Wagmi configuration
βββ public/
β βββ payram_horizontalVividGreen.svg
β βββ payram_logoIconVividGreen.svg
β βββ PayRam_longshadow_long_1.svg
βββ types/
β βββ index.ts # TypeScript type definitions
βββ .env.local.example # Environment variables template
βββ next.config.js # Next.js configuration
βββ tailwind.config.ts # Tailwind CSS configuration
βββ tsconfig.json # TypeScript configuration
The faucet uses Payram's brand colors defined in tailwind.config.ts:
colors: {
"payram-green": "#01E46F", // Primary accent
"payram-dark": "#003401", // Dark green
"payram-lime": "#CAFF54", // Bright lime
"payram-magenta": "#FF00FF", // Accent magenta
"payram-purple": "#6A0DAD", // Accent purple
}Adjust claim limits in your .env.local:
MIN_MAINNET_BALANCE: Minimum ETH required on mainnet (default: 0.0025)COOLDOWN_MINUTES: Minutes between claims (default: 5)DAILY_CLAIM_LIMIT: Max claims per wallet per day (default: 3)MAX_DAILY_CLAIMS: Total ETH budget per day (default: 100)FAUCET_AMOUNT: ETH amount per claim (default: 0.05)
Edit the FAQ section by modifying data/FAQ.json:
[
{
"id": 1,
"question": "Your question here?",
"answer": "Your answer here."
}
]- IP Address Tracking: Records IP addresses to prevent multi-account abuse
- Treasury Wallet Rotation: Supports multiple private keys for load distribution
- Tweet Uniqueness: Each tweet URL can only be used once
- Mainnet Balance Verification: Requires real ETH holdings to claim
- Rate Limiting: Multiple layers of protection against abuse
- Database Validation: Comprehensive checks before ETH distribution
- Environment Validation: Startup checks for critical configuration
CREATE TABLE faucet_claims (
id SERIAL PRIMARY KEY,
to_wallet_address VARCHAR(42) NOT NULL,
from_wallet_address VARCHAR(42) NOT NULL,
tweet_id VARCHAR(255) UNIQUE NOT NULL,
tweet_account VARCHAR(255) NOT NULL,
amount DECIMAL(18,8) NOT NULL,
ip_address VARCHAR(45) NULL,
time_stamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);Process a faucet claim with tweet verification.
Request Body:
{
"walletAddress": "0x...",
"tweetUrl": "https://twitter.com/user/status/..."
}Response:
{
"success": true,
"message": "Successfully claimed 0.05 Sepolia ETH!",
"txHash": "0x...",
"amount": "0.05"
}Verify mainnet balance requirements.
Response:
{
"hasMinBalance": true,
"balance": "0.0050",
"required": "0.0025"
}Check faucet operational status.
Response:
{
"status": "operational",
"network": "sepolia",
"faucetAmount": "0.05"
}- Push your code to GitHub
- Import project in Vercel
- Add environment variables in Vercel dashboard
- Deploy
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]npm run build
npm start# Run development server
npm run dev
# Build for production
npm run build
# Start production server
npm start
# Lint code
npm run lint
# TypeORM CLI
npm run typeorm| Variable | Description | Required | Default |
|---|---|---|---|
DB_HOST |
PostgreSQL host | Yes | - |
DB_PORT |
PostgreSQL port | Yes | 5432 |
DB_USERNAME |
Database username | Yes | - |
DB_PASSWORD |
Database password | Yes | - |
DB_DATABASE |
Database name | Yes | - |
ETHEREUM_MAINNET_RPC |
Mainnet RPC URL | Yes | - |
SEPOLIA_RPC |
Sepolia RPC URL | Yes | - |
TREASURY_PRIVATE_KEYS |
Treasury wallet keys (comma-separated) | Yes | - |
MIN_MAINNET_BALANCE |
Minimum mainnet ETH | No | 0.0025 |
COOLDOWN_MINUTES |
Cooldown period | No | 5 |
DAILY_CLAIM_LIMIT |
Claims per day | No | 3 |
MAX_DAILY_CLAIMS |
Daily budget (ETH) | No | 100 |
FAUCET_AMOUNT |
ETH per claim | No | 0.05 |
TWITTER_API_KEY |
Twitter API key | Yes | - |
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID |
WalletConnect ID | Yes | - |
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License.
- Built with Next.js
- Wallet connectivity by RainbowKit
- Blockchain interactions with Ethers.js
- Icons from Lucide
- Database ORM by TypeORM
For support, email dev@payram.com or visit our website.
Built with β€οΈ by the PayRam Team
colors: {
'payram-green': '#01E46F',
'payram-dark': '#003401',
// Add your custom colors
}Modify environment variables:
MIN_MAINNET_BALANCE=0.0025
COOLDOWN_MINUTES=5
DAILY_CLAIM_LIMIT=3
FAUCET_AMOUNT=0.05Place your logo files in the public directory:
public/logo-horizontal.pngpublic/logo-vertical.pngpublic/logo-badge.png
Update the logo in app/page.tsx.
- Verify PostgreSQL is running
- Check database credentials in
.env.local - Ensure database exists:
createdb faucet_db
- Verify
NEXT_PUBLIC_WALLETCONNECT_PROJECT_IDis set - Check that you're using a supported wallet
- Ensure you're on the correct network
- Verify treasury wallets have sufficient Sepolia ETH
- Check RPC endpoint is working
- Ensure private keys are correct format (include '0x' prefix)
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Open a Pull Request
MIT License - see LICENSE file for details
For issues and questions:
- Open an issue on GitHub
- Contact: support@payram.io
- Built with Next.js 15
- Wallet integration by RainbowKit
- Inspired by QuickNode Faucet design
