Lux Faucet - Testnet Token Distribution
Lux Faucet distributes testnet tokens for Lux Network development. It is a TypeScript application with an Express API server backend and a Next.js ...
Overview
Lux Faucet distributes testnet tokens for Lux Network development. It is a TypeScript application with an Express API server backend and a Next.js frontend. Supports multiple EVM chains and subnets, rate limiting per chain, ReCaptcha verification, ERC-20 token drips, and concurrent transaction handling.
When to use
- Requesting testnet LUX or subnet tokens for development
- Deploying a custom faucet for a Lux subnet or L1
- Integrating a new EVM chain into the live faucet at faucet.lux.network
Quick reference
| Item | Value |
|---|---|
| Repo | github.com/luxfi/faucet |
| Language | TypeScript |
| Package manager | pnpm ( >=8.0.0) |
| Runtime | Node.js ( >=17) |
| Server | Express on port 8000 |
| Frontend | Next.js on port 3000 (@luxfi/faucet-app v2.0.0) |
| Key deps | express, web3, luxfi, express-rate-limit, wagmi, viem, react-google-recaptcha-v3 |
| License | BSD 3-Clause |
| Live | faucet.lux.network |
| Default branch | main |
Project structure
faucet/
server.ts -- Express API server (TypeScript)
types.ts -- Shared type definitions
config.json -- Chain configs, rate limits, ERC-20 tokens
package.json -- Root package (@luxfi/faucet)
pnpm-workspace.yaml
vms/
evm.ts -- EVM chain transaction handler
evmTypes.ts -- EVM type definitions
ERC20Interface.json -- ERC-20 ABI
app/ -- Next.js frontend (@luxfi/faucet-app v2.0.0)
src/ -- React components, pages
next.config.ts
package.json
client/ -- Legacy React frontend (faucet-client)
src/
package.json
contracts/ -- Supporting contracts
middlewares/ -- Rate limiter, captcha verification, URI parsing
scripts/ -- Key generation utilitiesOne-file quickstart
git clone https://github.com/luxfi/faucet.git
cd faucet
# Create .env from example
cp .env.example .env
# Edit .env: set PK (private key with testnet funds) and CAPTCHA_SECRET
# Install dependencies
pnpm install
# Start both server and frontend in development mode
pnpm dev:all
# Server: http://localhost:8000
# Frontend: http://localhost:3000API endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /health | Server health check |
| GET | /api/faucetAddress?chain=C | Get faucet wallet address for a chain |
| GET | /api/getBalance?chain=C | Get faucet balance for a chain |
| GET | /api/getChainConfigs | Get all chain and token configurations |
| POST | /api/sendToken | Request token drip (requires captcha token) |
Send token request body
{
"address": "0x...",
"chain": "C"
}Adding a new subnet
Add chain configuration to the evmchains array in config.json:
{
"ID": "MY_SUBNET",
"NAME": "My Subnet Testnet",
"TOKEN": "MST",
"RPC": "https://rpc.my-subnet.example.com",
"CHAINID": 12345,
"EXPLORER": "https://explorer.my-subnet.example.com",
"IMAGE": "https://example.com/logo.png",
"MAX_PRIORITY_FEE": "2000000000",
"MAX_FEE": "100000000000",
"DRIP_AMOUNT": 2,
"DECIMALS": 18,
"RATELIMIT": {
"MAX_LIMIT": 1,
"WINDOW_SIZE": 1440
}
}Provide a corresponding private key in .env as MY_SUBNET="<key>" or rely on the PK fallback.
Preconfigured chains
| ID | Name | Token | Chain ID |
|---|---|---|---|
| C | Testnet (C-Chain) | LUX | 43113 |
| WAGMI | WAGMI Testnet | WGM | 11111 |
| DFK | DeFi Kingdoms Testnet | JEWEL | 335 |
| SWIMMER | Swimmer Testnet | TUS | 73773 |
Environment variables
PK="fallback private key for all chains"
C="C-chain specific private key (optional)"
CAPTCHA_SECRET="Google ReCaptcha v3 secret"
V2_CAPTCHA_SECRET="Google ReCaptcha v2 secret (optional)"
PORT=8000Development
# Build server and frontend
pnpm build
# Start production mode (after build)
pnpm start
# Dev mode (server only, with hot reload)
pnpm dev
# Dev mode (frontend only)
pnpm dev:app
# Generate a new wallet key
pnpm generate:keyDocker
# Build image
docker build . -t faucet-image
# Run container (server on port 8000, exposed on host port 3000)
docker run -p 3000:8000 --name faucet --env-file .env faucet-image
# Stop / restart
docker stop faucet
docker start faucetRate limiting
Two levels of rate limiting are applied:
- Global: Configured in
config.jsonunderGLOBAL_RL-- applies to all endpoints - Per-chain: Configured per chain in the
RATELIMITobject -- applies to/api/sendToken
The REVERSE_PROXIES setting in GLOBAL_RL controls how many trusted proxies to skip when extracting client IP from x-forwarded-for. Cloudflare's cf-connecting-ip header is used as default.
Related Skills
lux/lux-cli.md-- CLI for network managementlux/lux-node.md-- Validator nodes (provide RPC endpoints)lux/lux-evm.md-- C-Chain and subnet EVM execution