Contributing
Run Opentip locally, self-host, or contribute to the open-source codebase.
Prerequisites
- Node.js 20 or later
- npm (workspaces)
- PostgreSQL database (local or cloud)
- Foundry (for smart contract development)
- Git
Clone & install
git clone https://github.com/opentiphq/opentip.git
cd opentip
npm installThis installs dependencies for both the frontend and indexer via npm workspaces.
Environment variables
Copy the example env file and fill in your values:
cd frontend
cp .env.example .envFrontend variables
| Variable | Required | Description |
|---|---|---|
| DATABASE_URL | Yes | PostgreSQL connection string |
| GITHUB_ID | Yes | GitHub OAuth app client ID |
| GITHUB_SECRET | Yes | GitHub OAuth app client secret |
| NEXTAUTH_SECRET | Yes | Session encryption key (random string) |
| NEXTAUTH_URL | Yes | Base URL (http://localhost:3000 for dev) |
| NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID | Yes | Reown/WalletConnect project ID |
| NEXT_PUBLIC_CHAIN | Yes | baseSepolia or base |
| NEXT_PUBLIC_BASE_SEPOLIA_CONTRACT | Yes | Contract address on Base Sepolia |
| NEXT_PUBLIC_BASE_CONTRACT | For mainnet | Contract address on Base mainnet |
| PRIVATE_KEY | Yes | Owner wallet private key (admin transactions) |
| REGISTRAR_PRIVATE_KEY | Yes | Registrar signer key (EIP-712 registration) |
| OWNER_ADDRESS | Yes | Owner wallet address (admin role check) |
| NEXT_PUBLIC_OWNER_ADDRESS | Yes | Owner address (client-side) |
| RESEND_API_KEY | Optional | Resend API key (signup verification and password reset emails) |
| RESEND_FROM | Optional | From address for emails |
| AZURE_STORAGE_ACCOUNT | Optional | Azure Blob Storage account (image uploads) |
| AZURE_STORAGE_KEY | Optional | Azure Blob Storage key |
| GROQ_API_KEY | Optional | Groq API key (AI-generated repo summaries) |
| GITHUB_TOKEN | Optional | GitHub token (higher API rate limits) |
| NEXT_PUBLIC_CDP_PROJECT_ID | Yes | CDP project ID (Opentip Smart Wallet) |
| JWT_PRIVATE_KEY / JWT_KID | Yes | RS256 keypair for CDP custom auth (served at /.well-known/jwks.json) |
| CDP_JWT_ISSUER / CDP_JWT_AUDIENCE | Yes | JWT issuer and audience for Smart Wallet auth |
| ALCHEMY_RPC_URL | Optional | Alchemy RPC URL, server-only (wallet history deposits + token legs; free tier covers ~125k opens/mo; falls back to tips-only without it) |
| NEXT_PUBLIC_RPC_URL | Optional | Public RPC for chain reads. Payout ETH checks fail closed when it is empty. |
| NOTIFICATION_SECRET | For push | Same value on the frontend and the indexer. POST /api/notifications/send rejects calls that do not send it as x-notification-secret. |
| VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY | For push | Server VAPID key pair used to send web push |
| NEXT_PUBLIC_VAPID_PUBLIC_KEY | For push | Public VAPID key the browser uses when subscribing. Users see "VAPID key not configured" when it is missing. |
| CDP_PAYMASTER_URL | Optional | Server-only paymaster URL. When set, Smart Wallet gas can be sponsored (up to 10 transactions per account per UTC day). |
| CDP_API_KEY_ID / CDP_API_KEY_SECRET | For Smart Wallet | Read by the Coinbase SDK when wallet linking constructs CdpClient() with no arguments, to confirm the address belongs to the caller. |
Admin note — Smart Wallet setup: the JWKS endpoint must return 200 JSON (never a redirect) or wallet creation fails to parse it. When testing locally, expose dev with a public tunnel and set that URL in the CDP portal's Custom auth tab; the portal cannot reach localhost. Keep the same private key across environments so signatures validate.
Indexer variables
| Variable | Description |
|---|---|
| DATABASE_URL | Same PostgreSQL connection as frontend |
| CONTRACT_ADDRESS | Deployed Opentip contract address |
| RPC_URL | Alchemy RPC endpoint (e.g. https://base-mainnet.g.alchemy.com/v2/YOUR_KEY) |
| START_BLOCK | Block to start scanning from (if no checkpoint) |
| POLL_MS | Poll interval in ms (default 12000) |
| CHAIN | base for Base mainnet. Any other value, including unset, means Base Sepolia. The indexer does not read NEXT_PUBLIC_CHAIN. |
| GETLOGS_RANGE | Blocks per eth_getLogs request (default 10) |
| NOTIFICATION_SECRET | Same value as the frontend. Sent as x-notification-secret when the indexer asks the app to push. |
| NOTIFICATION_API_URL | Push endpoint. Defaults to https://opentip.tech/api/notifications/send |
Database setup
cd frontend
npx prisma migrate dev
npx prisma generateThis creates all tables in your PostgreSQL database. The Prisma schema is shared between the frontend and indexer.
Running locally
Frontend
cd frontend
npm run devStarts the Next.js dev server at http://localhost:3000
Indexer
cd indexer
npx prisma generate
npx tsx src/index.tsStarts the event indexer polling loop
Smart contract development
cd contracts
forge install
forge testThe contract has 36 tests covering registration, tipping, claiming, admin functions, and edge cases. Run forge test -vvv for verbose output.
Deploy to Base Sepolia:
forge script script/Deploy.s.sol:Deploy \
--rpc-url baseSepolia \
--broadcast \
--verifyTesting checklist
- Sign up with GitHub and email/password
- Link a wallet on Base Sepolia
- Register a repo (verify ownership → sign → on-chain tx)
- Send a USDC tip (approve + receiveTip)
- Send an ETH tip (payable receiveTipEth)
- OAR tipping is coming soon. The token menu shows "OAR tipping coming soon" and keeps the current token.
- Press Claim all as the payout address holder
- Set a display name
- Edit profile (bio, social links, pfp, header)
- Test forgot password flow
- View AI-generated repo summary on About tab
- Add/edit links on dashboard repos page
- Browse repos, activity, leaderboard pages
- Admin: pause/unpause, set fee, manage admins
Production deployment
Frontend (Vercel)
- Set the frontend environment variables from the table above in the Vercel dashboard
- Set NEXTAUTH_URL to your production domain
- Deploy from the main branch
Indexer (Azure Container Apps)
- Build Docker image from the indexer directory
- Push to a container registry
- Deploy to Azure Container Apps with the indexer environment variables from the table above
Contract (Base mainnet)
- Deploy via Foundry with mainnet RPC
- Verify on Basescan
- Update all env vars to mainnet addresses
- Update NEXT_PUBLIC_CHAIN to "base"
License
Opentip is open-source software. The smart contract is MIT licensed. See the repository for full license details.