mirror of
https://github.com/logos-messaging/OpChan.git
synced 2026-01-02 21:03:09 +00:00
@opchan/react
Lightweight React provider and hooks for building OpChan clients on top of @opchan/core.
Install
npm i @opchan/react @opchan/core react react-dom
Quickstart
Basic Usage
import React from 'react';
import { createRoot } from 'react-dom/client';
import { OpChanProvider } from '@opchan/react';
import type { OpChanClientConfig } from '@opchan/core';
const config: OpChanClientConfig = {
ordiscanApiKey: 'YOUR_ORDISCAN_API_KEY',
};
// Optional: bridge your wallet to OpChan
const walletAdapter = {
getAccount() {
// Return { address, walletType: 'bitcoin' | 'ethereum' } or null
return null;
},
onChange(cb) {
// Subscribe to wallet changes; return an unsubscribe function
return () => {};
},
};
function App() {
return (
<OpChanProvider config={config} walletAdapter={walletAdapter}>
{/* your app */}
</OpChanProvider>
);
}
createRoot(document.getElementById('root')!).render(<App />);
(Suggested) With Reown AppKit Integration
Using Reown AppKit for wallet management:
import React from 'react';
import { createRoot } from 'react-dom/client';
import { WagmiProvider } from 'wagmi';
import { AppKitProvider } from '@reown/appkit/react';
import { OpchanWithAppKit } from './providers/OpchanWithAppKit';
// Define your own config for networks, or use our by default (supports Bitcoin and Ethereum)
import { config, appkitConfig } from '@opchan/core';
const opchanConfig = { ordiscanApiKey: 'YOUR_ORDISCAN_API_KEY' };
function App() {
return (
<WagmiProvider config={config}>
<AppKitProvider {...appkitConfig}>
<OpchanWithAppKit config={opchanConfig}>
{/* your app */}
</OpchanWithAppKit>
</AppKitProvider>
</WagmiProvider>
);
}
createRoot(document.getElementById('root')!).render(<App />);
Common usage
import { useForum } from '@opchan/react';
export function NewPostButton({ cellId }: { cellId: string }) {
const { user, content, permissions } = useForum();
const onCreate = async () => {
if (!permissions.canPost) return;
await content.createPost({ cellId, title: 'Hello', content: 'World' });
};
return (
<button disabled={!permissions.canPost || !user.isAuthenticated} onClick={onCreate}>
New post
</button>
);
}
import { useAuth, useUserDisplay } from '@opchan/react';
export function Connect() {
const { currentUser, connect, disconnect, verifyOwnership } = useAuth();
const display = useUserDisplay(currentUser?.address ?? '');
return (
<div>
{currentUser ? (
<>
<span>{display.displayName}</span>
<button onClick={() => verifyOwnership()}>Verify</button>
<button onClick={() => disconnect()}>Disconnect</button>
</>
) : (
<button
onClick={() =>
connect({ address: '0xabc...1234', walletType: 'ethereum' })
}
>
Connect
</button>
)}
</div>
);
}
API
-
Providers
OpChanProvider: High-level provider that constructs anOpChanClientand wires persistence/events.- Props:
config: OpChanClientConfig— core client configuration.walletAdapter?: WalletAdapter— optional bridge to your wallet system.children: React.ReactNode.
- Types:
WalletAdapterAccount:{ address: string; walletType: 'bitcoin' | 'ethereum' }.WalletAdapter:getAccount(): WalletAdapterAccount | nullonChange(cb: (a: WalletAdapterAccount | null) => void): () => void
- Props:
OpchanWithAppKit: Convenience wrapper aroundOpChanProviderthat integrates with Reown AppKit.- Props:
config: OpChanClientConfig— core client configuration.children: React.ReactNode.
- Automatically bridges AppKit wallet connections to OpChan's wallet adapter interface.
- Requires
WagmiProviderandAppKitProviderfrom Reown AppKit as parent providers.
- Props:
ClientProvider: Low-level provider if you constructOpChanClientyourself.- Props:
{ client: OpChanClient; children: React.ReactNode }.
- Props:
-
Hooks
-
useForum()→{ user, content, permissions, network }— convenience bundle of the hooks below. -
useAuth()→ session & identity actions- Data:
currentUser,verificationStatus,isAuthenticated,delegationInfo. - Actions:
connect({ address, walletType }),disconnect(),verifyOwnership(),delegate(duration),delegationStatus(),clearDelegation(),updateProfile({ callSign?, displayPreference? }).
- Data:
-
useContent()→ forum data & actions- Data:
cells,posts,comments,bookmarks,postsByCell,commentsByPost,cellsWithStats,userVerificationStatus,lastSync,pendinghelpers. - Actions:
createCell({ name, description, icon? }),createPost({ cellId, title, content }),createComment({ postId, content }),vote({ targetId, isUpvote }),moderate.{post,unpost,comment,uncomment,user,unuser}(...),togglePostBookmark(post, cellId?),toggleCommentBookmark(comment, postId?),removeBookmark(bookmarkId),clearAllBookmarks(),refresh().
- Data:
-
usePermissions()→ permission checks- Booleans:
canPost,canComment,canVote,canCreateCell,canDelegate. - Functions:
canModerate(cellId),check(action, cellId?) → { allowed, reason },reasons.
- Booleans:
-
useNetwork()→ connection state- Data:
isConnected,statusMessage,issues,canRefresh. - Actions:
refresh()— triggers a light data refresh via core.
- Data:
-
useUIState(key, defaultValue, category?)→ persisted UI state- Returns
[value, setValue, { loading, error? }]. - Categories:
'wizardStates' | 'preferences' | 'temporaryStates'(default'preferences').
- Returns
-
useUserDisplay(address)→ identity details for any address- Returns
{ address, displayName, callSign?, ensName?, ordinalDetails?, verificationStatus, displayPreference, lastUpdated, isLoading, error }. - Backed by a centralized identity cache; updates propagate automatically.
- Returns
-
useClient()→ access the underlyingOpChanClient(advanced use only).
-
Notes
- Identity resolution, verification states, and display preferences are centralized and cached;
useUserDisplayanduseAuth.verifyOwnership()will keep store and local DB in sync. - This package is UI-agnostic; pair with your component library of choice.
License
MIT