From 028a464412f9f02cacf957b20814d6fedd150b8c Mon Sep 17 00:00:00 2001 From: Danish Arora Date: Wed, 29 Oct 2025 18:28:40 +0530 Subject: [PATCH] chore: update README --- MASTER_PROMPT.md | 139 ++++++++ packages/core/src/index.ts | 2 +- packages/react/README.md | 313 ++++++++++++++++++ packages/react/package.json | 2 +- .../react/src/v1/provider/OpChanProvider.tsx | 4 +- 5 files changed, 456 insertions(+), 4 deletions(-) diff --git a/MASTER_PROMPT.md b/MASTER_PROMPT.md index c5b9e4b..61fbc35 100644 --- a/MASTER_PROMPT.md +++ b/MASTER_PROMPT.md @@ -543,6 +543,72 @@ const popular = [...posts].sort((a, b) => } ``` +### Critical Setup Requirements + +**⚠️ IMPORTANT: Provider Configuration** + +The `OpChanProvider` must be properly configured to avoid the "useClient must be used within ClientProvider" error: + +```tsx +// ✅ CORRECT - Complete setup +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import { OpChanProvider } from '@opchan/react'; +import { Buffer } from 'buffer'; +import App from './App'; + +// Required polyfill for crypto libraries +if (!(window as any).Buffer) { + (window as any).Buffer = Buffer; +} + +createRoot(document.getElementById('root')!).render( + + + +); +``` + +**Common Setup Mistakes:** + +1. **Missing reownProjectId** - Causes wallet connection failures +2. **Missing Buffer polyfill** - Causes crypto library errors +3. **Provider not wrapping all components** - Causes "useClient must be used within ClientProvider" error +4. **Using hooks outside provider** - All `@opchan/react` hooks must be inside `OpChanProvider` + +**Environment Variables:** + +```bash +# .env +VITE_REOWN_SECRET=your_reown_project_id_here +``` + +**Vite Configuration (if using Vite):** + +```typescript +// vite.config.ts +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + define: { + global: 'globalThis', + }, + optimizeDeps: { + include: ['buffer'], + }, +}); +``` + ### Recommended UI Libraries - **shadcn/ui** - Accessible component primitives @@ -743,6 +809,79 @@ export function PostDetail({ postId }: { postId: string }) { } ``` +## Troubleshooting Common Issues + +### Error: "useClient must be used within ClientProvider" + +**Root Cause:** Components using `@opchan/react` hooks are not wrapped by `OpChanProvider`. + +**Solution:** +```tsx +// ❌ WRONG - Hooks used outside provider +function App() { + const { currentUser } = useAuth(); // This will fail + return
Hello
; +} + +// ✅ CORRECT - All hooks inside provider +function App() { + return ( + + + + ); +} + +function MainApp() { + const { currentUser } = useAuth(); // This works + return
Hello
; +} +``` + +### Error: Wallet Connection Fails + +**Root Cause:** Missing or invalid `reownProjectId` in provider config. + +**Solution:** +```tsx +// ❌ WRONG - Missing reownProjectId + + +// ✅ CORRECT - Include reownProjectId + +``` + +### Error: "Buffer is not defined" + +**Root Cause:** Missing Buffer polyfill for crypto libraries. + +**Solution:** +```tsx +import { Buffer } from 'buffer'; + +// Add before rendering +if (!(window as any).Buffer) { + (window as any).Buffer = Buffer; +} +``` + +### Error: Anonymous users can't interact after setting call sign + +**Root Cause:** Verification status not preserved during profile updates. + +**Solution:** +```tsx +// In updateProfile function +const updated: User = { + ...user, + ...identity, + verificationStatus: user.verificationStatus, // Preserve! +}; +``` + ## Testing Your Implementation ### Manual Test Checklist diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index f49db74..bd6e28c 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -42,7 +42,7 @@ export * from './lib/waku/network'; // Export wallet functionality export { EthereumWallet, EthereumWalletHelpers } from './lib/wallet'; -export { wagmiConfig, config } from './lib/wallet/config'; +export { wagmiConfig, config, createWagmiConfig } from './lib/wallet/config'; export * from './lib/wallet/types'; // Primary client API diff --git a/packages/react/README.md b/packages/react/README.md index 7192df1..80ce83e 100644 --- a/packages/react/README.md +++ b/packages/react/README.md @@ -618,6 +618,262 @@ interface OpChanProviderProps { } ``` +## Complete Example App + +Here's a minimal working example that demonstrates all the key patterns: + +### 1. Main Entry Point (`main.tsx`) + +```tsx +import { createRoot } from 'react-dom/client'; +import { OpChanProvider } from '@opchan/react'; +import { Buffer } from 'buffer'; +import App from './App'; + +// Required polyfill +if (!(window as any).Buffer) { + (window as any).Buffer = Buffer; +} + +createRoot(document.getElementById('root')!).render( + + + +); +``` + +### 2. App Component (`App.tsx`) + +```tsx +import { useForum } from '@opchan/react'; + +export default function App() { + const { user, content, permissions, network } = useForum(); + + // Wait for initial data load + if (!network.isHydrated) { + return
Loading...
; + } + + return ( +
+
+
+ {!user.currentUser ? ( + + ) : ( + + )} +
+
+ ); +} +``` + +### 3. Authentication Component (`AuthPrompt.tsx`) + +```tsx +import { useAuth } from '@opchan/react'; + +export function AuthPrompt() { + const { connect, startAnonymous } = useAuth(); + + return ( +
+

Welcome to OpChan

+

Choose how you'd like to participate:

+ +
+ + +
+
+ ); +} +``` + +### 4. Header Component (`Header.tsx`) + +```tsx +import { useAuth } from '@opchan/react'; + +export function Header() { + const { currentUser, disconnect, verificationStatus } = useAuth(); + + return ( +
+
+

OpChan

+ + {currentUser ? ( +
+ + {currentUser.displayName} + {verificationStatus === 'anonymous' && ' (Anonymous)'} + {verificationStatus === 'ens-verified' && ' (ENS)'} + + +
+ ) : null} +
+
+ ); +} +``` + +### 5. Forum Interface (`ForumInterface.tsx`) + +```tsx +import { useContent, usePermissions } from '@opchan/react'; + +export function ForumInterface() { + const { cells, posts, createPost } = useContent(); + const { canPost, canCreateCell } = usePermissions(); + + return ( +
+
+

Cells

+ {canCreateCell && ( + + )} +
+ +
+ {cells.map(cell => ( + + ))} +
+ +
+

Recent Posts

+
+ {posts.slice(0, 10).map(post => ( + + ))} +
+
+
+ ); +} +``` + +### 6. Cell Card Component (`CellCard.tsx`) + +```tsx +import { useContent } from '@opchan/react'; + +export function CellCard({ cell }) { + const { postsByCell } = useContent(); + const cellPosts = postsByCell[cell.id] || []; + + return ( +
+

{cell.name}

+

{cell.description}

+
+ {cellPosts.length} posts +
+
+ ); +} +``` + +### 7. Post Card Component (`PostCard.tsx`) + +```tsx +import { useUserDisplay } from '@opchan/react'; + +export function PostCard({ post }) { + const { displayName, callSign, ensName } = useUserDisplay(post.author); + + return ( +
+
+ + {displayName} + {callSign && ` (#${callSign})`} + {ensName && ` (${ensName})`} + + + {new Date(post.timestamp).toLocaleDateString()} + +
+

{post.title}

+

{post.content}

+
+ ); +} +``` + +### 8. Package.json Dependencies + +```json +{ + "dependencies": { + "@opchan/react": "^1.1.0", + "@opchan/core": "^1.0.0", + "react": "^18.3.0", + "react-dom": "^18.3.0", + "buffer": "^6.0.3" + }, + "devDependencies": { + "@types/react": "^18.3.0", + "typescript": "^5.3.0", + "vite": "^5.0.0", + "@vitejs/plugin-react": "^4.0.0" + } +} +``` + +### 9. Vite Configuration (`vite.config.ts`) + +```typescript +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + define: { + global: 'globalThis', + }, + optimizeDeps: { + include: ['buffer'], + }, +}); +``` + +### 10. Environment Variables (`.env`) + +```bash +VITE_REOWN_SECRET=your_reown_project_id_here +``` + ## Best Practices 1. **Use `useForum()` for most cases** - Cleaner than importing individual hooks @@ -647,6 +903,63 @@ interface OpChanProviderProps { ## Troubleshooting +### Error: "useClient must be used within ClientProvider" + +**Root Cause:** Components using `@opchan/react` hooks are not wrapped by `OpChanProvider`. + +**Solution:** +```tsx +// ❌ WRONG - Hooks used outside provider +function App() { + const { currentUser } = useAuth(); // This will fail + return
Hello
; +} + +// ✅ CORRECT - All hooks inside provider +function App() { + return ( + + + + ); +} + +function MainApp() { + const { currentUser } = useAuth(); // This works + return
Hello
; +} +``` + +### Error: Wallet Connection Fails + +**Root Cause:** Missing or invalid `reownProjectId` in provider config. + +**Solution:** +```tsx +// ❌ WRONG - Missing reownProjectId + + +// ✅ CORRECT - Include reownProjectId + +``` + +### Error: "Buffer is not defined" + +**Root Cause:** Missing Buffer polyfill for crypto libraries. + +**Solution:** +```tsx +import { Buffer } from 'buffer'; + +// Add before rendering +if (!(window as any).Buffer) { + (window as any).Buffer = Buffer; +} +``` + ### Anonymous users can't interact after setting call sign - Ensure `mapVerificationStatus` includes `ANONYMOUS` case - Check that `updateProfile` preserves `verificationStatus` diff --git a/packages/react/package.json b/packages/react/package.json index 496b7e2..7a57a9a 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@opchan/react", - "version": "1.1.2", +"version": "1.1.2", "private": false, "description": "React contexts and hooks for OpChan built on @opchan/core", "main": "dist/index.js", diff --git a/packages/react/src/v1/provider/OpChanProvider.tsx b/packages/react/src/v1/provider/OpChanProvider.tsx index cbe34e3..b58b238 100644 --- a/packages/react/src/v1/provider/OpChanProvider.tsx +++ b/packages/react/src/v1/provider/OpChanProvider.tsx @@ -1,10 +1,9 @@ import React from "react"; -import { OpChanClient, type OpChanClientConfig } from "@opchan/core"; +import { OpChanClient, type OpChanClientConfig, createWagmiConfig } from "@opchan/core"; import { ClientProvider } from "../context/ClientContext"; import { StoreWiring } from "./StoreWiring"; import { WagmiProvider } from "wagmi"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { wagmiConfig } from "@opchan/core"; export interface OpChanProviderProps { config: OpChanClientConfig; @@ -30,6 +29,7 @@ export const OpChanProvider: React.FC = ({ children, }) => { const [client] = React.useState(() => new OpChanClient(config)); + const [wagmiConfig] = React.useState(() => createWagmiConfig(config.reownProjectId)); return (