# OpChan - Decentralized Forum Application A production-ready decentralized forum built on the Waku protocol with Ethereum wallet and anonymous session support. OpChan enables communities to create discussion boards (cells), share content, and engage in threaded conversations without centralized control. ## ๐ŸŒŸ Features ### Authentication & Identity - โœ… **Multiple Auth Modes** - Anonymous sessions (browser-only, no wallet required) - Ethereum wallet connection (MetaMask, WalletConnect, Coinbase Wallet) - ENS verification for premium features - โœ… **Key Delegation** - One-time wallet signature, then browser signs all messages - โœ… **Call Signs** - Custom usernames for both wallet and anonymous users - โœ… **Identity Resolution** - Automatic ENS resolution and avatar display ### Content & Engagement - โœ… **Cells (Forums)** - ENS holders create and moderate discussion boards - โœ… **Posts & Comments** - Threaded discussions with markdown support - โœ… **Voting System** - Upvote/downvote with verification-weighted relevance - โœ… **Relevance Scoring** - Multi-factor algorithm prioritizing verified users - โœ… **Bookmarks** - Local-only bookmarking of posts and comments - โœ… **Moderation** - Cell-based moderation without global censorship ### Technical - โœ… **Decentralized Messaging** - Waku protocol for P2P content distribution - โœ… **Local-First** - IndexedDB caching with network sync - โœ… **Cryptographic Verification** - Ed25519 signatures on all messages - โœ… **Real-Time Updates** - Live content updates via Waku subscriptions ## ๐Ÿš€ Quick Start ### Installation ```bash # Clone the repository git clone https://github.com/status-im/opchan.git cd opchan # Install dependencies npm install # Build packages npm run build # Start development server cd app npm run dev ``` ### Environment Setup Create `app/.env`: ```bash VITE_REOWN_SECRET=your_reown_project_id ``` Get a Reown (formerly WalletConnect) project ID from https://cloud.reown.com ## ๐Ÿ“– Usage Guide ### For End Users #### Getting Started - Anonymous Mode 1. **Visit the App** - No wallet required! 2. **Click "Connect"** in the header 3. **Select "Continue Anonymously"** 4. **Set a Call Sign** - From header dropdown menu 5. **Start Engaging** - Post, comment, and vote immediately #### Getting Started - Wallet Mode 1. **Click "Connect"** and choose your wallet 2. **Complete Setup Wizard**: - Step 1: Connect wallet - Step 2: Verify ENS ownership (optional) - Step 3: Delegate browser key (recommended) 3. **Create or Join Cells** 4. **Engage with Content** #### Permission Levels | Action | Anonymous | Wallet Connected | ENS Verified | |--------|-----------|------------------|--------------| | View Content | โœ… | โœ… | โœ… | | Upvote/Downvote | โœ… | โœ… | โœ… | | Comment | โœ… | โœ… | โœ… | | Create Posts | โœ… | โœ… | โœ… | | Create Cells | โŒ | โŒ | โœ… | | Moderate | โŒ | โŒ | โœ… (Own cells) | | Set Call Sign | โœ… | โœ… | โœ… | ### For Developers #### Building with @opchan/react See `packages/react/README.md` for complete API documentation. **Basic Example:** ```tsx import { useForum } from '@opchan/react'; export function MyForumComponent() { const { user, content, permissions } = useForum(); const handleCreatePost = async () => { if (!permissions.canPost) return; const post = await content.createPost({ cellId: 'cell-id', title: 'Hello World', content: 'My first post!' }); if (post) { console.log('Post created:', post.id); } }; return (
{user.currentUser ? ( ) : ( <> )}
); } ``` ## ๐Ÿ—๏ธ Architecture ### High-Level Architecture ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ React Application โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ useAuth โ”‚ โ”‚ useContent โ”‚ โ”‚ usePermissions โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ @opchan/react โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ @opchan/core โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ OpChanClient โ”‚โ”€โ”€โ”‚ ForumActionsโ”‚ โ”‚ DelegationManagerโ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ LocalDB โ”‚ โ”‚ MessageManager โ”‚ โ”‚ Crypto Utilsโ”‚ โ”‚ โ”‚ โ”‚ (IndexedDB)โ”‚ โ”‚ (Waku) โ”‚ โ”‚ (ed25519) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### Authentication System ``` โ”Œโ”€ Anonymous Flow โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ 1. startAnonymous() โ”‚ โ”‚ 2. Generate browser keypair (ed25519) โ”‚ โ”‚ 3. Store as AnonymousDelegation (sessionId + keys) โ”‚ โ”‚ 4. User can interact immediately โ”‚ โ”‚ 5. Optional: Set call sign โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”Œโ”€ Wallet Flow โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ 1. connect() โ†’ Wallet connection via wagmi โ”‚ โ”‚ 2. verifyOwnership() โ†’ Check for ENS (optional) โ”‚ โ”‚ 3. delegate('7days') โ†’ Wallet signs browser key auth โ”‚ โ”‚ 4. Browser signs all subsequent messages โ”‚ โ”‚ 5. Messages include delegationProof (wallet signature) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### Message Flow ``` Create Content โ†’ Sign with Browser Key โ†’ Broadcast to Waku โ†’ Peers Verify โ†’ Store in Local Cache โ†“ โ†“ โ†“ โ†“ โ†“ User Action DelegationManager MessageManager MessageValidator LocalDatabase โ†“ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ Wallet Users: Anonymous Users: Verify delegationProof Verify session ID format (wallet signature) (UUID pattern check) ``` ### Data Layer - **IndexedDB Stores**: cells, posts, comments, votes, moderations, userIdentities, delegation, bookmarks - **Caching Strategy**: Write-through cache with optimistic updates - **Sync Strategy**: Waku messages update local cache, triggers React re-renders - **Persistence**: All user data persisted locally, nothing on centralized servers ## ๐ŸŽจ UI/UX Design ### Design System - **Theme**: Cyberpunk-inspired dark theme - **Components**: shadcn/ui (Radix UI + Tailwind CSS) - **Typography**: Monospace fonts for technical aesthetic - **Colors**: Cyan accent, dark backgrounds, high contrast ### Key Components - `
` - Navigation, auth status, network indicator - `` - 3-step onboarding flow - `` - Call sign configuration - `` - User identity with badges (ENS, Call Sign, Anonymous) - `` - Visual relevance score display - `` & `` - Rich text support ## ๐Ÿ” Security Model ### Cryptographic Trust Chain ``` Wallet Users: Wallet Private Key (user device) โ†’ Signs delegation authorization โ†’ Authorizes Browser Private Key โ†’ Browser signs all messages โ†’ Messages include delegationProof โ†’ Peers verify wallet signature on delegationProof Anonymous Users: Browser Private Key (generated locally) โ†’ Signs all messages directly โ†’ No wallet proof required โ†’ Peers verify session ID format โ†’ Lower trust/relevance weight ``` ### Security Guarantees - โœ… All messages cryptographically signed (ed25519) - โœ… Message authorship verifiable by any peer - โœ… Delegation proofs prevent impersonation - โœ… Session IDs prevent anonymous user collisions - โœ… Browser keys never leave device - โœ… No centralized authentication server ### Spam Prevention - Anonymous users have lower relevance weights - Cell admins can moderate any content - Moderated content hidden by default - Time decay reduces old content relevance ## ๐Ÿ“Š Relevance Algorithm Content is scored based on multiple factors: ``` Base Score (Post: 10, Comment: 5, Cell: 15) + Engagement (upvotes ร— 1, comments ร— 0.5) + Author Verification Bonus (ENS: +25%, Wallet: +10%) + Verified Upvote Bonus (+0.1 per verified upvoter) + Verified Commenter Bonus (+0.05 per verified commenter) ร— Time Decay (exponential, ฮป=0.1) ร— Moderation Penalty (0.5 if moderated) = Final Relevance Score ``` Anonymous users: - Get **no verification bonus** - Their votes count but with **no verified upvote bonus** to others - Can still create popular content through engagement ## ๐Ÿ› ๏ธ Development ### Project Structure ``` app/ โ”œโ”€โ”€ src/ โ”‚ โ”œโ”€โ”€ components/ โ”‚ โ”‚ โ”œโ”€โ”€ ui/ # shadcn/ui components + custom โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ wallet-wizard.tsx # 3-step onboarding โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ author-display.tsx # User identity display โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ inline-callsign-input.tsx # Anonymous call sign โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ ... โ”‚ โ”‚ โ”œโ”€โ”€ Header.tsx # Main navigation โ”‚ โ”‚ โ”œโ”€โ”€ PostList.tsx # Post feed โ”‚ โ”‚ โ”œโ”€โ”€ PostDetail.tsx # Single post view โ”‚ โ”‚ โ”œโ”€โ”€ CommentCard.tsx # Comment display โ”‚ โ”‚ โ””โ”€โ”€ ... โ”‚ โ”œโ”€โ”€ pages/ โ”‚ โ”‚ โ”œโ”€โ”€ Dashboard.tsx # Landing page โ”‚ โ”‚ โ”œโ”€โ”€ CellPage.tsx # Cell view โ”‚ โ”‚ โ”œโ”€โ”€ PostPage.tsx # Post view โ”‚ โ”‚ โ”œโ”€โ”€ ProfilePage.tsx # User profile โ”‚ โ”‚ โ””โ”€โ”€ ... โ”‚ โ”œโ”€โ”€ hooks/ โ”‚ โ”‚ โ””โ”€โ”€ index.ts # Re-exports from @opchan/react โ”‚ โ””โ”€โ”€ utils/ โ”‚ โ”œโ”€โ”€ sorting.ts # Content sorting utilities โ”‚ โ””โ”€โ”€ ... โ””โ”€โ”€ package.json ``` ### Building from Source ```bash # Build all packages npm run build # Build individual packages cd packages/core && npm run build cd packages/react && npm run build cd app && npm run build # Development mode (with hot reload) cd app && npm run dev ``` ### Testing ```bash # Run tests npm test # Run specific tests cd packages/core && npm test ``` ## ๐ŸŒ Deployment ### Build for Production ```bash cd app npm run build # Output in app/dist/ ``` ### Deploy to Vercel/Netlify The app is a static SPA that can be deployed to any static hosting: ```json // vercel.json { "routes": [ { "handle": "filesystem" }, { "src": "/(.*)", "dest": "/index.html" } ] } ``` Environment variables required: - `VITE_REOWN_SECRET` - Reown project ID for WalletConnect ## ๐Ÿ“š Key Learnings & Implementation Notes ### Why Anonymous Support? From FURPS requirement #18: "Anonymous users can upvote, comments and post" Benefits: - **Lower barrier to entry** - Users can try before connecting wallet - **Privacy-preserving** - No on-chain footprint required - **Better adoption** - Immediate engagement without Web3 knowledge - **Flexible identity** - Users can upgrade to wallet later ### Why Key Delegation? - **UX Problem**: Signing every message with wallet is tedious - **Solution**: Wallet signs once to authorize browser keys - **Result**: Seamless posting/commenting without wallet prompts - **Security**: Delegation expires (7-30 days), can be revoked anytime ### Why Local-First? - **Resilience**: App works offline, syncs when online - **Performance**: Instant UI updates, background network sync - **Privacy**: All data local until shared on network - **Decentralization**: No centralized API dependency ## ๐Ÿ› Common Issues & Solutions ### Issue: Anonymous user loses session after interaction **Solution**: Ensure wallet sync effect preserves anonymous users (check `verificationStatus !== ANONYMOUS`) ### Issue: Call sign update clears anonymous session **Solution**: Preserve `verificationStatus` in `updateProfile` and add `ANONYMOUS` case to `mapVerificationStatus` ### Issue: Permissions show false for anonymous users **Solution**: Update permission checks to include `isAnonymous` condition ### Issue: Wizard loops anonymous users through verification steps **Solution**: Close wizard immediately after anonymous selection (check `verificationStatus` in `handleStepComplete`) ## ๐Ÿ”ฎ Future Enhancements - [ ] Multi-wallet support (Bitcoin, Solana) - [ ] ENS avatar display improvements - [ ] Content persistence strategies - [ ] Rate limiting for anonymous users - [ ] Advanced moderation tools - [ ] Search functionality - [ ] Notifications system - [ ] Mobile app (React Native) ## ๐Ÿค Contributing ### Development Workflow 1. **Fork** the repository 2. **Create branch**: `git checkout -b feature/my-feature` 3. **Make changes** following existing patterns 4. **Test thoroughly** - especially authentication flows 5. **Build all packages**: `npm run build` from root 6. **Commit**: `git commit -m "feat: add my feature"` 7. **Push**: `git push origin feature/my-feature` 8. **Open PR** with description ### Code Style - TypeScript strict mode - No `any` types (use proper typing) - Functional components with hooks - Tailwind CSS for styling - shadcn/ui component patterns ## ๐Ÿ“„ License MIT ## ๐Ÿ™ Acknowledgments Built on: - [Waku Protocol](https://waku.org) - Decentralized messaging - [Viem](https://viem.sh) - Ethereum interactions - [Wagmi](https://wagmi.sh) - React hooks for Ethereum - [shadcn/ui](https://ui.shadcn.com) - Component library - [Tailwind CSS](https://tailwindcss.com) - Styling --- **OpChan - Decentralized communities built on cryptographic trust, not corporate servers** ๐ŸŒ