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 (
+
+ );
+}
+```
+
+### 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 (