Proxy backend for QuickNode Faucet API with JWT validation (Para/Privy) and rate limiting.
cp config/config.example.json config/config.json
cp .env.example .env
docker-compose up -dcurl -X POST http://localhost:8080/endpoint \
-H "Content-Type: application/json" \
-d '{"visitorId": "fp_xxx", "walletAddress": "0x..."}'curl -X POST http://localhost:8080/endpoint \
-H "Authorization: Bearer <para-jwt>" \
-d '{"visitorId": "fp_xxx"}'curl -X POST http://localhost:8080/endpoint \
-H "Authorization: Bearer <privy-identity-token>" \
-d '{"visitorId": "fp_xxx"}'- Create distributor
bun run script/create-distributor.ts "My Faucet"
# save uuid and apiKey- Set rules (optional)
bun run script/set-distributor-rules.ts <uuid>- Add to config
"/my/endpoint": {
"distributorId": "<uuid>",
"distributorApiKey": "${MY_API_KEY}",
"dripAmount": 0.1,
"validators": {
"privy-account": {
"jwksUrl": "https://auth.privy.io/api/v1/apps/${PRIVY_APP_ID}/jwks.json",
"appId": "${PRIVY_APP_ID}"
},
"once-only": {}
}
}-
Add secret to .env
-
Restart and test
docker-compose restart backend
bun run script/claim-privy.ts $TOKEN visitor123 /my/endpoint| Name | Config | Description |
|---|---|---|
para-account |
{jwksUrl, verifyUrl?, secretKey?} |
Para JWT |
privy-account |
{jwksUrl, appId} |
Privy JWT |
direct |
true |
No auth, wallet in body |
once-only |
{} |
One claim per wallet |
time-limit |
{period, maxClaims, cooldownHours} |
Rate limiting |
nft-ownership |
{contractAddress, tokenId, rpcUrl} |
ERC1155 gate |
| Script | Usage |
|---|---|
claim.ts |
<jwt> <visitorId> — test Para |
claim-privy.ts |
<jwt> <visitorId> [endpoint] — test Privy |
claim-direct.ts |
<wallet> <visitorId> — test Direct |
create-distributor.ts |
<name> — create QuickNode distributor |
get-distributors.ts |
list all distributors |
set-distributor-rules.ts |
<uuid> — sync rules |
parse-jwt.ts |
<token> — decode JWT |
DATABASE_URL=postgres://user:pass@host:5432/db
CONFIG_PATH=/app/config/config.json
PORT=8080
LOG_LEVEL=info